Operant Studio
OPER-127

[OPER-QA-2 PR 2] Assignment resolver + state machines + API routes for QA Projects

Band
MEDIUM
Suggested
Justin Cooke

Body

feature_id: FEAT-studio-qa-projects

## Context

Second half of OPER-QA-2. OPER-100 (PR 1) ships the schema; this ticket ships the runtime. Per the plan doc `docs/plans/OPER-QA-2-projects-phases-tasks-inbox.md`:

- `resolveAssignmentsForProject()` — walks members -> phases -> cases and materializes concrete `TestAssignment` rows on phase `DRAFT -> IN_PROGRESS`
- Phase state machine (`PLANNED -> IN_PROGRESS -> COMPLETED | SKIPPED`) — no phase starts until all preceding phases are COMPLETED or SKIPPED
- Project state machine (`DRAFT -> IN_PROGRESS -> BLOCKED? -> COMPLETED -> ARCHIVED`) — LEAD-only status transitions
- 7 API routes under `apps/web/src/app/api/studio/[team]/qa/projects/*`

This is the API surface the Portico BFF (POR-764/POR-QA-1) proxies to.

## Acceptance Criteria

- `packages/qa/src/projects.ts` implements the 3 named functions with strict state-machine typing
- 7 API routes at the paths named in the plan doc, each with Zod validators + full `createAuditLog -> emitEvent -> awardPoints` sequence
- Phase transition rejected if any preceding phase is not COMPLETED or SKIPPED
- Project status transition to any non-DRAFT state rejected if caller lacks LEAD role in QaTestProjectMember
- Assignment resolver materializes exactly one TestAssignment per (member, case) pair; idempotent on re-resolve
- Vitest suite covers resolver correctness, state-machine legal + illegal transitions, teamId isolation, member-role gating
- OpenAPI generated from Zod validators; committed to `apps/web/src/lib/openapi/qa-projects.json`

Attachments

Loading attachments…

Comments

Loading comments…