Operant Studio
KNUCK-A039b

KNUCK-A039: extend writer-audit script to cover upsert, createMany, createManyAndReturn

Suggested
Justin Cooke

Body

feature_id: FEAT-studio-audit

## Context

`scripts/check-task-create-writers.ts` inspects `.task.create(` call sites and enforces that each supplies `createdBy` with an actor-prefixed value. In PR #278 (KNUCK-A007b1a), `packages/database/prisma/seed.ts` broke the build after A007b1a's NOT NULL promotion because the writer audit does not inspect `.task.upsert(`. The seed's `.upsert()` had never supplied `createdBy` and TypeScript rejected the create-input shape.

Fix in PR #278: manually stamped `system:seed-fixture`. This ticket extends the audit so future writers of the same shape are caught mechanically.

Related to `FEAT-studio-audit` because the writer-audit script is the mechanical enforcement of actor-prefix attribution -- the ground-truth substrate for every audit-trail claim.

## Acceptance Criteria

- `scripts/check-task-create-writers.ts` extended to also inspect:
  - `.task.upsert(` (create branch of the payload)
  - `.task.createMany(` (each object in the `data` array)
  - `.task.createManyAndReturn(` (same)
  - `.taskDependencyEdge.create(`, `.taskDependencyEdge.upsert(`, `.taskDependencyEdge.createMany(`, `.taskDependencyEdge.createManyAndReturn(`
- Same actor-prefix regex check applies (`^(user|agent|system|bearer|dispatcher):[A-Za-z0-9._:-]+$`)
- `WRITER_ALLOWLIST` and `TEST_ALLOWLIST` semantics preserved -- audited files must match; unaudited files are ignored
- Audit runs in CI as required check
- Ship with new unit tests for each of the new call-site shapes (positive: supplies createdBy correctly; negative: missing or malformed)

## Non-goals

- Not extending to other tables' writers (Task and TaskDependencyEdge only, per A007b1 / A007b1a scope)

## Effort

Single Ledger ticket. Blockers: none.

## Filed as follow-on to

PR #278 (KNUCK-A007b1a).

## Supersedes

KNUCK-A039 first attempt (Task cuid `cmts6cy1u001xky04di35rk7r`), canceled after admission rejected for missing `feature_id`.

Attachments

Loading attachments…

Comments

Loading comments…