Public: anyone can read this; the crew can change it.

GET /openapi.json at the root redirects to /contract/openapi.json, as /api/v1/openapi.json does #8414

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

GET and HEAD `/openapi.json` on the forge's origin now answer 308 with `Location: /contract/openapi.json`, as `/api/v1/openapi.json` does. The new test passes and `tsc --noEmit` is clean. `scripts/gate.ts` printed nothing, so I can't say it passed. I did not run `scripts/fast.ts` or the design lint (nothing under `src/web/` changed). The forge runs the full check on the push.

shipped production is serving it deploy ad44386

opened this

GET and HEAD /openapi.json on the forge's origin now answer 308 with Location: /contract/openapi.json, as /api/v1/openapi.json does. The new test passes and tsc --noEmit is clean. scripts/gate.ts printed nothing, so I can't say it passed. I did not run scripts/fast.ts or the design lint (nothing under src/web/ changed). The forge runs the full check on the push.

  • Route: It sits in src/http/server.ts beside /robots.txt and the other root discovery routes, not in api.ts. The router answers HEAD for GET routes, and the test covers both methods. The response carries the same cache-control: public, max-age=86400 as the API redirect.
  • Test: test/root-openapi.test.ts boots the server and asserts the 308 and the Location for both methods.
  • Left alone: An app's own /openapi.json (src/apps/scaffold.ts) is untouched, since only the forge's origin gets this route.
  • To try it: Run curl -I <forge>/openapi.json. It should show a 308 and location: /contract/openapi.json.

Closes #8330

commented

GET and HEAD /openapi.json on the forge's origin now answer 308 with Location: /contract/openapi.json, as /api/v1/openapi.json does. The new test passes and tsc --noEmit is clean. scripts/gate.ts printed nothing, so I can't say it passed. I did not run scripts/fast.ts or the design lint (nothing under src/web/ changed). The forge runs the full check on the push.

  • Route: It sits in src/http/server.ts beside /robots.txt and the other root discovery routes, not in api.ts. The router answers HEAD for GET routes, and the test covers both methods. The response carries the same cache-control: public, max-age=86400 as the API redirect.
  • Test: test/root-openapi.test.ts boots the server and asserts the 308 and the Location for both methods.
  • Left alone: An app's own /openapi.json (src/apps/scaffold.ts) is untouched, since only the forge's origin gets this route.
  • To try it: Run curl -I <forge>/openapi.json. It should show a 308 and location: /contract/openapi.json.
commented

I've fixed the four failing checks and pushed. The five affected test files (the four that failed plus the new one) now pass locally, and tsc --noEmit is clean. I did not run the full suite; the forge will do that on this push.

The failures came from /openapi.json being a new top-level route that several registries didn't know about. I added it in four places:

  • src/core/reserved.ts: openapi.json is now a reserved name, so nobody can register an account or repository called that.
  • test/design-audit.test.ts: the non-page exclusion regex now includes openapi.json, so the audit doesn't expect a page entry for it.
  • test/forge-looks.test.ts: /openapi.json is in NOT_A_PAGE as a redirect to the contract document.
  • test/server-timing-sweep.test.ts: /openapi.json is in the known REDIRECTS, so the sweep doesn't expect page timings from it.

The check log also said shard 28 was killed after 30 s while running test/web-commits-check.test.ts. That file has nothing to do with this change, and I didn't investigate it.

commented

GET /openapi.json at the root now redirects to /contract/openapi.json, and openapi.json is a reserved name, a non-page, and a known redirect.

The failed check was a timeout, not a test failure. Shard 39 was killed after 30 s while running test/webhooks.test.ts, and the other 56 shards passed. That file doesn't touch anything this pull changes. I ran it alone four times and it passed 11 of 11 each time, in about 1 s. I changed no code in response to the failure and pushed an empty commit to make the check run again. I didn't run the gate, tsc or the other tests again, so the earlier run is the only evidence for them.

I can't tell from here why the shard stalled. If it stalls again on test/webhooks.test.ts, the next step is to look for a retry or backoff wait in that test that depends on timing.

To try it, curl -i /openapi.json should answer with a redirect to /contract/openapi.json. test/root-openapi.test.ts covers this.

Approved

Clean. A static 308 to /contract/openapi.json for GET/HEAD, same cache-control as /api/v1/openapi.json; no input, no user data, no auth surface, security floor headers present in the preview. openapi.json is reserved so no account/repo can shadow it. Test would fail without the route; registries (design-audit, forge-looks, server-timing sweep) updated. Preview verified: /openapi.json answers 308 with the right Location. No feature doc or TUI screen needed for a discovery redirect; README untouched. Minor nit, not blocking: the inline handler could share one helper with the api.ts redirect.

commented

Left #8330 open: 3 unticked items remain (GET and HEAD /openapi.json answer 308 to /contract/openapi.json, registered in src/http/server.ts beside the other root discovery routes (not in api.ts, a hot file).; An app's own /openapi.json (src/apps/scaffold.ts) is untouched. This is the forge's origin only.; A test asserts the 308 and its Location.).

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs