Repository navigation
fix(purchase): let an identified approver approve scheduler-created executions under four-eyes - #1071
Conversation
|
Warning Review limit reached
This review includes 20 billable files and costs up to $5.00.
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Or wait 1 minute for your next included review. View limit details
Comment |
|
@coderabbitai review |
|
…utions under four-eyes
Under four-eyes mode the plan-step sweep minted executions with a NULL
creator, and the gate denied every NULL creator ("predates the dual-control
feature"), so the emailed approve link was dead and the error text was false.
A NULL creator also covers API-key, deleted-user and legacy rows, so allowing
all NULLs would fail open for those.
Add purchase_executions.created_by_system (migration 000130, NOT NULL DEFAULT
false, CHECK that a flagged row has no creator). Only writeAttached's
root==nil sweep path sets it; the upsert never rewrites it. The flag is
server-only (json:"-" on the execution) and is projected read-only as
created_by_system on the history record.
checkDifferentApprover and requireDifferentApprover: a creator is compared as
before (the flag cannot override it); NULL creator without the flag keeps the
existing deny; NULL creator with the flag accepts any identified approver and
still denies an empty actor. RI exchange passes false and is unchanged.
Policy notes: no backfill, so existing NULL-creator rows stay denied. On the
token path the approver is the per-account contact_email, as for human rows
today. Under this model a single human with approve-any can run-now or
direct-execute a sweep row and skip the veto window; the owner accepted this.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Insert the legacy execution directly while the test database is at version 126. The current store requires the system-creator column introduced in version 130.
4f928f1 to
430f4d9
Compare
|
@coderabbitai full review |
|
|
Recovered and published PR head 430f4d9. The recovered rebase preserved the backend patch (range-diff equal). The added fixture fix seeds the pre-127 execution using a parameterized historical-schema INSERT. Reproduction before the fix failed with SQLSTATE 42703 because the current store required the version-130 created_by_system column while this fixture deliberately staged version 126. Current local macOS verification: all three focused integration cases passed against Docker PostgreSQL with no skips, including TestMigration_NeverStartedLegacyRampsBecomeNew and both TestFourEyes_Sweep cases. The migration fixture exercised version 126 followed by 130. go build ./... and normal pre-commit hooks passed. This is local fixture/integration evidence, with no real purchases or deployments. Independent non-author gpt-6.1-sol medium reviewer completed two passes over the full backend change and fixture fix. Reviewed staged tree bc8027e7b636731f4b32978dc3112b120a4ce1b1, which is the committed head tree. No actionable findings within backend scope. Attacks covered system-marker provenance, insert-only storage, all 13 execution read shapes, fail-closed identity checks, and historical fixture semantics. The reviewer did not independently rerun tests or mutation probes; those limits remain explicit. The audit peer separately reviewed the fixture twice with no actionable findings. Earlier verification and mutation counts in the PR description describe historical head 4f928f1, not new runs on this head. No combined migration-129 runtime proof is claimed: migration 129 belongs to prerequisite #1022, which must merge before this PR's migration 130. The dashboard approval predicate remains the planned frontend slice of #233; this PR remains backend-only. CI watchers are armed for runs 39080639737 and 39080639918. A separate CodeRabbit watcher is armed, and a full review was requested because the previous attempt was rate limited. That earlier green bot check was not a completed review. This head is not yet merge-ready. |
Summary
Part of #233 (P1). This PR is the backend change. A small frontend PR follows so the Approve button appears for these rows; it will complete the issue.
The notification sweep creates purchase executions without a creator. It does this for AutoPurchase plans that have no pre-created root (
getOrCreateExecution→claimPlanStep→attachStep(root=nil)→writeAttached).checkDifferentApproverdenied every row with no creator ("predates the dual-control feature"). WithRequireDifferentApproveron, nobody could approve or run-now these rows early. The scheduler still bought them unattended once the veto window passed.Simply allowing rows with no creator would fail open. API-key-created rows (#677), rows whose creator was deleted, and legacy rows also have no creator. The owner decided (2026-10-17, on #233):
Changes
purchase_executions.created_by_system BOOLEAN NOT NULL DEFAULT false, plusCHECK (NOT created_by_system OR created_by_user_id IS NULL). Existing rows all get false, which satisfies the CHECK.PurchaseExecution.CreatedBySystem: server-only (json:"-"). It is written by the INSERT and read through the single positionalscanExecutionRowsby all 13 full-row SELECT lists. The upsert'sDO UPDATEexcludes the column, so the value is insert-only.writeAttached'sroot == nilsweep path sets the flag.failStepand target-met terminal rows, API-key paths, retry successors and managed plans (which always have a root) never set it.checkDifferentApprover(purchase) andrequireDifferentApprover(handler):falseand behaves exactly as before.created_by_systemis projected read-only, for the frontend PR.Policy notes (owner decision B)
authorizeSessionApprovestill denies it, because there is no creator. Only approve-any holders can approve.contact_email. A signed-in contact approver can therefore approve a system row without holding approve-any. "Approve-any only" applies to the session path.Tests (each fails on the unfixed rule)
Fail-before is shown with the decision branches disabled, because the tests depend on the new field and do not compile on main.
TestFourEyes_SweepMintedRowIsApprovableByIdentifiedApproverruns realsendPlanNotificationinto Postgres, then the approval. It failed with "predates the dual-control feature" before the fix.TestRequireDifferentApprover_ModeOn_SystemCreated(handler) andTestManager_ApproveAndExecute_FourEyesOn_SystemCreatedfail the same way.true) is equivalent, because RI calls it only with a creator.Historical verification at 4f928f1 (local, macOS)
go build ./...andgo vet ./...pass.go test -racepasses on purchase, api, config, database and mocks. The mock-assertion guard passes.--build-tags integrationreports 0 issues. The pre-commit gocyclo hook passes.Current recovery evidence for head 430f4d9 is recorded in the recovery comment below. CI and CodeRabbit remain pending.
Review
plans/233-four-eyes-system-executions.md): independent review with R1-R7, then the owner's decision.🤖 Generated with Claude Code