Operant Studio
OPER-83

Recover P3009 on 20260802120000_oper_80_phi_harm_scan; unblock all prod deploys

Suggested
Justin Cooke

Body

---
feature_id: FEAT-core-platform
write_sets:
  - packages/database/prisma/schema/migrations/**
  - apps/web/vercel.json
  - .github/workflows/migrate-prod.yml
verify_cmd: pnpm --filter @operant/database exec prisma migrate status --schema=./prisma/schema && cd apps/web && pnpm build
---

## 1. Context

Every production Vercel deploy since [REDACTED-DOB] fails with Prisma P3009 on migration `20260802120000_oper_80_phi_harm_scan` (OPER-80). The failed-migration state is:

- `_prisma_migrations` row: started 2026-08-02T01:09:00Z, `finished_at = NULL`, `applied_steps_count = 0`, `rolled_back_at = NULL`, error `42710: type "PhiScanVerdict" already exists` on line 20 (`CREATE TYPE`).
- **Actual DB state:** both enum types (`PhiScanVerdict`, `PhiHumanVerdict`) exist with correct values. Table `PhiHarmScan` exists with all 14 columns, correct types, and both CHECK constraints (`PhiHarmScan_checkNumber_range` and the human-verdict tri-column completeness constraint). Both FKs exist.
- **Index drift:** DB has `PhiHarmScan_teamId_scannedAt_idx` and `PhiHarmScan_taskId_scannedAt_idx` (match), plus `PhiHarmScan_teamId_checkNumber_humanVerdict_idx` and `PhiHarmScan_commitSha_idx` (NOT in the migration file). DB is MISSING `PhiHarmScan_checkNumber_rejectionReason_humanVerdict_idx` and `PhiHarmScan_pullRequestUrl_idx` (are in the migration file).
- `SELECT count(*) FROM "PhiHarmScan"` = 0. No production data at risk.
- **No `schema.migrated` AuditLog row for OPER-80** — the `migrate-prod` GitHub workflow never ran for PR #202. Root cause: PR #202 was merged by github-actions bot (Agent Automerge). Per GitHub Actions default policy, push events triggered by `GITHUB_TOKEN` do NOT trigger further push workflows to prevent recursion. `paths:` filter matches, but the workflow was suppressed by GitHub's anti-recursion rule.
- **Someone applied a hand-crafted version of the OPER-80 migration directly to prod at 2026-08-02T01:09:00Z** — six hours BEFORE PR #202 was merged (07:21:58Z). The `_prisma_migrations` row records that attempt as failed. The version applied has different index names than the version that landed in main.

## 2. Impact

- POR-132a/b/c/d, POR-184a/b/c, OPER-82, PR #213's feature-map declaration, and every other change on main since [REDACTED-DOB] 01:09 UTC cannot reach production.
- Vercel prod is running the [REDACTED-DOB] pre-P3009 build. Runtime is fine; new code is stuck.
- Auto-planner and dispatcher crons on Vercel are still running against the pre-block build, so ticket state machines continue to advance, but any change that depends on a schema/code delta from the last 30+ hours does not exist in prod.

## 3. Acceptance Criteria

- [ ] `_prisma_migrations` row for `20260802120000_oper_80_phi_harm_scan` reflects the actual DB state (see DOC decision for `--applied` vs baseline-reset choice).
- [ ] Index set on `PhiHarmScan` matches ONE canonical source (migration file OR the DB — DOC decides which).
- [ ] Next Vercel prod deploy succeeds. `prisma migrate status` reports clean.
- [ ] `schema.migrated` AuditLog row backfilled for OPER-80 (Toma non-negotiable — audit trail integrity).
- [ ] `migrate-prod.yml` workflow trigger updated to not silently skip on bot-merges (Suki + Roan non-negotiable — silent-green surface).
- [ ] `apps/web/vercel.json` migrate-in-buildCommand DOC decision revisited (Vela + Nika — two places running migrate deploy against prod is the class of bug that produced this).

## 4. Non-Goals

- Not investigating who applied the hand-crafted DDL at 01:09 UTC. Discovery is out-of-band; forensic is a follow-up if the DOC memo recommends it.
- Not changing the `PhiHarmScan` schema. Whatever the DOC-approved recovery is, it accepts the current column/constraint set.

## 5. Verification

```
pnpm --filter @operant/database exec prisma migrate status --schema=./prisma/schema
# expected: Database schema is up to date!

cd apps/web && pnpm build
# expected: exit 0

# then trigger a Vercel deploy on main and verify READY, not Error.
```

## 6. References

- OPER-D13 migrate-prod design memo ([REDACTED-DOB] DOC)
- OPER-80 PRs: #202 (schema), #203/#204 (packet builder)
- DOC memo: [pending — this ticket]

---
<!-- admission-rejected -->
**Admission rejected (unknown_feature_id):** feature_id=FEAT-core-platform is not declared in the feature-map.md of any admission-enabled product owned by this team

Attachments

Loading attachments…

Comments

Loading comments…