4.7 KiB
id, title, status, wave, depends_on, plan, spec
| id | title | status | wave | depends_on | plan | spec | |
|---|---|---|---|---|---|---|---|
| 04-rest-endpoints | Clarification REST endpoints on ResolveBundle, with authorization | done | 4 |
|
plan.md | ../../specs/integrations/requirements/external-question-answering.md |
Task 04: Clarification REST endpoints on ResolveBundle, with authorization
Rewire the four existing endpoints onto the resolver and add the ownership check they never had. After this task the shipped product is already fixed: the double-answer bug is closed and a PAT holder can no longer read or answer another user's question. The MCP tools are additive on top.
-
Acceptance:
POST /:id/respondreturns200 {"success":true,"claimed":…,"status":…,"response":…,"resume":…}for both winner and loser,400for validation,404for an unknown or unauthorized bundle, and500naming the bundle when partially applied. No response path publishes a resume event for a loser.- All four endpoints deny a caller who cannot access the owning task, with a
404body indistinguishable from a fabricatedpending_idand carrying no question text, option labels, task ID, session ID, or workspace ID (A2, A3). - With auth disabled, all four endpoints behave exactly as before this change (A4).
POST /:id/cancelsucceeds for a bundle whose in-memory entry is gone but whose durable record is unresolved (X2), and still closesCancelChwhen an entry exists (X3).
-
Verification:
cd apps/backend && \ gofmt -l internal/clarification internal/backendapp && \ go test -race ./internal/clarification/... ./internal/backendapp/... && \ go build ./... && \ golangci-lint run ./internal/clarification/... --timeout=5m -
Files likely touched:
apps/backend/internal/clarification/handlers.go(Handlers/NewHandlers/RegisterRoutesgain the resolver;httpRespondcollapses onto it;httpCancelRequest,httpGetRequest,httpWaitForResponseauthorize; the event-fallback branch at:326-336, theErrAlreadyResponded409 at:301, andapplyAnswersToMessagesat:447are deleted)apps/backend/internal/backendapp/helpers.go:1135(build and pass the resolver)apps/backend/internal/clarification/handlers_test.goapps/backend/internal/clarification/handlers_authz_test.go(new — revive's 800-effective-line file limit applies to test files, so authorization cases go in their own file)
-
Dependencies: 03.
-
Parallelism:
sequential— sharesapps/backend/internal/backendapp/helpers.gowith task 05. -
Inputs:
- Spec § Authorization (A1–A6), § Cancel joins the same claim (X1–X3), R8a, § Failure modes, and the BREAKING CHANGE note (the web UI is the only in-tree production caller and is covered by task 07).
- Plan § Backend → REST endpoints for the exact response envelope and error mapping.
httpCreateRequestis explicitly out of scope (A6) — do not touch it.- Authorization tests must cover both auth modes; A4 is the compatibility guarantee, not an
afterthought. Follow
internal/auth/authn.IdentityFromContextand the synthetic-identity rule inapps/backend/AGENTS.md§ Opt-in authentication & per-user scoping. - Reconcile Files likely touched with the actual diff before finishing.
-
Output contract: summary, files changed, tests run with counts, blockers, risks, and the task/plan status update in the same conversation.
Results
Implemented in commit 782dac9af. Handlers gained the *Resolver; httpRespond collapsed onto
ResolveBundle and now returns the uniform {success, claimed, status, response, resume} envelope
for both winner and loser; httpCancelRequest, httpGetRequest, and httpWaitForResponse now
authorize before reading; the event-fallback branch, the ErrAlreadyResponded 409, and
applyAnswersToMessages were deleted (their behavior moved into the resolver in task 03).
internal/backendapp/helpers.go builds and passes the resolver.
Verified in this session's final gauntlet (Wave 10): go test ./internal/clarification/... ./internal/backendapp/... passes, including handlers_authz_test.go (all four endpoints denying a
caller who cannot access the owning task, with a 404 body identical to a fabricated pending_id, in
both auth-enabled and auth-disabled modes) and the cancel-with-no-in-memory-entry case (X2).
gofmt -l reports no files; go build ./... succeeds; golangci-lint run ./internal/clarification/... --timeout=5m is clean.
No external side effects. The response envelope is a breaking change to the REST contract, but the in-tree web client is the only production caller and was updated in task 07.