Context
ChangeReport detail already has the key operator actions in the handoff: acknowledge, snooze, and resolve. This issue owns only the change lifecycle routes and persistence semantics so it can ship independently from pipeline, billing, and UI work.
Acceptance Criteria
Files to Touch
apps/api/src/routes/changes.ts
apps/api/src/db/changeReports.ts
apps/api/src/stream/events.ts
apps/api/src/server.ts
packages/shared/src/types.ts
packages/shared/src/schemas.ts
tests/api/changes.lifecycle.test.ts
Prompt
/plan
Implement the Redline change lifecycle slice from the handoff. Focus only on acknowledge, snooze, and resolve routes; append-only persistence; conflict handling; and the `change.stateChanged` SSE event. Branch must stand alone from other issue branches and must not wait for UI, Stripe, Slack, or agent pipeline work.
Test Plan
- Run the API route tests for acknowledge, snooze, and resolve
- Verify invalid payloads return 422 with the standard error envelope
- Verify stale/conflicting transitions return 409
- Verify the persisted ChangeReport reads back with updated state
- Verify one
change.stateChanged event is emitted per successful transition
Redline Handoff Adherence
- API shape from
handoff/API.html
- Persistence shape from
handoff/Data Model.html
- No citation, no claim remains enforced on ChangeReport reads
- This issue has no dependency on other Sprint 1 issues
Per-Issue PR Workflow (REQUIRED)
- Branch from
main: d3v07/change-state-transitions
- Implement without waiting on any other issue branch
- PR to
main: Closes #1
- Review pass for route validation, persistence correctness, and SSE behavior
- Address comments
- Leave final merge to
main for the owner
Definition of Done
Context
ChangeReport detail already has the key operator actions in the handoff: acknowledge, snooze, and resolve. This issue owns only the change lifecycle routes and persistence semantics so it can ship independently from pipeline, billing, and UI work.
Acceptance Criteria
POST /v1/changes/:id/acknowledgeexactly to the API contractPOST /v1/changes/:id/snoozewith typeduntilhandling and validationPOST /v1/changes/:id/resolvewith typed resolution payloadchange_reportsmodel from the data handoffFINALor equivalent correctness handling for reads where ClickHouse replacement semantics require itchange.stateChangedover SSE when state changesFiles to Touch
apps/api/src/routes/changes.tsapps/api/src/db/changeReports.tsapps/api/src/stream/events.tsapps/api/src/server.tspackages/shared/src/types.tspackages/shared/src/schemas.tstests/api/changes.lifecycle.test.tsPrompt
Test Plan
change.stateChangedevent is emitted per successful transitionRedline Handoff Adherence
handoff/API.htmlhandoff/Data Model.htmlPer-Issue PR Workflow (REQUIRED)
main:d3v07/change-state-transitionsmain:Closes #1mainfor the ownerDefinition of Done
d3v07/change-state-transitionsmain