Data Model: Data Exchange & ICPC
On this page
Overview
The exchange service manages inter-agency data sharing (partners, agreements, transactions) and Interstate Compact on the Placement of Children (ICPC) requests with home studies and attachments.
Partners define external systems to exchange data with. Agreements establish the legal basis. Transactions record individual data exchange operations. ICPC requests follow a multi-step workflow from draft through home study to completion.
Tables
| Table | Purpose |
|---|---|
|
#1466 B5 (ADR-065/066 §Amendment #1479) SSA screening run-lifecycle substrate: per-case cohort watermarks backing stale-run invalidation delivery |
|
External agencies/systems configured for data exchange |
|
Legal agreements governing data exchange with a partner |
|
Individual send/receive operations with payload and status tracking |
|
Async partner-send queue behind the 202-Accepted handler (platform-stab-2 §D5; #1185 lease + fencing) |
|
Interstate placement requests with multi-step status workflow. Carries the
|
|
Structured home study evaluations for ICPC requests (one-to-one); carries
the same denorm triple via the |
|
Documents attached to ICPC requests — stored in object storage; carries
the same denorm triple via the |
|
ADR-062 §U upload-attempt tombstones (SU2 #1248): one immutable row per client
upload operation, id = the client-held request id; generation-fenced CAS
state machine + replay decision table live in |
|
SSA SOLQ screening runs (#1462, plan |
|
One row per screened household member: the A4 |
|
The typed job queue the |
|
E3 (#1566): the UD4 provenance handoff relation — one insert-only row per
member, written INSIDE the transport prune transaction, snapshotting the
facts only the pruned job/transaction rows held (correlation token,
partner, attempts, final status, categorical |
|
E3 (#1566): craig-exchange’s durable archive ledger (the craig-rules shape
verbatim; ADR-058 D8) — one row per archived-and-pruned provenance batch,
written inside the prune transaction; |
ER Diagram
exchange_send_jobs
The send worker’s queue: one row per staged partner send, drained by
ExchangeSendWorker (claim → adapter POST → fenced finalize). Statuses:
pending / in_flight / sent / failed.
| Column | Type | Notes |
|---|---|---|
|
UUID |
PK (uuidv7) |
|
UUID |
FK → |
|
UUID |
Target partner |
|
UUID |
UNIQUE — propagated as |
|
JSONB |
Outbound payload staged verbatim |
|
TEXT |
CHECK pending / in_flight / sent / failed |
|
INT |
Incremented on EVERY claim (incl. lease reclaims); adapter errors past |
|
TEXT |
Latest adapter/dispatch error |
|
TIMESTAMPTZ |
Scheduled ELIGIBILITY (backoff target) — deliberately untouched at claim; never a claim clock |
|
TIMESTAMPTZ |
#1185: the REAL claim clock. NULL (never claimed / legacy / crash residue) counts as an expired lease |
|
BIGINT |
#1185: fencing token — every claim increments it; every terminal/retry transition carries a |
|
TIMESTAMPTZ |
Stage / terminal stamps |
Lease semantics (#1185): the claim query itself re-admits in_flight
rows whose claimed_at is NULL or older than the worker’s
CLAIM_LEASE_SECS (90s = 3× the 30s transport cap) — recovery is
continuous on the 1s poll; there is no recovery sweep. A crash after
the partner accepted but before finalize re-sends after lease expiry:
at-least-once by design (ADR-022 #1185 amendment), deduped
partner-side by craig_correlation_id.
Key Indexes
-
idx_exchange_partners_type— filter by partner type -
idx_exchange_partners_active— active partner lookup -
idx_agreements_partner— agreements by partner -
idx_agreements_status— agreement status filtering -
idx_transactions_partner— transactions by partner -
idx_transactions_status— transaction status filtering -
idx_transactions_initiated_at— time-range queries -
idx_icpc_case— ICPC requests by case -
idx_icpc_child— ICPC requests by child -
idx_icpc_status— ICPC status filtering -
idx_icpc_direction— inbound vs outbound ICPC -
ssa_screening_runs_one_active_idx— UNIQUE (case_id) WHERE pending AND not invalidated: the one-ACTIVE-run-per-case safety net (#1462) -
ssa_screening_runs_case_idx— run history by case (D3 freshness checks) -
ssa_screening_members_person_idx/_ordinal_idx— UNIQUE per run -
ssa_screening_members_transaction_idx— UNIQUE fleet-wide (txn↔member 1:1) -
ssa_screening_jobs_member_idx/_correlation_idx— UNIQUE -
ssa_screening_jobs_drainable_idx/_lease_idx— the B4 worker’s claim
lease-recovery partials (theexchange_send_jobsshape) -
ssa_screening_runs_held_idx— partial on(id) WHERE legal_hold(#1566): the held-runs gauge + hold-shield predicates; held rows are rare by design -
ssa_transport_handoffs_completed_idx— the archive spec’s(ts, id)paging key (#1566; the family’s shared age clock) -
idx_archive_ledger_id_range—(first_record_id, last_record_id): the D17 archive-fetch batch resolution (#1566) -
idx_icpc_home_study_request— home study by ICPC request -
idx_icpc_attachments_request— attachments by ICPC request -
idx_exchange_send_jobs_drainable— partial on(next_attempt_at) WHERE status = 'pending'; the claim query’s due-pending arm -
idx_exchange_send_jobs_lease— partial on(claimed_at) WHERE status = 'in_flight'(#1185); the claim query’s expired-lease arm (replaced the wrong-clockstuck_in_flightindex) -
idx_exchange_send_jobs_correlation— UNIQUE oncorrelation_id