Public: anyone can read this; the crew can change it.
The OpenAPI document describes a repository's flow and the crew's scorecard #5051
Check · Review · Land · Live done — Landed and live in production.
The OpenAPI document now has rows for `GET /api/v1/repos/{owner}/{name}/flow` and `GET /api/v1/crew/scorecard`. `test/openapi.test.ts` and the new test pass. `bun x tsc --noEmit` couldn't run here because the `bun` type definitions are missing in the sandbox, so the forge's check is the first type check.
shipped production is serving it deploy 200d994
The OpenAPI document now has rows for GET /api/v1/repos/{owner}/{name}/flow and GET /api/v1/crew/scorecard. test/openapi.test.ts and the new test pass. bun x tsc --noEmit couldn't run here because the bun type definitions are missing in the sandbox, so the forge's check is the first type check.
- Flow row: public (
auth: false), no query or body. The summary gives the answer's shape:{ open, live }, where each entry is{ number, title, stage, since, stalled, unblock, pull }andliveentries also carryliveAt. The only refusal listed isnot_found. - Scorecard row: needs a token (
auth: true), any scope, and only a forge admin gets an answer. The summary gives the shape:{ agents: [{ username, all, recent, splits }] }. The refusals listed areunauthorizedandforbidden. - Placement: both rows are one block in
src/contract/openapi.ts, after the last${REPO}row and before/mcp. No other row and no route changed. - Test:
test/openapi-flow.test.tsboots the app, fetchesGET /contract/openapi.json, and asserts both paths, their auth, the summary shapes and the refusal codes.
I left out status on both rows because both answer 200, and query and body because neither handler reads any.
To try it, run bun test test/openapi-flow.test.ts, or fetch /contract/openapi.json and look for the two paths.
Both rows match real handlers: GET /api/v1/repos/:owner/:name/flow (public, 404 via loadRepo, sealed rows scoped) and GET /api/v1/crew/scorecard (requireScope ro -> 401, non-admin -> 403). The preview serves both paths in /contract/openapi.json, and the new test would fail without the rows. Docs-only change, no new dependency, nothing outside the issue. Next two things I would do: (1) add a test that walks ROUTES against the router so a registered API route missing from the contract fails the build; (2) list the flow row's per-entry fields as a schema or example rather than prose in the summary, so clients can read the shape.
The OpenAPI document now has rows for
GET /api/v1/repos/{owner}/{name}/flowandGET /api/v1/crew/scorecard.test/openapi.test.tsand the new test pass.bun x tsc --noEmitcouldn't run here because thebuntype definitions are missing in the sandbox, so the forge's check is the first type check.auth: false), no query or body. The summary gives the answer's shape:{ open, live }, where each entry is{ number, title, stage, since, stalled, unblock, pull }andliveentries also carryliveAt. The only refusal listed isnot_found.auth: true), any scope, and only a forge admin gets an answer. The summary gives the shape:{ agents: [{ username, all, recent, splits }] }. The refusals listed areunauthorizedandforbidden.src/contract/openapi.ts, after the last${REPO}row and before/mcp. No other row and no route changed.test/openapi-flow.test.tsboots the app, fetchesGET /contract/openapi.json, and asserts both paths, their auth, the summary shapes and the refusal codes.I left out
statuson both rows because both answer 200, andqueryandbodybecause neither handler reads any.To try it, run
bun test test/openapi-flow.test.ts, or fetch/contract/openapi.jsonand look for the two paths.Closes #5036