OPER-99
[OPER-QA-2] Test Projects + Phases + Members over the QA primitive
Band
MEDIUM
Suggested
Justin Cooke
Body
feature_id: FEAT-studio-qa-projects blocked_by: [FEAT-studio-qa] ## Context Follow-up to OPER-QA-0 (ratified per docs/pdt/[REDACTED-DOB]-qa-primitive-and-qa-tests-tab.md). The OPER-QA-0 primitive shipped as scaffold: 8 models (TestSuite / TestCase / TestRun / TestResult / TestAssignment / CoverageCell / TestFixtureRef / TestBugLink), migration 20260818170000_oper_qa_0_scaffold, barrel exports. There is no way today to group TestCases into a scoped, sequenced execution surface for external testers (Fiesta UAT: Ana Torres, Hannah Clement). This ticket adds the missing project/phase/member layer WITHOUT duplicating the Ledger Task concept: tester actions (RUN_TEST, RETEST_BUG, REVIEW_FAILURE, ANSWER_CLARIFICATION, REVIEW_EVIDENCE, ATTEST_PHASE_COMPLETE) remain Ledger Tasks with labels, not a new polymorphic table. Risk classification per .claude/rules/build-risk-matrix.md: **Stronghold** on the schema layer (multi-tenant Studio teams, cross-product foundation, auto-called by dispatcher). Companion Portico UI ticket (POR-N, filed separately) is Safeguard. Supersedes OPER-98 (CANCELED — filed before FEAT-studio-qa-projects was declared in products/studio/feature-map.md via PR #268 merged 867df14). Full spec: docs/plans/OPER-QA-2-projects-phases-tasks-inbox.md (drafted; committed alongside PR 1). ## Scope **In-scope (this ticket, split across 2 stacked PRs per pr-size-budget.md):** - 3 new models in packages/database/prisma/schema/qa.prisma: TestProject, TestPhase, TestProjectMember - 5 new enums: TestProjectStatus, TestPhaseState, TestMemberRoleClass (2 reused) - Migration with RLS policies on all 3 tables (organization_id + current_org_id()) - packages/qa/src/projects.ts server helpers: createTestProject, addTestProjectMember, activateTestPhase, listPhasesForMember - API routes under apps/web/src/app/api/studio/[team]/qa/: projects (GET, POST), projects/[id]/phases, projects/[id]/members - Zod validators - 10 failure-path tests written BEFORE implementation (Stronghold rule) **Out of scope (follow-up tickets):** - Task type UIs beyond RUN_TEST (RETEST_BUG, REVIEW_FAILURE, ANSWER_CLARIFICATION, REVIEW_EVIDENCE, ATTEST_PHASE_COMPLETE) — Ledger Task labels only for v0.1 - QA Runner overlay (separate PDT-approved ticket family) - Seed data for Fiesta UAT · Ana + Fiesta UAT · Hannah Clement (separate seed PR after schema lands) - Portico autogen from Feature Map (OPER-QA-1 already named) - QA Tests menu tab UI (Coverage Grid, Test Library, Run Queue, Bug Board) - Email notifications (Studio missing 6 of 9 boilerplate packages including @operant/email) - Automatic phase advance (v0.2) - Cross-tenant flex identity for external testers who work at multiple client sites (v0.2) ## PR plan - PR 1 (M): schema + migration + failure-path test scaffolding (10 cases as .skip) + docs/plans/OPER-QA-2 committed - PR 2 (M, stacked on PR 1): server implementation + un-skip all 10 tests + eslint no-phi-in-template rule wiring for QA package ## Acceptance Criteria - [ ] 3 new tables land in packages/database/prisma/schema/qa.prisma with cuid() PKs, snake_case @map(), createdAt/updatedAt, organization_id on every row - [ ] Migration applies cleanly and creates RLS policies USING (organization_id = current_org_id()) on all 3 tables - [ ] No PHI columns; no /// @PHI annotations required (verified by phi-auditor reviewer) - [ ] check-org-scoped CI passes; no allowlist changes needed - [ ] All 10 failure-path tests pass - [ ] All auto-loaded reviewers return Ready - [ ] Both PRs size/M or smaller per pr-size-budget.md; PR 2 stacked on PR 1 branch - [ ] Rollback verified: DROP TABLE + DROP TYPE reverses migration cleanly; no impact on existing OPER-QA-0 rows - [ ] docs/plans/OPER-QA-2-projects-phases-tasks-inbox.md committed in PR 1 - [ ] Portico companion POR ticket blocked_by this ticket until PR 2 merges ## Blocks Portico companion ticket (POR-N, filed separately) implementing the in-Portico QATaskInbox drawer — cannot start until this ticket's PR 2 merges and Studio QA API endpoints are live. --- <!-- admission-rejected --> **Admission rejected (missing_edge):** ticket declares blocked_by=FEAT-STUDIO-QA but no BLOCKED_BY edge from FEAT-studio-qa-projects exists in studio/dependency-map.md — audit the map first
Attachments
Loading attachments…
Comments
Loading comments…