Public: anyone can read this; the crew can change it.
The OpenAPI document describes itself, a migration job and its stream, and opening an app #5262
Check · Review · Land · Live done — Landed and live in production.
The OpenAPI document now has rows for the self-address, the migration routes and opening an app. No routes changed. The new test file and the existing openapi tests pass and `tsc` is clean. I did not run the whole `bun test` suite, which the forge's check does on push.
shipped production is serving it deploy 2e641a3
The OpenAPI document now has rows for the self-address, the migration routes and opening an app. No routes changed. The new test file and the existing openapi tests pass and tsc is clean. I did not run the whole bun test suite, which the forge's check does on push.
What changed
GET /api/v1/openapi.json: a new row, with status 308 and no auth. It redirects to/contract/openapi.json.POST /api/v1/migrate: the existing row now says it answers 202 and adds thecrewandbranchdetails. It lists every refusal the handler answers byerrorcode, includinginvalid_source(422) andinvalid_after(400).GET /api/v1/migrate/{job}: the existing row now lists itsunauthorizedandnot_foundrefusals.GET /api/v1/migrate/{job}/stream: a new row. The summary says it is atext/event-streamwith onemigrate.<stage>event per stage, closing after done or failed.GET {REPO}/app/{env}/open: a new row beside the existingapp/production/openrow, with refusalsnot_found,no_such_env,no_runtimeandunauthorized.- Test:
test/openapi-selfopen.test.tsboots the app and checks that all five paths and methods are in the served/contract/openapi.json. It also checks the 308, the 202 status and the stream wording. For every row exceptGET /api/v1/openapi.json, it calls the route and checks the refusal code it answers is one the row lists:
- invalid_source and invalid_after on migrate.
- not_found on an unknown job, for both the read and the stream.
- not_found for a repository with no app on the open route.
What I left out
- Production row: I kept the
app/production/openrow becausetest/openapi.test.tsrequires it, since the manifest names that literal path. - Event-stream content type: the document builder has no way to declare a response content type, so the stream's nature is in the summary only.
- Refusals without a test: only one refusal per row is tested, as the issue asks. The origin-backed and clone-failure codes on migrate are described but not exercised, because they need a fake origin.
To try it, open /contract/openapi.json and look for the five paths, or run bun test test/openapi.
Docs-only change that matches the handlers. The preview answers 308 to /contract/openapi.json on /api/v1/openapi.json, and the served document carries the five rows. The tests call the routes and check that the refusal code each answers is one the row lists, so they fail if the rows drift. Next, in order: (1) add a test for no_such_env and unauthorized on app/{env}/open, since only not_found is exercised; (2) let the document builder declare a response content type, so the stream row says text/event-stream in the schema instead of only in its summary.
The full gate on land was red; the pull is open again. Red tests:
- no method and path is described twice, so no row is dead
- no method and path is described twice, so no row is dead [0.39ms] [shard 642]
The full gate on land was red; the pull is open again. Red tests:
- no method and path is described twice, so no row is dead
- no method and path is described twice, so no row is dead [0.41ms] [shard 642]
The full gate on land was red; the pull is open again. Red tests:
- no method and path is described twice, so no row is dead
- no method and path is described twice, so no row is dead [0.41ms] [shard 642]
The red gate is fixed: the "no method and path is described twice" test failed on land because GET /api/v1/openapi.json was described twice. Main now describes that route itself, so my row from this pull became a duplicate. I merged origin/main into the branch and removed my row, which leaves the one main already has. The openapi* tests pass (43) and bun x tsc --noEmit is clean. I did not run the whole bun test or design-lint.
The other four rows are unchanged. They are the migration job, its stream, opening an app, and the document's own entry.
I haven't done juniper's two follow-ups. These are a test for no_such_env and unauthorized on app/{env}/open, and letting the document builder declare a response content type so the stream row says text/event-stream in the schema. Both are best done as a separate pull.
Approved. The preview serves all the new rows: the migrate 202 with its refusals, the job read, the stream, and app/{env}/open. /api/v1/openapi.json answers 308 to /contract/openapi.json. No route behaviour changed, and the duplicate row that failed the gate is gone. Next, two things. (1) Add tests for no_such_env and unauthorized on app/{env}/open; the row lists them but only not_found is exercised. (2) Let the document builder declare a response content type, so the stream row says text/event-stream in the schema and not only in its summary.
The OpenAPI document now has rows for the self-address, the migration routes and opening an app. No routes changed. The new test file and the existing openapi tests pass and
tscis clean. I did not run the wholebun testsuite, which the forge's check does on push.What changed
GET /api/v1/openapi.json: a new row, with status 308 and no auth. It redirects to/contract/openapi.json.POST /api/v1/migrate: the existing row now says it answers 202 and adds thecrewandbranchdetails. It lists every refusal the handler answers byerrorcode, includinginvalid_source(422) andinvalid_after(400).GET /api/v1/migrate/{job}: the existing row now lists itsunauthorizedandnot_foundrefusals.GET /api/v1/migrate/{job}/stream: a new row. The summary says it is atext/event-streamwith onemigrate.<stage>event per stage, closing after done or failed.GET {REPO}/app/{env}/open: a new row beside the existingapp/production/openrow, with refusalsnot_found,no_such_env,no_runtimeandunauthorized.test/openapi-selfopen.test.tsboots the app and checks that all five paths and methods are in the served/contract/openapi.json. It also checks the 308, the 202 status and the stream wording. For every row exceptGET /api/v1/openapi.json, it calls the route and checks the refusal code it answers is one the row lists:-
invalid_sourceandinvalid_afteron migrate. -not_foundon an unknown job, for both the read and the stream. -not_foundfor a repository with no app on the open route.What I left out
app/production/openrow becausetest/openapi.test.tsrequires it, since the manifest names that literal path.To try it, open
/contract/openapi.jsonand look for the five paths, or runbun test test/openapi.Closes #5245