Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions PRODUCTION_SURFACE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ These surfaces are part of the core production spine when their corresponding ro
token-scoped supplier correction session (`remediation`; compliance-critical,
see "Boot-critical routers" below)
- FDA export and export monitoring
- Public proof endpoints: export-bundle verification and the recall drill
- Public proof endpoints: export-bundle verification and the recall-drill endpoint (currently returns no drill data)
(`proof_verify`, `proof_recall`; tenantless and unauthenticated, see below)
- Tenant, user, API-key, supplier, and audit-log administration
- Billing routes required for customer subscription management
Expand Down Expand Up @@ -85,7 +85,7 @@ so `ENABLE_EXPERIMENTAL_ROUTERS` does not gate them:
Public export-bundle hash-chain/Merkle verifier. No auth, no tenant
context. Rate limit 10 req/min/IP.
- `proof_recall` — `POST /api/v1/proof/recall-drill` (`server/main.py:654`).
Public deterministic recall drill over a frozen synthetic dataset. No auth,
Public recall-drill endpoint. It reads no customer data and currently returns an honest empty result (`data_available: false`, no steps, no lot, no trace time, no CSV) with an explanatory message. No auth,
no tenant context. Rate limit 5 req/min/IP.

Both carry an in-module justification docstring arguing they belong to the
Expand Down
4 changes: 2 additions & 2 deletions docs/PRODUCT_DESCRIPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Accepted events are stored with tenant boundaries in PostgreSQL. The platform ev

Optional Jev assistance suggests mappings for unfamiliar CSV columns and a file's CTE when none is declared. Upload screens expose suggestions for operator review. Automatic application defaults off, requests use headers without row samples by default, and model suggestions do not replace deterministic validation. Preview and evaluation tools let operators inspect suggestions before enabling automatic application.

A browser verifier, a downloadable Python bundle verifier, and a reproducible recall drill let reviewers inspect the evidence format. Successful hash or Merkle verification establishes artifact integrity; it does not establish source-data accuracy or regulatory approval.
A browser verifier and a downloadable Python bundle verifier let reviewers inspect the evidence format. Successful hash or Merkle verification establishes artifact integrity; it does not establish source-data accuracy or regulatory approval.

## Capability and availability matrix

Expand All @@ -29,7 +29,7 @@ A browser verifier, a downloadable Python bundle verifier, and a reproducible re
| Tenant-scoped records and tamper-evident chains | [Tenant authority](../services/shared/tenant_context.py), [canonical persistence](../services/shared/canonical_persistence/writer.py), [canonical chain verification](../services/shared/canonical_persistence/verification.py), [admin audit integrity](../services/admin/app/audit_integrity.py). See [persistence cutover](persistence/dual-write-cutover.md). |
| FDA-oriented exports and request-response packages | Release-enabled: [FDA export](../services/ingestion/app/fda_export/router.py), [request workflow](../services/ingestion/app/request_workflow_router.py), [auditor API](../services/ingestion/app/auditor_router.py). |
| Readiness assessments and recall reporting | Release-enabled: [readiness](../services/ingestion/app/readiness_router.py), [recall reports](../services/ingestion/app/recall_report.py). |
| Public proof and synthetic recall drill | [Proof page](https://regengine.co/proof), [browser verifier](https://regengine.co/verify), [recall drill](https://regengine.co/proof/recall-drill), [verifier source](../frontend/public/sdk/verify_chain.py). Synthetic demonstration data. |
| Public proof and recall-drill endpoint | [Proof page](https://regengine.co/proof), [browser verifier](https://regengine.co/verify), [verifier source](../frontend/public/sdk/verify_chain.py). Synthetic verification artifacts; the recall-drill endpoint currently returns no drill data. |
| Supplier manifest remediation and correction links | Implemented in [remediation](../services/ingestion/app/remediation/) and the [buyer dashboard](../frontend/src/app/remediation/page.tsx); excluded from the production router allowlist. Notification delivery also requires recipient/provider configuration. |
| EPCIS JSON-LD export and broader recall simulations | Implemented in [EPCIS export](../services/ingestion/app/epcis_export.py) and [simulations](../services/ingestion/app/recall_simulations.py); these routers are experimental and excluded from the production allowlist. Public sample EPCIS downloads are a separate proof surface. |
| Inbound email CSV ingestion | [Postmark integration](../services/ingestion/app/email_ingest/); excluded from the production allowlist, with no self-service provisioning UI. See [rollout notes](engineering/EMAIL_INGESTION.md). |
Expand Down
2 changes: 1 addition & 1 deletion docs/security/TRUST_CLAIMS_MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Do not use these phrases in public or procurement copy without owner approval an
| COM-001 | Design-partner pricing and rate commitments are contract-controlled. | Review each use | Public / Contract | Pricing, order forms, procurement | Pricing page and executed terms | Founder / Legal | `frontend/src/components/pricing/PricingPageClient.tsx`, `frontend/src/app/pricing/page.tsx` | 2026-06-24 | "Rate controlled by your executed design-partner terms." | "Locked forever", "no increases ever" unless order form says so | Before pricing-page release |
| COM-002 | Competitor comparisons are qualitative unless individually sourced. | Review each use | Public | Pricing, sales decks | Pricing page | Product / Legal | `frontend/src/app/pricing/page.tsx`, `frontend/src/components/pricing/PricingPageClient.tsx` | 2026-06-24 | "Validate competitor capabilities directly before procurement decisions." | Checkmarks or unsupported feature claims without citations | Before pricing-page release |
| INT-001 | Integration status taxonomy is conservative and status labels are source-controlled. | Approved | Public | Trust, integrations, dashboard | Customer readiness registry | Product / Engineering | `frontend/src/lib/customer-readiness.ts`, `frontend/src/app/trust/page.tsx`, `frontend/src/app/integrations/page.tsx` | 2026-06-24 | "Implemented", "Supported", "Pilot", "Custom Scoped", "Contract-only." | "Native Bidirectional" unless truly supported | Monthly and before registry additions |
| MET-001 | Synthetic benchmark metrics are not customer ROI, SLA, or production-performance commitments. | Review each use | Public | Case studies, proof pages, sales decks | Case-study methodology and claims matrix | Product / Legal | `frontend/src/app/case-studies/page.tsx`, `frontend/src/app/proof/recall-drill/page.tsx` | 2026-06-24 | "Synthetic validation workflow modeled on leafy-greens supply chains; not customer ROI, SLA, or production-performance commitments." | "No projections", "customer-proven savings", "guaranteed recall time" without executed evidence | Before publishing metrics |
| MET-001 | Synthetic benchmark metrics are not customer ROI, SLA, or production-performance commitments. | Review each use | Public | Case studies, proof pages, sales decks | Case-study methodology and claims matrix | Product / Legal | `frontend/src/app/case-studies/page.tsx` | 2026-06-24 | "Synthetic validation workflow modeled on leafy-greens supply chains; not customer ROI, SLA, or production-performance commitments." | "No projections", "customer-proven savings", "guaranteed recall time" without executed evidence | Before publishing metrics |
| AVAIL-001 | Guided onboarding and self-serve language must reflect design-partner availability. | Review each use | Public / Contract | Pricing, case studies, onboarding pages | Trust Center maturity banner and pricing page | Product / Legal | `frontend/src/app/pricing/page.tsx`, `frontend/src/components/pricing/PricingPageClient.tsx`, `frontend/src/app/case-studies/page.tsx` | 2026-06-24 | "Guided onboarding is available for approved design-partner workspaces; timeline, support, and commercial terms are confirmed during scoping." | "Self-serve in minutes", "no contract negotiation", "public checkout available" unless billing is aligned | Before pricing-page release |
| EXT-001 | External market, retailer, and recall-cost claims require citations or conservative caveats. | Review each use | Public | Case studies, blogs, sales decks | Source citation or buyer validation | Product / Legal | `frontend/src/app/case-studies/page.tsx`, `frontend/src/app/blog/` | 2026-06-24 | "Retailer requirements vary and should be confirmed directly with each buyer." | "Walmart/Kroger require..." without current citation and qualification | Monthly and before sales use |
| BILL-001 | Public price, CTA, checkout, and order-form consistency must be verified before self-serve claims. | Review each use | Public / Contract | Pricing, checkout, terms | Billing config and executed order form | Product / Finance / Legal | `frontend/src/app/pricing/page.tsx`, `frontend/src/components/billing/PricingCheckoutButton.tsx`, `services/ingestion/app/stripe_billing/plans.py` | 2026-06-24 | "Pricing shown is indicative; executed agreement controls final plan, billing period, and checkout availability." | "Start plan" / direct checkout claims when plan IDs or billing terms are not aligned | Before billing/pricing releases |
169 changes: 39 additions & 130 deletions services/ingestion/app/proof_recall_router.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,32 @@
"""Public recall-drill endpoint.

Why this belongs in the FSMA pipeline (production-surface promotion rule
per ``PRODUCTION_SURFACE.md``):

The core production contract is::

ingest -> canonicalize -> validate -> persist evidence -> export

This router adds a public, tenantless surface that demonstrates the
*recall-response* capability built on top of the export stage. It is
the FSMA pipeline's public proof surface for recall capability: a
prospect, regulator, or trade partner can run a deterministic recall
drill against a frozen synthetic dataset and observe the wall-clock
trace time vs. the FDA 24-hour mandate, without an account, without
tenant context, and without reading any tenant data.

Endpoint: ``POST /api/v1/proof/recall-drill``

- No auth (public). Rate limit: 5 requests per minute per IP via the
shared slowapi ``limiter`` (``shared.rate_limit``).
- Operates *only* against a frozen synthetic dataset baked into this
module. The endpoint MUST NEVER read real tenant data: static
analysis of this module should show zero imports of
``shared.database``, ``CTEPersistence``, or any tenant-scoped
client.
- Output is deterministic — every call returns the same step list,
``time_to_trace_seconds`` (sum of step durations), ``lot_code``,
and ``output_csv_url``.
- The pre-generated recall CSV referenced by ``output_csv_url`` lives
in the frontend's public assets (``/samples/sample_recall_drill.csv``)
and was produced from the synthetic 7-CTE dataset.
This is a public, tenantless, unauthenticated surface (rate limit: 5
requests per minute per IP via the shared slowapi ``limiter``). It MUST
NEVER read tenant data: this module imports no ``shared.database``,
``CTEPersistence`` or other tenant-scoped client.

Because it cannot read tenant data, it has no real recall to trace. It
previously returned a frozen synthetic drill (an invented lot, invented
facilities, invented step durations and a pre-generated sample CSV).
That was fake data presented as a proof, so it was removed. The endpoint
now returns an honest empty result: no steps, no lot code, no trace time
and no CSV, with ``data_available: false``. The only populated value is
the FDA 24-hour records-production window from 21 CFR 1.1455(c)(3),
which is a regulatory constant, not data.

Returned JSON shape::

{
"steps": [
{"name": str, "duration_ms": int,
"status": "ok"|"warning"|"error", "detail": str?},
...
],
"time_to_trace_seconds": float,
"output_csv_url": str,
"lot_code": str,
"fda_24h_mandate_seconds": 86400
"data_available": false,
"steps": [],
"time_to_trace_seconds": null,
"output_csv_url": null,
"lot_code": null,
"fda_24h_mandate_seconds": 86400,
"message": str,
"timestamp": str
}
"""

Expand All @@ -61,65 +45,12 @@

router = APIRouter(prefix="/api/v1/proof", tags=["Public Proof"])


# ---------------------------------------------------------------------------
# Frozen synthetic drill -- deterministic by construction
# ---------------------------------------------------------------------------
# This corresponds to the public CSV at
# ``frontend/public/samples/sample_recall_drill.csv`` -- a known-contaminated
# romaine lot harvested at Sunny Valley Farms, traced forward through the
# 7 CTEs (harvesting, cooling, initial packing, shipping, receiving,
# transformation, shipping) into Metro Foods, Valley Wholesale, and
# SuperMart #42.
FROZEN_LOT_CODE = "SV-20240115-001"
OUTPUT_CSV_URL = "/samples/sample_recall_drill.csv"
# 21 CFR 1.1455(c)(3): records must be provided to FDA within 24 hours.
FDA_24H_MANDATE_SECONDS = 86400

# Steps mirror the synthetic frontend script so a UI consuming this
# endpoint produces the same per-step animation. Durations sum to
# 7.0 seconds — well inside the 24h FDA mandate.
_FROZEN_STEPS: tuple[dict, ...] = (
{
"name": "Identifying source lot",
"duration_ms": 1200,
"status": "ok",
"detail": (
"Loaded contaminated lot SV-20240115-001 (Romaine Lettuce, "
"500 cases) from Sunny Valley Farms (GLN 1234567890128)."
),
},
{
"name": "Tracing forward through 7 CTEs",
"duration_ms": 2400,
"status": "ok",
"detail": (
"Walked CTE-1 HARVESTING -> CTE-2 COOLING -> CTE-3 "
"INITIAL_PACKING -> CTE-4 SHIPPING -> CTE-5 RECEIVING -> "
"CTE-6 TRANSFORMATION -> CTE-7 SHIPPING. Resolved 2 child "
"lots (FC-20240116-A, FC-20240116-B) at the transformation "
"node."
),
},
{
"name": "Walking downstream graph edges",
"duration_ms": 1800,
"status": "ok",
"detail": (
"Visited 11 events across 5 facilities. Reached 3 "
"downstream receivers: Metro Foods, Valley Wholesale, "
"SuperMart #42."
),
},
{
"name": "Generating FDA-oriented recall CSV",
"duration_ms": 1600,
"status": "ok",
"detail": (
"Wrote 21 CFR §§1.1325–1.1350 Key Data Elements for each downstream "
"lot. Hash-anchored each record (SHA-256 chain integrity "
"preserved)."
),
},
NO_DATA_MESSAGE = (
"No recall drill data is available on this public endpoint. "
"Run a recall trace against your own records after signing in."
)


Expand All @@ -134,11 +65,13 @@ class DrillStep(BaseModel):


class RecallDrillResponse(BaseModel):
steps: list[DrillStep]
time_to_trace_seconds: float
output_csv_url: str
lot_code: str
data_available: bool = False
steps: list[DrillStep] = Field(default_factory=list)
time_to_trace_seconds: Optional[float] = None
output_csv_url: Optional[str] = None
lot_code: Optional[str] = None
fda_24h_mandate_seconds: int = FDA_24H_MANDATE_SECONDS
message: str = NO_DATA_MESSAGE
timestamp: str


Expand All @@ -157,22 +90,8 @@ def _hash_ip(client_host: Optional[str]) -> str:


def _build_response() -> RecallDrillResponse:
"""Build the deterministic drill response.

Pure function of module constants — no I/O, no tenant lookups.
Two calls return identical ``steps`` / ``time_to_trace_seconds``
(only ``timestamp`` differs).
"""
steps = [DrillStep(**s) for s in _FROZEN_STEPS]
total_ms = sum(s.duration_ms for s in steps)
return RecallDrillResponse(
steps=steps,
time_to_trace_seconds=round(total_ms / 1000.0, 3),
output_csv_url=OUTPUT_CSV_URL,
lot_code=FROZEN_LOT_CODE,
fda_24h_mandate_seconds=FDA_24H_MANDATE_SECONDS,
timestamp=_now_iso(),
)
"""Build the honest empty response. No I/O, no tenant lookups."""
return RecallDrillResponse(timestamp=_now_iso())


# ---------------------------------------------------------------------------
Expand All @@ -181,30 +100,20 @@ def _build_response() -> RecallDrillResponse:
@router.post(
"/recall-drill",
response_model=RecallDrillResponse,
summary="Run a deterministic recall drill against a frozen synthetic dataset",
summary="Public recall drill: returns an honest empty result (no tenant data is read)",
)
@limiter.limit("5/minute")
async def run_recall_drill(request: Request) -> RecallDrillResponse:
"""Run a public recall drill against the frozen synthetic dataset.

Takes no body. Returns a deterministic step list plus the
wall-clock ``time_to_trace_seconds`` for the synthetic drill, the
FDA 24-hour response target for client-side comparison, and the
URL of a pre-generated FDA-oriented recall CSV.
"""Return an honest empty recall-drill result.

This endpoint MUST NOT read any tenant data: it operates entirely
against module-level constants derived from
``frontend/public/samples/sample_recall_drill.csv``. No database,
queue, or tenant store is touched.
Takes no body and reads no tenant data, so there is nothing real to
trace: ``steps`` is empty, ``lot_code``, ``time_to_trace_seconds``
and ``output_csv_url`` are null, and ``data_available`` is false.
"""
ip_hash = _hash_ip(request.client.host if request.client else None)
response = _build_response()
logger.info(
"proof_recall_drill_call",
extra={
"ip_hash": ip_hash,
"lot_code": response.lot_code,
"time_to_trace_seconds": response.time_to_trace_seconds,
},
extra={"ip_hash": ip_hash, "data_available": response.data_available},
)
return response
Loading
Loading