canopy-rules Data Model
On this page
Cross-link: canopy-rules API Reference · Source: migrations/
Tables
| Table | Purpose |
|---|---|
|
Per-evaluation audit row. One row written every time |
|
Per-service transactional outbox (ADR-018), schema single-sourced in |
|
T2-7 (#680) corpus-version history for non-persisting dry-run replay (ADR-027 §6, ADR-028). One row per |
rule_sets no longer exists. The original schema (20260326000000) provisioned it as a startup-cache table that auto-imported JDM files; the JDM ruleset rewrite (see docs/modules/ROOT/pages/plans/jdm-ruleset-rewrite.adoc Step 2.5) replaced it with direct filesystem serving via a NamedFilesystemLoader wrapping zen-engine’s FilesystemLoader. Migration 20260412000000 drops the now-vestigial table; rule_evaluations.rule_set_name is intentionally a TEXT column (not an FK) so the drop is safe for the audit trail.
Relationships
The three tables are independent — there is no relationship between the ruleset audit trail, the event outbox, and the corpus-version history. (rule_evaluations and ruleset_corpus_versions both reference a corpus hash, but only as a value — there is no FK.)
Cross-service FKs (ADR-001 boundary)
canopy-rules holds no Postgres-level foreign keys to other services. rule_evaluations.context_id is an opaque UUID supplied by the caller (canopy-snap, canopy-tanf, canopy-medicaid, canopy-caps, canopy-wic, canopy-eligibility); canopy-rules makes no attempt to validate it against any other database. The rule_set_name column is also unenforced — it refers to a logical name in the filesystem ruleset loader, not a DB row. This is intentional: rulesets evolve via JDM file revisions in rulesets/, and the audit trail must remain readable even after a ruleset is renamed or retired. event_outbox likewise holds no cross-service FKs — its payload is a self-contained JSON event envelope routed by routing_key, with no DB-level reference to any consumer.
Retention
The ruleset audit trail’s retention floor is the lifetime of any determination that referenced the ruleset. Determinations are retained for the case + appeal window across all program services (typically 3 years post-closure for SNAP per 7 CFR 272.1(f), 3 years post-final-claim for Medicaid per 42 CFR 433.32, longer for cases under audit or appeal), and a determination is only replayable while its corresponding rule_evaluations row survives. In practice this makes rule_evaluations an append-only, indefinitely-retained table in production. Archive moves are operator-driven and rare.
Indexes
-
idx_rule_evaluations_rule_set_name— per-ruleset evaluation listing (regression analysis, audit replay) -
idx_rule_evaluations_context— composite(context_type, context_id)for retrieving the evaluation history of a specific determination -
event_outbox_*— the three generated partial outbox indexes (drainer hot path, lease-aware claim, ADR-039 held-skip); documented once in the data-models index
Migration files
-
20260326000000_create_rules_tables.sql— original schema (rule_sets startup cache + rule_evaluations audit trail) with per-rule-set-name and per-context indexes -
20260412000000_drop_rule_sets_table.sql— drops the rule_sets cache table after the JDM ruleset rewrite moved ruleset serving to the filesystem viaNamedFilesystemLoader;rule_evaluationsis untouched -
20260508000000_create_event_outbox.sql+20260518004851_event_outbox_lease_columns.sql+20260713000000_event_outbox_hold.sql— the generated ADR-039 single-sourced outbox migrations (cargo xtask outbox-migrations --write); documented once in the data-models index -
20260626000000_create_ruleset_corpus_versions.sql— T2-7 (#680) corpus-version history table, primary-keyed(corpus_hash, ruleset_name)for idempotent boot insert and corpus-version replay
All migrations are forward-only per ADR-016.