Operant Studio
OPER-103

Denormalize teamId onto QaTestPhase / QaTestProjectCase / QaTestProjectMember with @@index([teamId, ...])

Band
MEDIUM
Suggested
Justin Cooke

Body

## Context

Denormalize `teamId` onto `QaTestPhase`, `QaTestProjectCase`, and `QaTestProjectMember`. Currently these three tables are `scoped_via_parent` (they reach `teamId` transitively through `QaTestProject.teamId`), which forces every read to join through the parent. Denormalizing puts them on the same footing as the other org-scoped tables and lets `withTeamContext` policies cover them directly without special-case join predicates.

Depends on OPER-100 (adds these tables). Reversible: `ALTER TABLE ... DROP COLUMN "teamId"` if we regret it.

## Acceptance Criteria

- Migration `20260908010000_oper_103_denormalize_teamid` adds nullable `"teamId" TEXT` on the 3 tables, backfills from parent, then sets `NOT NULL` + FK to `Team(id)`.
- Prisma `qa.prisma` updates the 3 models with `teamId String` + `team Team @relation(...)`.
- `scripts/org-scoped-allowlist.json` removes the 3 tables from `scoped_via_parent`; they now scope directly.
- Vitest `packages/qa/src/__tests__/team-scope.test.ts` proves cross-team reads fail on all 3 tables (against `withTeamContext(teamA)`).
- Migration is a no-op on empty DBs (fresh Neon preview).

blocked_by: [OPER-100]

Attachments

Loading attachments…

Comments

Loading comments…