trade-policy) is the dashboard’s go-to surface for live trade-policy context — what’s getting restricted, where tariffs are moving, how flows are shifting, what barriers exist, and how US customs revenue is tracking as a real-time signal of tariff pass-through.
What the panel shows
Six tabs across one data-dense panel (defaultRowSpan: 2):
TabId is the union 'restrictions' | 'tariffs' | 'flows' | 'barriers' | 'revenue' | 'comtrade' (src/components/TradePolicyPanel.ts:17).
Panel id is trade-policy; canonical component is src/components/TradePolicyPanel.ts. Title resolves from i18n (panels.tradePolicy).
How you reach it
- Cmd+K: type trade, tariff, or customs.
- Availability by variant: registered and enabled by default in the full/geopolitical (
priority: 1), finance (priority: 1), and commodity (priority: 1) variants. Not present in the tech or happy variants. Source:'trade-policy'entries inFULL_PANELS,FINANCE_PANELS,COMMODITY_PANELSofsrc/config/panels.ts.
Data sources
Six response shapes from@/services/trade, each backed by a generated sebuf REST RPC in TradeService. The panel shell is free; tariff trends and Comtrade calls use premiumFetch because those two paths are premium transport paths, while restrictions, flows, barriers, and customs revenue use the public client. Customs revenue also checks the bootstrap cache key customsRevenue before falling back to the RPC.
The
revenue tab’s US-Treasury feed is particularly sensitive — see the changelog entry for “US Treasury customs revenue in Trade Policy panel” (#1663).
Trade-flow coverage
get-trade-flows is served entirely from the Railway seed; it never calls WTO per request. What that seed contains is the whole supported space:
- Reporter — any 3-digit UN M49 code the WTO
/reportersendpoint advertises. Empty defaults to840(United States). - Partner —
000(World) only. The WTO indicators behind these rows,ITS_MTV_AXandITS_MTV_AM, publish a World total and answer HTTP 204 for every named partner, so no bilateral pair is obtainable. Empty defaults to000. - Years —
1–30, inclusive of both endpoints (years=10returns 11 calendar years). The seed holds the full 30-year window per reporter and the handler slices it, so every lookback is served from the same fetch.0selects the default of10.
years is rejected with HTTP 400 rather than silently replaced by a default. A well-formed request the seed cannot answer returns empty flows plus an unavailableReason from a closed vocabulary, so a coverage gap is distinguishable from a fault:
unavailableReason is the TradeFlowUnavailableReason enum, so the closed set is discoverable from the OpenAPI schema rather than only from prose. Values are prefixed TRADE_FLOW_UNAVAILABLE_REASON_:
Fleet-level coverage is published as the
tradeFlows entry in /api/health, whose records count is the number of reporter/World pairs actually seeded; a shortfall reads COVERAGE_PARTIAL, while a stopped seeder reads STALE_SEED.
Tariff-trend coverage
get-tariff-trends is also seed-backed (premium path). The Railway seeder pre-fetches WTO MFN applied averages (TP_A_0010) and this API serves slices of that history — it never calls WTO per request.
- Reporter — any 3-digit UN M49 code the WTO
/reportersendpoint advertises. Empty defaults to840(United States). - Partner — accepted for forward compatibility;
TP_A_0010is an MFN applied average for the reporting economy and has no partner dimension, so this field never changes the answer. - Product sector — empty or
allselects the All-products aggregate, which is the only sector currently covered. Any other value is answeredNOT_COVERED. - Years —
1–30, inclusive of both endpoints (years=10returns 11 calendar years). The seed holds the full 30-year window per reporter and the handler slices it.0selects the default of10.
years is rejected with HTTP 400 rather than silently replaced by 840 / 10. A well-formed request the seed cannot answer returns empty datapoints plus an unavailableReason from the TariffTrendUnavailableReason enum (prefixed TARIFF_TREND_UNAVAILABLE_REASON_):
Fleet-level coverage is published as the
tariffTrendsUs entry in /api/health (the series name is historical; the probe is the fleet seed-meta:trade:tariffs record). A shortfall against the min-record floor reads COVERAGE_PARTIAL; a stopped seeder reads STALE_SEED.
Refresh cadence
Per-tab fetches on mount and on tab switch; no polling. Upstream seeders run on varying cadences per dataset (tariffs daily, Comtrade monthly).Tier & gating
Panel shell is free. Nopremium flag in variant registrations. The generated REST service is mixed: restrictions, flows, barriers, and customs revenue are public; get-tariff-trends and list-comtrade-flows are premium RPC paths and degrade to empty data without an entitled session or API key.
API reference
- Trade service — full schemas and query parameters for the six tab-backing RPCs.
