fix(db): cascade policy_results when deleting a policy (FK 500) - #23
Merged
Merged
Conversation
policy_results.policy_id is NOT NULL REFERENCES policies(id) with no ON DELETE CASCADE, connections run foreign_keys = ON, and finalizeRun writes one result row per active policy on every completed run. So once a single run completed, deleting any policy threw SQLITE_CONSTRAINT_FOREIGNKEY and the dashboard's DELETE 500'd — policies were effectively undeletable in normal operation. deletePolicy now deletes children-first inside a transaction (same pattern as deleteOldRuns) and returns the number of evaluation rows that went with the policy; the route surfaces that count in the response and in the audit-log entry. Tests: db-level regression (evaluated policy deletes cleanly, sibling policies' results untouched, fresh policy reports 0) plus a route-level regression asserting DELETE returns 200 for an evaluated policy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
iaj6
added a commit
that referenced
this pull request
Jul 12, 2026
…24) Doc/config drift flagged by the July audit: - CLAUDE.md was the stalest file in the repo and actively misled agent sessions: claimed 6 policy types incl. a nonexistent RequiredApproval (actual: 8, with guard/check modes), "eight tables" (actual: 16 — the whole auth/webhook/audit/budget layer was missing), no mention of the auth model, login/doctor/user/admin/cleanup commands, or the transcript cost pipeline. Also marks the jobs/locks/dispatch layer as vestigial and documents the stale-dist gotcha for web tests. - CHANGELOG now covers the June audit sweep (PRs #1-#16) and the July revival audit (PRs #17-#23); previously it stopped before both. - `agentops serve` printed "The API is currently unauthenticated" when binding beyond localhost — false since the auth layer shipped. The warning now says what's true: auth is required, but traffic is plain HTTP, so use the caddy profile beyond a trusted LAN. - Litestream sidecar mounted the DB read-only, which breaks replication outright (litestream needs the checkpoint lock + sidecar files). Now rw, with a comment explaining why. The S3-compatible endpoint comment now says explicitly that setting AGENTOPS_S3_ENDPOINT alone does nothing while the config line stays commented. - scripts/demo-seed.mjs (previously untracked) is committed, now gated behind --yes since it wipes runs/events/policy_results/run_metrics. - packages/cli/src/build-info.ts is generated on every build, so the working tree was permanently dirty. Gitignored; the generator now also runs as pretest so fresh clones can run cli tests before a build. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
From the July audit: deleting any policy that had ever been evaluated threw
SQLITE_CONSTRAINT_FOREIGNKEYand the dashboard DELETE 500'd. SincefinalizeRunwrites onepolicy_resultsrow per active policy on every completed run, this made policies effectively undeletable in normal operation.deletePolicynow deletespolicy_resultschildren first inside a transaction (mirroring thedeleteOldRunspattern) and returns how many evaluation rows were removed.{ok: true, deletedResults: N}) and records it in the audit-log metadata, so an admin deleting a heavily-evaluated policy leaves a trace of how much history went with it.Tests
foreign_keys = ON; other policies' results untouched; never-evaluated policy reports 0.Full workspace suite green (1,292 tests).
🤖 Generated with Claude Code