11.4.5 Declare the remaining `/api/v1` operations — projects, sprints, backlog, ready set, workspaces and `/me` — so the document covers the whole surface
Repo: motir-core. One PR. 11.4.4 proved the registry and the emitter on the work-item resource. This card finishes the surface: every remaining /api/v1 endpoint gets its operation declaration, so the emitted document describes the whole API rather than a sample of it.
The work is mechanical but not clerical — each declaration is a claim about what the route actually does, and each one has to be read off the route and its schema module rather than off memory or off the sibling above it.
Do NOT work from a list written here. A hard-coded inventory of endpoints goes stale the moment a route is added or renamed. Instead walk app/api/v1 for every route.ts and every HTTP method it exports — v1RouteFiles() in tests/helpers/v1RouteAudit.ts:38 already does exactly this walk, and declaredScopeByMethod() (line 166) already reads the scope each method declares — and declare an operation for each. Today that covers /me, workspaces, projects and the project resource, the project-scoped sprints / backlog / backlog work-items / ready collections, and the sprint resource with its start, complete and membership routes; tomorrow it covers whatever the walk returns.
For each operation, take from the route and its schema module: the path parameters, the query parameters it parses, the request body schema where it has one, which of the two page envelopes it returns (the ranked one carrying totalCount, or the plain cursor page — Amendment 3 Q2 decided this per endpoint, so read that section rather than inferring), the scope it declares, and the error statuses it can raise.
Two things worth reading before declaring rather than after: lib/api/v1/rankedCollections.ts (which collections are ranked and therefore counted) and lib/api/v1/pagination.ts's V1_COLLECTIONS (the collection vocabulary a cursor is scoped to).
Scope BOUNDARY
Ends at the operation declarations. It builds no machinery — the descriptor type, the registry and the emitter are 11.4.4's. It authors no schema, shared or per-resource. It builds no CI guard: proving the document and the routes cannot disagree is 11.4.6, which needs this card's completeness to be assertable at all. It changes no route's behaviour, path, parameters or response — where a route's real behaviour differs from what its declaration would naturally say, the declaration follows the route and the discrepancy is recorded as a finding, never corrected by editing the endpoint.
Acceptance criteria
- Every
route.tsunderapp/api/v1— discovered by walking the tree, not from a list — has an operation declared for each HTTP method it exports, with the sole exception of the spec route itself, which is named explicitly as the exception. - A test drives that same walk and fails if any exported method has no operation, so a route added later without a declaration fails rather than silently going undocumented.
- Each collection operation references the envelope its route genuinely returns, with the ranked-vs-plain choice traceable to Amendment 3 Q2 rather than guessed.
- Each operation's declared scope equals the scope its route file declares, asserted by comparing against
declaredScopeByMethod(). - Each operation names the error statuses that route can actually raise, drawn from
DOMAIN_ERROR_STATUSand the ADR §4 table — including 409 and 412 where the write endpoints use them. - The assembled document still validates as OpenAPI 3.1 with the full operation set present.
- No file under
app/api/v1/**changes behaviour; any route-vs-declaration discrepancy found is written up as a bug against the owning story, not fixed here. - New files join the per-file coverage thresholds in
vitest.config.tsat the ≥90% floor.
Context refs
tests/helpers/v1RouteAudit.ts—v1RouteFiles()(the route walk) anddeclaredScopeByMethod()(the per-method scope read).lib/api/v1/projects/schema.ts·lib/api/v1/sprints/schema.ts·lib/api/v1/ready/schema.ts— the per-resource schemas 11.3 shipped, which these operations reference.lib/api/v1/rankedCollections.ts·lib/api/v1/pagination.ts— which collections are ranked and counted, and the collection vocabulary.lib/api/v1/sprints/membership.ts— the sprint-membership route's shape.docs/decisions/public-api-conventions.md— §3 the operation→scope table, §4 the status table, Amendment 3 (cursors,totalCount, the by-id carve-out).- Blocker: 11.4.4. Parent story: 11.4.