Frequently Asked

FAQ — how CommodityTrax scores and reports risk

The three questions buyers ask most about the FDA detention badge on /feed, the composite origin risk score on /origin-risk, and the FSMA export.

Q1 · FDA Detention Score

How is the FDA detention score on /feed computed?

The visible "score" on /feed is a severity badge — not a number. Each row in the feed renders one of three states: ALERT (red), WATCH (orange), or CLEAR (green), driven by the FDA's own advisory_level string.

The mapping is deterministic — it lives in routes/feed.js as the severityBadge() function and is reused on the proof page at routes/how-it-works.js:12-19:

  • ALERT (red) — when advisory_level contains avoid, dwpe, or refuse
  • WATCH (orange) — when it contains watch, advisory, or alert
  • CLEAR (green) — when it contains clear, ok, or pass
  • WATCH (orange) — the safe default when advisory_level is missing or unrecognized

Because this badge is derived directly from openFDA's advisory_level string, it is binary per-alert and never combines signals across rows — the feed stays scannable. Composite scoring across multiple data sources happens separately on /origin-risk.

See it live → /feed
Q2 · Origin Risk Score

How is the composite origin risk score on /origin-risk built?

The page ranks each (commodity_code, country_code) row on a 0–100 composite risk score derived from four independent signals and bucketed into a three-tier label. The full formula lives in migrations/1782300000_origin_risk_view.sql:27-42 and powers the origin_risk_v view queried by the page.

Composite score formula · 100 points FDA (40) + Harvest Pace (30) + Active Gap (20) + Limited Data (10)
  • FDA · 40 pts — linear, capped at 3 detentions → full 40. Detention count comes from fda_alerts rows in the last 90 days for the same (commodity_code, country_code) pair.
  • Harvest Pace · 30 pts — only behind-schedule adds risk. Scaled so that a 15-point deficit (e.g. pct_harvested 15% below the 5-year average) returns the full 30.
  • Active Gap · 20 pts — flat 20 whenever an unresolved row exists in supply_gaps for the same (commodity_code, country_code) pair.
  • Limited Data · 10 pts — flat 10 when commodity_origins.limited_data = true AND no observed harvest_progress row exists for the pair.

The 0–100 score is then bucketed into a tier label:

CLEAR ≥ 70
No meaningful risk signals.
WATCH ≥ 40
Elevated — review before placing orders.
ALERT < 40
Avoid — multiple compounding risk factors.

Data lineage. Each page row's grain is (commodity_code, country_code) from commodity_origins; harvest progress is the most recent harvest_progress row matched on origin = country_code; FDA detentions count fda_alerts rows in the last 90 days; open gaps count unresolved supply_gaps rows.

See it live → /origin-risk
Q3 · FSMA Export

What columns does the FSMA export contain and why?

The FSMA export is a CSV (RFC-4180) or JSON snapshot of the currently-visible /origin-risk rows, expanded to one row per (origin × FDA alert in the last 90 days). Origins with no alerts in the window appear once with NULL alert fields. The 24-column schema is defined in routes/origin-risk.js:57-66 as EXPORT_COLUMNS.

  • Commodity identitycommodity_code, commodity_name (the human-readable label from lib/codes.js), country_code (ISO-2), country_name, origin_type (import or domestic).
  • Data-quality flagsis_limited_data (incomplete coverage flag from commodity_origins.limited_data), fda_eligible (static eligibility annotation: eligible / alert / unknown).
  • Risk inputsfda_detention_count_90d, open_gap_count, pct_harvested, pct_harvested_5yr_avg, pace_delta (positive = ahead), harvest_week_ending.
  • Risk scorecomposite_risk_score (0–100) plus the bucketed risk_tier (CLEAR / WATCH / ALERT).
  • Alert detailalert_number, alert_status, supplier_name, country_origin, detention_reason, product_scope, advisory_level, detention_date, alert_source_url.

FSVP mapping (21 CFR § 1.500). Each FSVP field maps to one or more columns:

  • Suppliersupplier_name scoped by alert_number. Country-level holds still identify the supplier-set via alert_number + country_origin.
  • Country / region of origincountry_code + country_name; country_origin carries the FDA-published free-text origin when it disagrees.
  • Food (commodity / food type)commodity_code + commodity_name; product_scope narrows to foods actually covered by the alert.
  • Hazard reasondetention_reason (FDA-published DWPE / hold explanation) plus advisory_level for severity.
  • Verification datedetention_date (FDA Import Alert publication date). Origins with no alert in the window emit one row with NULL alert fields; harvest_week_ending / pct_harvested / pace_delta and is_limited_data carry the current verification signal.
  • Risk score / known riskcomposite_risk_score (0–100) with risk_tier. Supporting evidence: fda_detention_count_90d, open_gap_count, pace_delta vs pct_harvested_5yr_avg, is_limited_data.

An auditor can reconstruct a verification list straight from the CSV: sort by composite_risk_score desc for origin-level exposure, then group by alert_number to see which suppliers are linked to which hazard. The JSON envelope is { generated_at, source_url, row_count, columns: [...], rows: [...] }.

Methodology notes & caveats
  • The detention badge on /feed reflects enforcement actions, not current border status — verify with US Customs before making sourcing decisions.
  • NASS harvest percentages are estimates until final numbers are published; data is reported with a 1–2 week lag.
  • The composite risk score is a heuristic for ranking, not a guarantee. It's intended to prioritize review attention — not replace your supplier-qualification program.
  • The FSMA export is not a substitute for your own FSVP verification records; it's an input to your existing supplier verification workflow under 21 CFR § 1.500 et seq.