- Shell 81.3%
- Makefile 18.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
CI / Contract drift (push) Successful in 4s
**What changes.** rasterhub.com now runs `17.0.0+gitea-1.22.0`; the vendored spec was pinned at `16.0.3`. The three spec files are `make fetch` + `make regenerate` against the live swagger, nothing hand-written. README and GAPS.md now state 17.0.0 as the vendored version, and GAPS.md gains entry 10 for the job log format switch.
No path, operation or schema was removed, and no schema gained a required field. Six operations are new:
```
GET /repos/{owner}/{repo}/actions/jobs/{job_id}
POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun
POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun
PUT /repos/{owner}/{repo}/issues/{index}/lock
DELETE /repos/{owner}/{repo}/issues/{index}/lock
GET /user/actions/secrets
```
Two new schemas, `ActionRunJobStep` and `IssueLockOption`. `ActionRunJob` gains `html_url` and `steps`.
Existing operations that moved:
- `GET actions/jobs/{job_id}/logs` gains `step`, `q`, `qi` and `format` query parameters and a second response media type, `application/x-ndjson`.
- Workflow dispatch gains a documented 400. Compare gains `verification` and `files` query parameters. Team member `PUT` gains a 409.
- `EditDeadlineOption.due_date` and `CreateUserOption.email` are no longer required. `MigrateRepoOptions.service` gains `bitbucketdc`.
- Some "Deprecated" prose in descriptions became `x-deprecated: true`.
`versionFloor` stays at `7.0.0`. 17.0.0 is a capability ceiling a consumer detects at runtime, not a new floor.
**Evidence.** Probed on rasterhub.com at 17.0.0 on 2026-10-16. `GET actions/jobs/104670` on rasterstate/fjord-ios returns 200 with `steps[]` (`number`, `name`, `status`, `started`, `stopped`), `html_url` and `attempt`. `GET /user/actions/secrets` returns 200. Run rerun answers 204 once a run has finished and 400 before that; job rerun reruns the job and every job that depends on it. Job logs return `text/plain` whatever the `Accept` order and `application/x-ndjson` only under `format=ndjson` (GAPS.md entry 10). None of these paths are in the 16.0.3 spec this replaces, which is the evidence a consumer's capability table needs for them. `make check` passes locally.
This is not a no-op for a consumer that generates exhaustive Swift enums. The second log media type and the new dispatch 400 each add a case to a generated response enum, so Fjord needs three small `switch` changes when it moves its submodule pointer. Those land with the pointer bump in fjord-ios, not here.
**Not verified.** `PUT` and `DELETE issues/{index}/lock` were not exercised for this PR, since both mutate a live issue. fj does not generate from this contract yet, so nothing was checked on its side.
Reviewed-on: #8
|
||
| .forgejo/workflows | ||
| patches | ||
| scripts | ||
| .gitattributes | ||
| .gitignore | ||
| CODEOWNERS | ||
| GAPS.md | ||
| LICENSE | ||
| Makefile | ||
| NOTICE | ||
| openapi.v1.yaml | ||
| openapi.yaml | ||
| OPERATIONS.md | ||
| policy.yaml | ||
| README.md | ||
| swagger.v1.json | ||
forgejo-api-contract
The shared API contract for Forgejo clients built at Raster & State. One pinned spec, one operational policy, consumed by both Fjord (Swift / iOS) and fj (Rust CLI).
This repo is the single source of truth for:
- which Forgejo API version the clients target,
- the OpenAPI 3.0 document they generate code from,
- the operational policy (retry budget, body cap, redaction list, version floor) the clients are expected to honor in lockstep.
It contains no compiled code. Each consumer vendors this repo as a git submodule and runs its own language-specific code generation.
What's here
| Path | Role |
|---|---|
swagger.v1.json |
Upstream Forgejo spec, vendored at a pinned version (Forgejo 17.0.0, Gitea 1.22-compatible). |
openapi.v1.yaml |
Raw OpenAPI 3.0 conversion of the swagger via swagger2openapi. Committed so consumers don't need Node to build. |
openapi.yaml |
The patched spec: openapi.v1.yaml plus policy.yaml's requiredOverrides: and requestBodyOverrides: applied. This is the document consumers generate from. |
policy.yaml |
Operational policy shared by every consumer: version floor, retry table, body cap, redaction allowlist, optionality overrides, required-field overrides. |
patches/ |
Reserved for future Redocly-style overlays. Empty today; the simple required: rewrites are driven from policy.yaml. |
scripts/apply-required-overrides.sh |
Reads policy.yaml's requiredOverrides:, applies them to openapi.v1.yaml. Validates each schema and field exists before writing. |
scripts/apply-requestbody-overrides.sh |
Reads policy.yaml's requestBodyOverrides:, marks each named operation's request body required: true. Runs after the required-field pass and writes openapi.yaml. |
scripts/generate-policy-swift.sh |
Consumer-side convenience: renders policy.yaml into a Swift constants file. Invoked by Fjord with its own output path. A generate-policy-rs.sh will join it when fj adopts the contract. |
Makefile |
Contract-level targets: fetch, convert, patch, check. |
OPERATIONS.md |
Re-vendor cadence, patch hygiene, ownership, breaking-change protocol. |
GAPS.md |
Live-verified divergences between the vendored spec and real deployed servers (version skew, undocumented semantics, missing webhook surfaces). |
Contract-level commands
make help # list targets
make fetch # re-download swagger.v1.json from rasterhub.com
make convert # rerun swagger2openapi (writes openapi.v1.yaml)
make patch # apply policy.yaml overrides (writes openapi.yaml)
make regenerate # convert + patch
make check # fail if either committed spec drifts (CI gate)
make check is this repo's CI gate. Language-specific code generation
(Swift types, Rust constants) is each consumer's responsibility and runs
in the consumer's own CI.
How consumers use this
Each consumer adds this repo as a git submodule, points its code generator
at openapi.yaml, and runs its own policy.yaml-to-constants step:
- Fjord vendors the submodule at
Fjord/Tools/forgejo-contract/, runsswift-openapi-generatoragainstopenapi.yaml, and runsscripts/generate-policy-swift.shto produceForgejoPolicyconstants. - fj (planned) will vendor the submodule, generate Rust models, and run
a
generate-policy-rs.shfor the matchingpolicy.rsconstants.
Prerequisites
node24.x (forswagger2openapi, invoked vianpx --yes).yq, Mike Farah's Go implementation (not the Pythonyqwrapper). The patching script refuses to run on the wrong flavor.make,bash,curl.
Re-vendoring
See OPERATIONS.md for the cadence, the patch-hygiene rules, and the
major-version bump protocol.
versionFloor vs spec version
policy.yaml's versionFloor.semver is the minimum Forgejo major version
clients agree to talk to (7.0.0, set by fj's pre-existing version-warning
baseline). It is independent of the spec version vendored in
swagger.v1.json (Forgejo 17.0.0 today); the spec floats forward, the floor
changes only when both clients agree to drop compatibility with older
servers.