How the work gets done

Denied-Party Screener

Screens importer, consignee, and supplier against the US government denied-party lists.

3 min readUpdated Jul 17, 2026

Deterministic service (not an LLM). Fuzzy-matches every party on an entry against US sanctions and watch lists. Auditable, reproducible, defensible.

What it does

Takes the supplier, importer, and consignee names off an entry and fuzzy-matches them against 31,400+ entity records from OpenSanctions us_trade_csl — the consolidated US trade screening list. Returns a band (block / review / watch / clear) per party with the matched entity, source list, and similarity score.

Why no LLM here: a denied-party hit must be reproducible across runs, must be cite-able in a CBP audit, and must never hallucinate. A pg_trgm similarity score with a documented cutoff is defensible; a model's "I think this looks like Hoshine" is not.

Inputs

{
  parties: {
    supplier?:  { name: string; country?: string };
    importer?:  { name: string; country?: string };
    consignee?: { name: string; country?: string };
  };
  origin?: string;                  // for UFLPA-sensitive geographic flags
  htsChapter?: string;              // for UFLPA-sensitive chapter flags (52, 54, 55, 61, 62, 64)
}

Outputs

{
  band: 'block' | 'review' | 'watch' | 'clear',
  blocking: boolean,                // true if any party is in `block` band
  hits: [
    {
      party: 'supplier',
      partyName: 'Xinjiang Apparel Mfg Co.',
      matched: 'XINJIANG APPAREL MFG. COMPANY LTD',
      score: 1.0,
      list: 'UFLPA',                // 'OFAC_SDN' | 'BIS_ENTITY' | 'UFLPA' | 'BIS_DENIED' | 'BIS_UNVERIFIED' | 'STATE_NONPROL'
      band: 'block',
      sourceUrl: 'https://www.dhs.gov/uflpa-entity-list',
    },
  ],
  topHit: { … },                    // highest-score hit across all parties
  geographicFlags: [                // non-entity-match flags
    { type: 'UFLPA_chapter_sensitive', detail: 'China-origin cotton (chapter 52)' },
  ],
}

When it runs

  • Every entry, automatically — in the draft → ai_review transition. The result is stored and surfaced as a header banner in the drawer.
  • Every Simulation — runs on the supplier name pulled from the PO so the user sees the band before any commitment.
  • On-demand from the supplier passport — broker clicks "Re-screen" to pick up newly-added entries to the sanctions lists.
  • On data refresh — when the screening lists refresh from OpenSanctions, all open entries are re-screened.

Dependencies

  • OpenSanctions us_trade_csl — 31.4K entities, consolidated from:
    • OFAC SDN (Treasury)
    • BIS Entity List (Commerce)
    • DHS UFLPA Entity List
    • BIS Denied Persons List
    • BIS Unverified List
    • State Department non-proliferation lists
  • Postgres with pg_trgm extension for trigram similarity.
  • Corporate-suffix normalization — strips "Co., Ltd.", "Inc.", "GmbH", "Pvt.", "JSC", etc. before scoring, so "Hoshine Silicon Industry Co., Ltd." and "Hoshine Silicon" both resolve at 1.0.

What success looks like

Screens every party on the entry — importer, consignee, and supplier — against the full set of US denied-party lists in under a second, tuned so that a true match is never missed (recall is the priority; a broker would rather clear a near-miss than let a real hit through). The lists are refreshed daily, so screening always runs against the current denied-party universe.

The bands themselves are chosen to be CBP-defensible:

BandScore cutoffWhat it means
block≥ 0.55High-confidence match. Broker must clear before transmit.
review≥ 0.40Likely match — surface to broker.
watch≥ 0.35Possible alias — investigate.
clear< 0.35No actionable match.

What it does NOT do

  • Does not make the screening decision. It surfaces hits with evidence; the broker decides whether to dismiss (with a reason code) or hold the entry.
  • Does not screen against EU, UK, or UN lists today. US-only — adding EU consolidated_eu is on the Q4 roadmap.
  • Does not rank or interpret matches with an LLM. Future LLM re-ranking pass to distinguish a true match from a generic word collision is on the roadmap (see AI architecture) but is NOT in production yet — the deterministic scoring is.
  • Does not check DOB, address, or program-specific eligibility (e.g. USMCA certificate validity). Out of scope.
  • Does not monitor for changes after the entry clears — that's a separate audit concern.

Roadmap

  • Q3 2026 — LLM re-ranking pass on review and watch band hits to separate true alias matches from generic word collisions. The deterministic score stays as the primary signal; the LLM is a secondary confidence input only.
  • Q3 2026 — Add EU consolidated list + UK FCDO list for customers doing transshipment.
  • Q4 2026 — Beneficial-ownership chain screening (today we screen only the parties named on the entry; this would walk the corporate graph one level).
  • Q4 2026 — Address-based screening (some Entity List records have address-only entries; we'd parse the shipper address off the BoL).
Ready to see it live?

Put your own book of entries through Commers.