Recall & Proof Projection Architecture
Companion to: docs/architecture/QC_PROJECTION_ARCHITECTURE_2026-05-18.md + docs/architecture/SALES_MARKET_PROJECTION_ARCHITECTURE_2026-05-18.md.
Source strategy: docs/product/FIN_DATA_SIGNAL_OFFERINGS_2026-05-15.md (G-1 / G-3 / G-4 federal offerings + B-5 custom reports + Tier 2 proof packages).
Source catalog: docs/projections/PROJECTION_CATALOG_2026-05-15.md §6.1 + §6.4 + §6.7.
0. TL;DR
Every recall-trigger or proof-window event ripples into 4 vault MDs + 3 JSONB projections + 1 evidence bundle + ~10 backlink edges. All renderers in this family are DETERMINISTIC (identical input → byte-identical output) because the outputs are legal-grade citation targets for federal recall investigations + FSMA enforcement + customer dispute resolution + Tier 2 customer proof reporting.
trigger event → ripple
─────────────────────────────────────────────────────────────────
compliance.recall_initiated → recall_trace.<lot_id> (on-demand)
+ recall_evidence_bundle (R2 attachments)
+ notifies impacted customers via
customer_commodity_matrix (Sales arch §2.3)
quarter_end + 5d (scheduled) → proof_package.<tenant>.<quarter>
recall_drill.fsma-204-test request → recall_drill MD + drill_metrics row
knowledge.fsma_completeness_updated → fsma_traceability_completeness.<tenant>
(live dashboard for FDA-facing view)
agent invokes assemble_recall_trace → on-demand walk via po_timeline_projection
+ vendor_scorecard + qc_inspection_history
+ customer_commodity_matrix
Why determinism matters here: these outputs are subpoena material. A federal investigator must be able to re-run the renderer 6 months later against frozen event-store state and get the same bytes back. No LLM in the renderer path. No timestamps-of-now in the body. No random IDs. Source-events list + renderer_version + content_hash + frozen_input_event_set are mandatory.
0.5 Central-overlay reads contract (3-rung taproot — see AOL §13.6)
Every projector in this family is a rung-3 tenant overlay renderer that ALSO captures Central knowledge state at frozen-input time. This is stricter than QC + Sales arches: because outputs are legal-grade citation targets, the projector MUST snapshot the exact Central MD content_hash at frozen_input_event_id_range time and pin it into the output’s frontmatter. A re-render at T+6mo reads the same Central MD versions, NOT the current ones.
Per Recall & Proof projector:
| Projector | Central MDs read from _taproot_mirror/ | Pinned in output as | Why |
|---|---|---|---|
recall_trace.<lot_id> | docs/commodities/<slug>.md, docs/vendors/<slug>.md, docs/grower-profiles/<slug>.md (when populated), docs/certifications/<slug>.md | central_md_pins[]: [{path, content_hash, captured_at}] | Upstream chain + grower terminus + cert-as-of-recall-time evidence |
proof_package.<tenant>.<quarter> | docs/commodities/<slug>.md (every commodity tenant traded in quarter), docs/regions/<slug>.md | central_md_pins[]: ... | ”Industry-standard baseline” for KPI claims (what the cited commodity profile SAID this commodity should do during this quarter) |
recall_drill.fsma-204-test | docs/commodities/<slug>.md for synthetic-scenario commodity, docs/certifications/<slug>.md | central_md_pins[]: ... | Synthetic scenario must use frozen Central content for replay reproducibility |
fsma_traceability_completeness.<tenant> | docs/certifications/<slug>.md (each cert held by tenant’s vendors) | central_md_pins[]: ... (monthly snapshot variant) | Cert MD lists required-KDE fields; completeness score is computed against frozen-at-snapshot rules |
Pinning contract: central_md_pins[] becomes part of the content_hash input. A change to a Central MD at T+1 does NOT invalidate the pinned recall_trace — that’s the whole point. To force re-evaluation, bump renderer_version AND re-run with the new Central MD content_hash captured.
Read graceful-degradation: same as other arches — central_pending: true flag if mirror missing. But for federal-audience outputs (recall_trace variant=federal, proof_package variant=federal), central_pending triggers system.federal_render_degraded alert and the federal variant DOES NOT ship until Central is present. Internal + customer variants ship anyway.
Write contract: projectors write to tenant paths (docs/recall/...) only. Never write to _taproot_mirror/.
1. Vault MD projectors (rung 3, DETERMINISTIC)
All 4 emit byte-identical outputs for identical inputs. Use crypto.subtle.digest('sha-256', ...) over the source-events list + renderer_version + central_md_pins[] to compute content_hash. Mismatched hash on re-render fires system.deterministic_renderer_drift_detected.
1.1 recall_trace.<lot_id>
- doc_kind:
recall_trace - audience: FIN operator (internal) + customer (customer-safe filtered) + federal (regulator)
- cadence: on-demand via
assemble_recall_traceMCP tool (privileged) + auto-render oncompliance.recall_initiated - path:
nathel-intranet:docs/recall/traces/<lot_id>/<iso_timestamp>.md - determinism: MANDATORY
- sources:
- Provenance walk via
walk_provenance(P1-08 — readsdoc_backlink_projection+fact_citations) lot_lifecycle_reconciliation_projection(already live) for receipt → adjustment → reconciliation chainpo_timeline_projection(Sales arch §2.2) for procurement chaincustomer_commodity_matrix(Sales arch §2.3) for customer reachqc_inspection_history(QC arch §2.2) for quality-event timelinevendor_scorecard+vendor_label_evidence(QC arch + Sales arch) for provenance back to grower- Comms history (operational_memory keyed by lot_id)
- Corrective action events (
compliance.corrective_action_taken,inventory.lot_quarantined)
- Provenance walk via
- output shape (deterministic structure):
- Section 1: scope statement (lot_id, commodity, vendor, harvest_date, total_cases, contamination_class)
- Section 2: receipt chain (PO → vendor → arrival → lot → QC outcome — each step with event_id citation)
- Section 3: outbound chain (lot → sales orders → invoices → customers → delivery confirmations)
- Section 4: customer reach (count, customer_ids, dollar exposure, primary contacts)
- Section 5: root-cause candidates (causally-linked events: vendor history, temperature exceptions, QC patterns)
- Section 6: mitigation timeline (when quarantined, when notified, when corrective action filed)
- Section 7: recordkeeping evidence (links to PDFs, photos, comms threads — all stored in R2 with content-addressed paths)
- audience filters:
federal: full chain, all event_ids, all PII redacted per FedRAMP rules; no commercial fieldscustomer: their orders only, their invoices only; vendor identity redacted; cost basis stripped; other customers invisibleFIN operator: full chain unredacted
1.2 proof_package.<tenant>.<quarter>
- doc_kind:
proof_package - audience: FIN operator + customer (executive level on share) + federal + partner (Anthropic / investor on share)
- cadence: quarterly (
quarter_end + 5d) + on-demand - path:
nathel-intranet:docs/recall/proof-packages/<tenant>/<YYYY-Q[1-4]>.md - determinism: MANDATORY (frozen input event set = events with
timestamp < quarter_end_timestamp) - sources:
- Tenant KPIs from
daily_company_pulse_projection,sales_team_dashboard,buyer_team_dashboard,data_quality_dashboard(all live JSONB) - Event volume by family (
SELECT type, count(*) FROM events WHERE tenant_id=? AND timestamp BETWEEN ?) - Agent action counts (
agent.tool_calledevent family aggregated per agent) - Outcomes attributed to FIN intervention (per
agent_enrichment_metricsprojection — when shipped) - Customer testimonials linked from comms threads (operational_memory
category = testimonial) - Cited evidence for every claim (each KPI claim cites its event-id source set)
- Tenant KPIs from
- output shape:
- Section 1: executive summary (3-bullet leadership read)
- Section 2: KPI deltas vs prior quarter (with embedded sparklines / bar charts as inline SVG)
- Section 3: narrative of operational improvements (LLM-AUTHORED but cached — see §3.1 LLM-author exception)
- Section 4: cited evidence ledger (every claim links to source event_ids)
- Section 5: attachments ledger (R2 paths + content hashes)
- Section 6: signing metadata (renderer_version, content_hash, frozen_input_event_id_range)
1.3 recall_drill.fsma-204-test
- doc_kind:
runbook - audience: federal + FIN operator
- cadence: on-demand (quarterly drill recommended;
recall_drill_requestedevent triggers) - path:
nathel-intranet:docs/recall/drills/<YYYY-MM-DD>-<drill_id>.md - determinism: MANDATORY
- sources:
- Synthetic recall scenario events (created at drill start with
data.is_drill: true) - Time-to-trace measurements (timestamp deltas across the recall walk)
- Renderer of
recall_trace.<synthetic_lot_id>invoked against the drill’s synthetic events
- Synthetic recall scenario events (created at drill start with
- output shape:
- Section 1: drill scope statement (commodity, hypothetical contamination, target time-to-trace)
- Section 2: actual drill plan (steps tested, agents involved, tools invoked)
- Section 3: expected step durations vs measured durations
- Section 4: pass/fail per FSMA 204 24-hour rule (
assemble_recall_tracecompletion within 24h of drill start) - Section 5: evidence of completion (cited synthetic events + the produced
recall_trace.<synthetic_lot_id>link) - Section 6: gaps identified (any incomplete provenance, slow walks, missing evidence)
1.4 fsma_traceability_completeness.<tenant> (vault MD form)
- doc_kind:
system_projected(live dashboard) +proof_package(monthly snapshot) - audience: FIN operator + employee (compliance) + federal (FDA-facing)
- cadence: live (event-driven on KDE events) + monthly snapshot
- path:
nathel-intranet:docs/recall/fsma-completeness/<tenant>/<YYYY-MM>.md - determinism: MANDATORY for monthly snapshot; live variant non-deterministic (just-in-time view)
- sources:
fsma_traceability_completeness_projection(existing JSONB substrate perproject_fsma_204_compliance_envelope)- All KDE-bearing events (
pallet.*,location.*,sensor.*,compliance.*) — verify full envelope - Lot-level walks: every active lot must have full provenance chain end-to-end
- output shape:
- Completeness score (0-100% per CTE — Critical Tracking Event)
- Per-commodity breakdown
- Per-vendor breakdown (which vendors’ lots have gaps)
- List of incomplete lots (with the specific KDE field missing)
- 24-hour rule readiness check (would
assemble_recall_tracecomplete within 24h for every active lot?) - Monthly snapshot: frozen input event set + renderer_version + content_hash
2. JSONB projections (event-driven)
2.1 recall_evidence_chain_projection (NEW)
- migration:
072_recall_evidence_chain_projection.sql - schema:
tenant_id × lot_id → { upstream_chain[], downstream_chain[], evidence_artifacts[], walk_completion_status, last_walked_at } - source events: any event with this lot_id (read-through) +
compliance.recall_initiated(triggers materialization) - replay command:
pnpm cli replay-projection --projection=recall_evidence_chain_projection --tenant=<tenant_id> - RLS: required
- fed-by:
event-handlers/projection-recall-evidence-chain.ts(NEW) - consumed-by:
recall_trace.<lot_id>renderer
2.2 drill_metrics_projection (NEW)
- migration:
073_drill_metrics_projection.sql - schema:
tenant_id × drill_id → { drill_started_at, drill_completed_at, total_walk_duration_ms, step_durations[], pass_fail, gaps_identified[] } - source events:
recall_drill.started,recall_drill.step_completed,recall_drill.completed - replay command:
pnpm cli replay-projection --projection=drill_metrics_projection --tenant=<tenant_id> - fed-by:
event-handlers/projection-drill-metrics.ts(NEW) - consumed-by:
recall_drill.fsma-204-testrenderer + federal_readiness_tracker
2.3 proof_package_evidence_index (NEW)
- migration:
074_proof_package_evidence_index.sql - schema:
tenant_id × quarter → { kpi_event_id_sets{}, testimonial_message_ids[], frozen_at, frozen_input_event_id_range, content_hash, renderer_version } - source events: quarter-boundary cron writes once; immutable after write
- replay command:
pnpm cli replay-projection --projection=proof_package_evidence_index --tenant=<tenant_id> - fed-by:
event-handlers/projection-proof-package-evidence-index.ts(NEW) - consumed-by:
proof_package.<tenant>.<quarter>renderer
Note: existing proof_package_projection (per audit registry — kb_health_summary siblings) is a separate JSONB substrate for raw KPI rollups. The new proof_package_evidence_index is the immutable-citation-index layer that makes the package itself deterministic and re-renderable. Keep both.
3. Determinism contract (non-negotiable)
3.1 Renderer rules
| Rule | Why |
|---|---|
NO Date.now() in the body. All timestamps come from source events. | Re-render at T+6mo must produce same bytes |
NO Math.random() / crypto.randomUUID(). Use content-addressed IDs (sha-256 of input). | Determinism |
| NO LLM in the rendering path (with one exception §3.2). | Determinism + auditability |
| Input is the frozen event-id set, not a query at render time. | Re-render must use same input |
content_hash is computed and emitted as part of the doc. | Drift detection |
renderer_version is bumped any time the renderer changes; bump triggers re-render with new hash. | Versioned reproducibility |
| Renderer is a pure function (deps injected: events fetch, attachment fetch). | Testable + replayable |
3.2 LLM-authored exception (§3.3 of catalog spec — “narrative of operational improvements”)
ONE section of proof_package (§1.2 Section 3 — narrative summary) may be LLM-authored because it’s editorial prose summarizing the KPI deltas. To preserve determinism:
- LLM call runs ONCE at quarter-end render time
- Output is stored in
proof_package_evidence_index(§2.3) keyed to that exactfrozen_input_event_id_range+renderer_version - Re-renders read the cached LLM output from the index, never re-call the LLM
- New LLM output requires explicit
renderer_versionbump proof_package_evidence_index.llm_narrative_cache_idis part ofcontent_hashinput
This is the only LLM call permitted in this family. All other renderers are pure deterministic.
4. Evidence bundle (R2 attachments)
Recall trace + proof package outputs reference attachments stored in R2 with content-addressed paths:
r2://<tenant>/recall-evidence/
└── <lot_id>/
└── <sha256-of-content>/
├── qc-photo-<message_id>.jpg
├── vendor-label-extract-<message_id>.json
├── temperature-log-<sensor_id>-<window>.csv
├── pp-arrival-report-<load_id>.pdf
└── comms-thread-<thread_id>.json (export of operational_memory rows)
Path components are deterministic (sha256 of content → path), so the same bytes always land at the same path. The recall_trace MD references attachments by R2 path; federal investigators can fetch by URL and verify hash matches.
R2 retention policy: evidence bundles for any lot involved in a compliance.recall_initiated event are RETAINED INDEFINITELY. All other evidence follows FSMA 204 7-year retention.
5. Native comms integration
| Surface | Where Recall & Proof projections land |
|---|---|
| Compliance role rail | fsma_traceability_completeness daily snapshot pinned; recall_drill results posted on completion |
| FIN operator rail | proof_package weekly preview during quarter-end window |
| Customer portal (when shipped) | recall_trace customer-facing variant: their orders only, vendor redacted |
| Federal portal (FedRAMP, Wave 5+) | recall_trace federal variant: full chain + evidence bundle access |
Critical recall: urgent_recall_notification email to affected customers + tenant compliance role + federal liaison; uses customer_commodity_matrix (Sales arch §2.3) to compute recipient list | |
| Slack | compliance.recall_initiated → instant Slack ping to #compliance channel with link to in-flight recall_trace.<lot_id> |
| SMS / Voice | Critical recall: SMS to compliance role primary contact + FIN operator on-call |
6. Frontmatter contract (same as QC + Sales arches)
---
schema_version: 1
doc_id: <projector-output-doc-id>
doc_kind: recall_trace | proof_package | runbook | system_projected
title: <human-readable>
slug: <kebab-case>
source_attribution:
- producer:<projector-name>
- source_events:<comma-separated event_ids in frozen input set>
- renderer_version:<semver>
- content_hash:<sha256>
- frozen_input_event_id_range:<min>-<max>
lifecycle_status: active
created_at: <iso>
updated_at: <iso>
maintained_by: <projector-name>
visibility: restricted | federal_only | customer_visible | company
data_plane: relationship_data
linked_entities:
- { type: lot, id: <lot_id> }
- { type: commodity, slug: <slug> }
- { type: vendor, slug: <slug> }
- { type: customer, slug: <slug> }
- { type: po, id: <po_id> }
- ... etc
tags: [recall, proof, fsma_204, ...]
determinism_required: true
re_render_hash_drift_alert: true
---Note determinism_required: true flag — projectors with this flag set hit the determinism-drift check on every re-render.
7. Build sequence
Sequence R1 — 3 JSONB projections (~2-3 days)
- R1-A
recall_evidence_chain_projection(migration 072 + handler + dispatcher + test) - R1-B
drill_metrics_projection(migration 073 + handler + dispatcher + test) - R1-C
proof_package_evidence_index(migration 074 + handler + dispatcher + test)
Sequence R2 — 4 vault MD renderers (~5-7 days, DETERMINISTIC)
- R2-A
recall_tracerenderer (event-driven oncompliance.recall_initiated+ on-demand MCP tool) + content_hash machinery + audience-filter machinery - R2-B
proof_packagerenderer (quarterly cron) + LLM-narrative cache (§3.2) + 4-audience output variants - R2-C
recall_drillrenderer (on-demand) + drill metrics aggregation - R2-D
fsma_traceability_completenessrenderer (live + monthly snapshot dual mode)
Sequence R3 — Evidence bundle pipeline (~2 days)
- R3-A R2 content-addressed path resolver + attachment fetcher + retention policy enforcer
- R3-B Federal investigator MCP tool:
fetch_recall_evidence(lot_id, attachment_hash)returns the bytes with audit log
Sequence R4 — Agent surface + UI (~2 days)
- R4-A
assemble_recall_traceMCP tool (privileged role only) - R4-B
request_recall_drillMCP tool (compliance role) - R4-C
get_proof_packageMCP tool (operator + customer-share) - R4-D Compliance role rail integration
Sequence R5 — Federal hardening (~1 week, FedRAMP gated)
- R5-A Federal audience filter audit + redaction completeness verification
- R5-B Federal MCP endpoint deployment (FedRAMP infrastructure)
- R5-C Agency-specific data handling protocols + IdP integration
R5 ships only when first federal contract clears (per feedback_federation_publisher_frozen analog — code can be ready, activation gated on Robert approval + federal contract).
8. Coordination with other arch docs
| Other arch doc | Recall & Proof dependency |
|---|---|
| QC arch | Reads qc_inspection_history JSONB for inspection events; reads vendor_label_evidence for label-verification chain; uses QC photos as recall-evidence-bundle attachments |
| Sales & Market arch | Reads po_timeline_projection for procurement chain; reads vendor_scorecard for vendor history; reads customer_commodity_matrix for customer-reach computation in recall_trace §4 |
| Agent Audit arch (forthcoming) | Recall investigations are themselves agent sessions → tracked via agent_harness_session projection |
9. Open questions
| ID | Question | Default until answered |
|---|---|---|
RP-Q1 | LLM-author cache (§3.2) — store in proof_package_evidence_index or separate llm_narrative_cache table? | Same index — keeps a single re-renderable source-of-truth per quarter |
RP-Q2 | Determinism-drift alert (§3 last bullet) — fail the render or warn-and-continue? | Fail loud — federal-grade outputs cannot drift silently |
RP-Q3 | Recall trace customer-facing variant — pre-render or on-demand? | On-demand — recall is rare; pre-render is wasteful |
RP-Q4 | Quarterly proof package cadence — fixed quarter-end + 5d or tenant-configurable? | Fixed; multi-tenant later may override per-tenant |
RP-Q5 | FSMA completeness score threshold for tenant-readiness — what % triggers tenant.fsma_below_threshold alert? | 95% — gives 5% buffer for in-flight lots |
RP-Q6 | R2 retention — recall-involved lots stored forever; how is “involved” defined? | Any lot transitively reachable via 2 hops from a compliance.recall_initiated event |
RP-Q7 | Federal MCP endpoint (R5-B) on Cloudflare FedRAMP or separate AWS GovCloud? | Defer until federal contract; FedRAMP-on-Cloudflare per existing strategy |
10. Productization mapping
| Offering | Recall & Proof projector that enables it |
|---|---|
| G-1 Real-time Recall Trace Access (1M/agency) | recall_trace.<lot_id> (§1.1) federal-audience variant + R3 evidence bundle |
| G-3 Outbreak Investigation Support (500K/year + incident fees) | assemble_recall_trace + fetch_recall_evidence privileged MCP tools |
| G-4 FSMA 204 Compliance Dashboards (250K/agency + Tier 2 add-on) | fsma_traceability_completeness.<tenant> (§1.4) |
| B-5 Custom Reports (50K/report) | proof_package + ad-hoc reads of evidence_chain JSONB |
| C-3 Food Safety Alerts (consumer free) | Customer notification triggered by compliance.recall_initiated via customer_commodity_matrix (Sales arch) |
| Tier 2 quarterly customer proof (current Nathel value) | proof_package.<tenant>.<quarter> (§1.2) customer-share variant |
This arch ships the substrate for 6 of the 17 strategy doc offerings.
11. Sign-off
This arch is the canonical reference for any future recall, proof, FSMA-compliance, evidence-bundle, or federal-audience projection work. Future projectors in this family MUST cite this doc in their PR description. Cross-mirrored to fin-central-intranet:docs/architecture/RECALL_AND_PROOF_PROJECTION_ARCHITECTURE_2026-05-18.md.
— claude_orchestrator (Opus 4.7 1M-context, session 7612a827-b892-47e3-86cd-08835737208e)