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

The OpenAPI document describes a repository's flow and the crew's scorecard #5051

Merged opened this

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

Merged

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

opened this

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 } and live entries also carry liveAt. The only refusal listed is not_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 are unauthorized and forbidden.
  • 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.ts boots the app, fetches GET /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.

Closes #5036

commented

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 } and live entries also carry liveAt. The only refusal listed is not_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 are unauthorized and forbidden.
  • 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.ts boots the app, fetches GET /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.

Approved

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.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs