mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
* fix(supply-chain): address all code review findings from PR #2873 - Rename costIncreasePct → supplyDeficitPct (semantic correction) - Add primaryChokepointWarRiskTier to GetBypassOptionsResponse - Consolidate ThreatLevel/threatLevelToWarRiskTier into _insurance-tier.ts - Replace inline CpEntry/ChokepointStatusCacheEntry with ChokepointInfo - Add outer cachedFetchJson wrapper (3 serial Redis reads → 1 on warm path) - Add hs2 validation guard matching sibling handler pattern - Extract CHOKEPOINT_STATUS_KEY constant; eliminate string literal duplication - Add SCORE_RISK_WEIGHT/SCORE_COST_WEIGHT named constants; clamp liveScore ≥ 0 - Add Math.max(0,...) to liveScore for sub-1.0 cost multiplier corridors - Fix closurePct: req.closurePct ?? 100 (was || which falsy-coalesced zero) - Type fetchBypassOptions cargoType as CargoType (was implicit string) - Add exhaustiveness check to threatLevelToInsurancePremiumBps switch - Move TIER_RANK to module level in _insurance-tier.ts - Update WIDGET_PRO_SYSTEM_PROMPT with both new PRO RPCs * fix(supply-chain): fix supplyDeficitPct averaging and coverageDays sentinel - Remove .filter(d > 0) from productDeficits: zero-deficit products have demand and must stay in the denominator to avoid overstating the average - Clamp coverageDays = Math.max(0, effectiveCoverDays): prevents -1 net-exporter sentinel from leaking into the public API response - Update proto comment: document 0 for net exporters - Add test assertions for both contracts * chore(api-docs): regenerate OpenAPI docs for coverage_days comment update * refactor(supply-chain): use CHOKEPOINT_STATUS_KEY in chokepoint-status writer The key was extracted to cache-keys.ts in the previous commit but the primary writer (getChokepointStatus) and BOOTSTRAP_CACHE_KEYS still embedded the raw string literal. Import the constant at both sites to complete the refactor. * test: update supply-chain-v2 assertions for CHOKEPOINT_STATUS_KEY refactor Handler now imports CHOKEPOINT_STATUS_KEY as REDIS_CACHE_KEY from cache-keys.ts rather than defining a local constant. BOOTSTRAP_CACHE_KEYS also references the constant. Update source-string assertions to match the new patterns. * fix: keep BOOTSTRAP_CACHE_KEYS.chokepoints as string literal bootstrap.test.mjs enforces string-literal values in BOOTSTRAP_CACHE_KEYS via regex. CHOKEPOINT_STATUS_KEY is used in handler imports and is the primary dedup win; the static registry entry stays as-is per test contract.
796 lines
30 KiB
YAML
796 lines
30 KiB
YAML
openapi: 3.1.0
|
||
info:
|
||
title: SupplyChainService API
|
||
version: 1.0.0
|
||
paths:
|
||
/api/supply-chain/v1/get-shipping-rates:
|
||
get:
|
||
tags:
|
||
- SupplyChainService
|
||
summary: GetShippingRates
|
||
operationId: GetShippingRates
|
||
responses:
|
||
"200":
|
||
description: Successful response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/GetShippingRatesResponse'
|
||
"400":
|
||
description: Validation error
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ValidationError'
|
||
default:
|
||
description: Error response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Error'
|
||
/api/supply-chain/v1/get-chokepoint-status:
|
||
get:
|
||
tags:
|
||
- SupplyChainService
|
||
summary: GetChokepointStatus
|
||
operationId: GetChokepointStatus
|
||
responses:
|
||
"200":
|
||
description: Successful response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/GetChokepointStatusResponse'
|
||
"400":
|
||
description: Validation error
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ValidationError'
|
||
default:
|
||
description: Error response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Error'
|
||
/api/supply-chain/v1/get-critical-minerals:
|
||
get:
|
||
tags:
|
||
- SupplyChainService
|
||
summary: GetCriticalMinerals
|
||
operationId: GetCriticalMinerals
|
||
responses:
|
||
"200":
|
||
description: Successful response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/GetCriticalMineralsResponse'
|
||
"400":
|
||
description: Validation error
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ValidationError'
|
||
default:
|
||
description: Error response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Error'
|
||
/api/supply-chain/v1/get-shipping-stress:
|
||
get:
|
||
tags:
|
||
- SupplyChainService
|
||
summary: GetShippingStress
|
||
description: GetShippingStress returns carrier market data and a composite stress index.
|
||
operationId: GetShippingStress
|
||
responses:
|
||
"200":
|
||
description: Successful response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/GetShippingStressResponse'
|
||
"400":
|
||
description: Validation error
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ValidationError'
|
||
default:
|
||
description: Error response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Error'
|
||
/api/supply-chain/v1/get-country-chokepoint-index:
|
||
get:
|
||
tags:
|
||
- SupplyChainService
|
||
summary: GetCountryChokepointIndex
|
||
description: GetCountryChokepointIndex returns per-chokepoint exposure scores for a country. PRO-gated.
|
||
operationId: GetCountryChokepointIndex
|
||
parameters:
|
||
- name: iso2
|
||
in: query
|
||
description: ISO 3166-1 alpha-2 country code (uppercase).
|
||
required: false
|
||
schema:
|
||
type: string
|
||
- name: hs2
|
||
in: query
|
||
description: HS2 chapter (2-digit string). Defaults to "27" (energy/mineral fuels) when absent.
|
||
required: false
|
||
schema:
|
||
type: string
|
||
responses:
|
||
"200":
|
||
description: Successful response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/GetCountryChokepointIndexResponse'
|
||
"400":
|
||
description: Validation error
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ValidationError'
|
||
default:
|
||
description: Error response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Error'
|
||
/api/supply-chain/v1/get-bypass-options:
|
||
get:
|
||
tags:
|
||
- SupplyChainService
|
||
summary: GetBypassOptions
|
||
description: GetBypassOptions returns ranked bypass corridors for a chokepoint. PRO-gated.
|
||
operationId: GetBypassOptions
|
||
parameters:
|
||
- name: chokepointId
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
- name: cargoType
|
||
in: query
|
||
description: 'container | tanker | bulk | roro (default: "container")'
|
||
required: false
|
||
schema:
|
||
type: string
|
||
- name: closurePct
|
||
in: query
|
||
description: '0-100, percent of capacity blocked (default: 100)'
|
||
required: false
|
||
schema:
|
||
type: integer
|
||
format: int32
|
||
responses:
|
||
"200":
|
||
description: Successful response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/GetBypassOptionsResponse'
|
||
"400":
|
||
description: Validation error
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ValidationError'
|
||
default:
|
||
description: Error response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Error'
|
||
/api/supply-chain/v1/get-country-cost-shock:
|
||
get:
|
||
tags:
|
||
- SupplyChainService
|
||
summary: GetCountryCostShock
|
||
description: GetCountryCostShock returns cost shock and war risk data for a country+chokepoint. PRO-gated.
|
||
operationId: GetCountryCostShock
|
||
parameters:
|
||
- name: iso2
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
- name: chokepointId
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
- name: hs2
|
||
in: query
|
||
description: 'HS2 chapter (default: "27")'
|
||
required: false
|
||
schema:
|
||
type: string
|
||
responses:
|
||
"200":
|
||
description: Successful response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/GetCountryCostShockResponse'
|
||
"400":
|
||
description: Validation error
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ValidationError'
|
||
default:
|
||
description: Error response
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Error'
|
||
components:
|
||
schemas:
|
||
Error:
|
||
type: object
|
||
properties:
|
||
message:
|
||
type: string
|
||
description: Error message (e.g., 'user not found', 'database connection failed')
|
||
description: Error is returned when a handler encounters an error. It contains a simple error message that the developer can customize.
|
||
FieldViolation:
|
||
type: object
|
||
properties:
|
||
field:
|
||
type: string
|
||
description: The field path that failed validation (e.g., 'user.email' for nested fields). For header validation, this will be the header name (e.g., 'X-API-Key')
|
||
description:
|
||
type: string
|
||
description: Human-readable description of the validation violation (e.g., 'must be a valid email address', 'required field missing')
|
||
required:
|
||
- field
|
||
- description
|
||
description: FieldViolation describes a single validation error for a specific field.
|
||
ValidationError:
|
||
type: object
|
||
properties:
|
||
violations:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/FieldViolation'
|
||
description: List of validation violations
|
||
required:
|
||
- violations
|
||
description: ValidationError is returned when request validation fails. It contains a list of field violations describing what went wrong.
|
||
GetShippingRatesRequest:
|
||
type: object
|
||
GetShippingRatesResponse:
|
||
type: object
|
||
properties:
|
||
indices:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/ShippingIndex'
|
||
fetchedAt:
|
||
type: string
|
||
upstreamUnavailable:
|
||
type: boolean
|
||
ShippingIndex:
|
||
type: object
|
||
properties:
|
||
indexId:
|
||
type: string
|
||
name:
|
||
type: string
|
||
currentValue:
|
||
type: number
|
||
format: double
|
||
previousValue:
|
||
type: number
|
||
format: double
|
||
changePct:
|
||
type: number
|
||
format: double
|
||
unit:
|
||
type: string
|
||
history:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/ShippingRatePoint'
|
||
spikeAlert:
|
||
type: boolean
|
||
ShippingRatePoint:
|
||
type: object
|
||
properties:
|
||
date:
|
||
type: string
|
||
value:
|
||
type: number
|
||
format: double
|
||
GetChokepointStatusRequest:
|
||
type: object
|
||
GetChokepointStatusResponse:
|
||
type: object
|
||
properties:
|
||
chokepoints:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/ChokepointInfo'
|
||
fetchedAt:
|
||
type: string
|
||
upstreamUnavailable:
|
||
type: boolean
|
||
ChokepointInfo:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: string
|
||
name:
|
||
type: string
|
||
lat:
|
||
type: number
|
||
format: double
|
||
lon:
|
||
type: number
|
||
format: double
|
||
disruptionScore:
|
||
type: integer
|
||
format: int32
|
||
status:
|
||
type: string
|
||
activeWarnings:
|
||
type: integer
|
||
format: int32
|
||
congestionLevel:
|
||
type: string
|
||
affectedRoutes:
|
||
type: array
|
||
items:
|
||
type: string
|
||
description:
|
||
type: string
|
||
aisDisruptions:
|
||
type: integer
|
||
format: int32
|
||
directions:
|
||
type: array
|
||
items:
|
||
type: string
|
||
directionalDwt:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/DirectionalDwt'
|
||
transitSummary:
|
||
$ref: '#/components/schemas/TransitSummary'
|
||
flowEstimate:
|
||
$ref: '#/components/schemas/FlowEstimate'
|
||
warRiskTier:
|
||
type: string
|
||
enum:
|
||
- WAR_RISK_TIER_UNSPECIFIED
|
||
- WAR_RISK_TIER_NORMAL
|
||
- WAR_RISK_TIER_ELEVATED
|
||
- WAR_RISK_TIER_HIGH
|
||
- WAR_RISK_TIER_CRITICAL
|
||
- WAR_RISK_TIER_WAR_ZONE
|
||
description: |-
|
||
*
|
||
War risk tier derived from Lloyd's JWC Listed Areas + OSINT threat classification.
|
||
This is a FREE field (no PRO gate) — it exposes the existing server-internal
|
||
threatLevel from ChokepointConfig, making it available to clients for badges
|
||
and bypass corridor scoring.
|
||
DirectionalDwt:
|
||
type: object
|
||
properties:
|
||
direction:
|
||
type: string
|
||
dwtThousandTonnes:
|
||
type: number
|
||
format: double
|
||
wowChangePct:
|
||
type: number
|
||
format: double
|
||
TransitSummary:
|
||
type: object
|
||
properties:
|
||
todayTotal:
|
||
type: integer
|
||
format: int32
|
||
todayTanker:
|
||
type: integer
|
||
format: int32
|
||
todayCargo:
|
||
type: integer
|
||
format: int32
|
||
todayOther:
|
||
type: integer
|
||
format: int32
|
||
wowChangePct:
|
||
type: number
|
||
format: double
|
||
history:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/TransitDayCount'
|
||
riskLevel:
|
||
type: string
|
||
incidentCount7d:
|
||
type: integer
|
||
format: int32
|
||
disruptionPct:
|
||
type: number
|
||
format: double
|
||
riskSummary:
|
||
type: string
|
||
riskReportAction:
|
||
type: string
|
||
TransitDayCount:
|
||
type: object
|
||
properties:
|
||
date:
|
||
type: string
|
||
tanker:
|
||
type: integer
|
||
format: int32
|
||
cargo:
|
||
type: integer
|
||
format: int32
|
||
other:
|
||
type: integer
|
||
format: int32
|
||
total:
|
||
type: integer
|
||
format: int32
|
||
container:
|
||
type: integer
|
||
format: int32
|
||
dryBulk:
|
||
type: integer
|
||
format: int32
|
||
generalCargo:
|
||
type: integer
|
||
format: int32
|
||
roro:
|
||
type: integer
|
||
format: int32
|
||
capContainer:
|
||
type: number
|
||
format: double
|
||
capDryBulk:
|
||
type: number
|
||
format: double
|
||
capGeneralCargo:
|
||
type: number
|
||
format: double
|
||
capRoro:
|
||
type: number
|
||
format: double
|
||
capTanker:
|
||
type: number
|
||
format: double
|
||
FlowEstimate:
|
||
type: object
|
||
properties:
|
||
currentMbd:
|
||
type: number
|
||
format: double
|
||
baselineMbd:
|
||
type: number
|
||
format: double
|
||
flowRatio:
|
||
type: number
|
||
format: double
|
||
disrupted:
|
||
type: boolean
|
||
source:
|
||
type: string
|
||
hazardAlertLevel:
|
||
type: string
|
||
hazardAlertName:
|
||
type: string
|
||
GetCriticalMineralsRequest:
|
||
type: object
|
||
GetCriticalMineralsResponse:
|
||
type: object
|
||
properties:
|
||
minerals:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/CriticalMineral'
|
||
fetchedAt:
|
||
type: string
|
||
upstreamUnavailable:
|
||
type: boolean
|
||
CriticalMineral:
|
||
type: object
|
||
properties:
|
||
mineral:
|
||
type: string
|
||
topProducers:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/MineralProducer'
|
||
hhi:
|
||
type: number
|
||
format: double
|
||
riskRating:
|
||
type: string
|
||
globalProduction:
|
||
type: number
|
||
format: double
|
||
unit:
|
||
type: string
|
||
MineralProducer:
|
||
type: object
|
||
properties:
|
||
country:
|
||
type: string
|
||
countryCode:
|
||
type: string
|
||
productionTonnes:
|
||
type: number
|
||
format: double
|
||
sharePct:
|
||
type: number
|
||
format: double
|
||
GetShippingStressRequest:
|
||
type: object
|
||
GetShippingStressResponse:
|
||
type: object
|
||
properties:
|
||
carriers:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/ShippingStressCarrier'
|
||
stressScore:
|
||
type: number
|
||
format: double
|
||
description: Composite stress score 0–100 (higher = more disruption).
|
||
stressLevel:
|
||
type: string
|
||
description: '"low" | "moderate" | "elevated" | "critical".'
|
||
fetchedAt:
|
||
type: integer
|
||
format: int64
|
||
description: 'Warning: Values > 2^53 may lose precision in JavaScript'
|
||
upstreamUnavailable:
|
||
type: boolean
|
||
description: Set to true when upstream data source is unavailable and cached data is stale.
|
||
ShippingStressCarrier:
|
||
type: object
|
||
properties:
|
||
symbol:
|
||
type: string
|
||
description: Ticker or identifier (e.g., "BDRY", "ZIM").
|
||
name:
|
||
type: string
|
||
description: Human-readable name.
|
||
price:
|
||
type: number
|
||
format: double
|
||
description: Current price.
|
||
changePct:
|
||
type: number
|
||
format: double
|
||
description: Percentage change from previous close.
|
||
carrierType:
|
||
type: string
|
||
description: 'Carrier type: "etf" | "carrier" | "index".'
|
||
sparkline:
|
||
type: array
|
||
items:
|
||
type: number
|
||
format: double
|
||
description: 30-day price sparkline.
|
||
description: ShippingStressCarrier represents market stress data for a carrier or shipping index.
|
||
GetCountryChokepointIndexRequest:
|
||
type: object
|
||
properties:
|
||
iso2:
|
||
type: string
|
||
pattern: ^[A-Z]{2}$
|
||
description: ISO 3166-1 alpha-2 country code (uppercase).
|
||
hs2:
|
||
type: string
|
||
description: HS2 chapter (2-digit string). Defaults to "27" (energy/mineral fuels) when absent.
|
||
required:
|
||
- iso2
|
||
description: GetCountryChokepointIndexRequest specifies the country and optional HS2 chapter.
|
||
GetCountryChokepointIndexResponse:
|
||
type: object
|
||
properties:
|
||
iso2:
|
||
type: string
|
||
description: ISO 3166-1 alpha-2 country code echoed from the request.
|
||
hs2:
|
||
type: string
|
||
description: HS2 chapter used for the computation.
|
||
exposures:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/ChokepointExposureEntry'
|
||
primaryChokepointId:
|
||
type: string
|
||
description: Canonical ID of the chokepoint with the highest exposure score.
|
||
vulnerabilityIndex:
|
||
type: number
|
||
format: double
|
||
description: Composite vulnerability index 0–100 (weighted sum of top-3 exposures).
|
||
fetchedAt:
|
||
type: string
|
||
description: ISO timestamp of when this data was last seeded.
|
||
description: GetCountryChokepointIndexResponse returns exposure scores for all relevant chokepoints.
|
||
ChokepointExposureEntry:
|
||
type: object
|
||
properties:
|
||
chokepointId:
|
||
type: string
|
||
description: Canonical chokepoint ID from the chokepoint registry.
|
||
chokepointName:
|
||
type: string
|
||
description: Human-readable chokepoint name.
|
||
exposureScore:
|
||
type: number
|
||
format: double
|
||
description: Exposure score 0–100; higher = more dependent on this chokepoint.
|
||
coastSide:
|
||
type: string
|
||
description: Which ocean/basin side the country's ports face (atlantic, pacific, indian, med, multi, landlocked).
|
||
shockSupported:
|
||
type: boolean
|
||
description: Whether the shock model is supported for this chokepoint + hs2 combination.
|
||
description: ChokepointExposureEntry holds per-chokepoint exposure data for a country.
|
||
GetBypassOptionsRequest:
|
||
type: object
|
||
properties:
|
||
chokepointId:
|
||
type: string
|
||
cargoType:
|
||
type: string
|
||
description: 'container | tanker | bulk | roro (default: "container")'
|
||
closurePct:
|
||
type: integer
|
||
format: int32
|
||
description: '0-100, percent of capacity blocked (default: 100)'
|
||
required:
|
||
- chokepointId
|
||
GetBypassOptionsResponse:
|
||
type: object
|
||
properties:
|
||
chokepointId:
|
||
type: string
|
||
cargoType:
|
||
type: string
|
||
closurePct:
|
||
type: integer
|
||
format: int32
|
||
options:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/BypassOption'
|
||
fetchedAt:
|
||
type: string
|
||
primaryChokepointWarRiskTier:
|
||
type: string
|
||
enum:
|
||
- WAR_RISK_TIER_UNSPECIFIED
|
||
- WAR_RISK_TIER_NORMAL
|
||
- WAR_RISK_TIER_ELEVATED
|
||
- WAR_RISK_TIER_HIGH
|
||
- WAR_RISK_TIER_CRITICAL
|
||
- WAR_RISK_TIER_WAR_ZONE
|
||
description: |-
|
||
*
|
||
War risk tier derived from Lloyd's JWC Listed Areas + OSINT threat classification.
|
||
This is a FREE field (no PRO gate) — it exposes the existing server-internal
|
||
threatLevel from ChokepointConfig, making it available to clients for badges
|
||
and bypass corridor scoring.
|
||
BypassOption:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: string
|
||
name:
|
||
type: string
|
||
type:
|
||
type: string
|
||
addedTransitDays:
|
||
type: integer
|
||
format: int32
|
||
addedCostMultiplier:
|
||
type: number
|
||
format: double
|
||
capacityConstraintTonnage:
|
||
type: string
|
||
format: int64
|
||
suitableCargoTypes:
|
||
type: array
|
||
items:
|
||
type: string
|
||
activationThreshold:
|
||
type: string
|
||
waypointChokepointIds:
|
||
type: array
|
||
items:
|
||
type: string
|
||
liveScore:
|
||
type: number
|
||
format: double
|
||
bypassWarRiskTier:
|
||
type: string
|
||
enum:
|
||
- WAR_RISK_TIER_UNSPECIFIED
|
||
- WAR_RISK_TIER_NORMAL
|
||
- WAR_RISK_TIER_ELEVATED
|
||
- WAR_RISK_TIER_HIGH
|
||
- WAR_RISK_TIER_CRITICAL
|
||
- WAR_RISK_TIER_WAR_ZONE
|
||
description: |-
|
||
*
|
||
War risk tier derived from Lloyd's JWC Listed Areas + OSINT threat classification.
|
||
This is a FREE field (no PRO gate) — it exposes the existing server-internal
|
||
threatLevel from ChokepointConfig, making it available to clients for badges
|
||
and bypass corridor scoring.
|
||
notes:
|
||
type: string
|
||
GetCountryCostShockRequest:
|
||
type: object
|
||
properties:
|
||
iso2:
|
||
type: string
|
||
pattern: ^[A-Z]{2}$
|
||
chokepointId:
|
||
type: string
|
||
hs2:
|
||
type: string
|
||
description: 'HS2 chapter (default: "27")'
|
||
required:
|
||
- iso2
|
||
- chokepointId
|
||
GetCountryCostShockResponse:
|
||
type: object
|
||
properties:
|
||
iso2:
|
||
type: string
|
||
chokepointId:
|
||
type: string
|
||
hs2:
|
||
type: string
|
||
supplyDeficitPct:
|
||
type: number
|
||
format: double
|
||
description: Average refined-product supply deficit % under full closure (Gasoline/Diesel/Jet fuel/LPG average; HS 27 only)
|
||
coverageDays:
|
||
type: integer
|
||
format: int32
|
||
description: Energy stockpile coverage in days (IEA data, HS 27 only; 0 for non-energy sectors or net exporters)
|
||
warRiskPremiumBps:
|
||
type: integer
|
||
format: int32
|
||
description: War risk insurance premium in basis points for this chokepoint
|
||
warRiskTier:
|
||
type: string
|
||
enum:
|
||
- WAR_RISK_TIER_UNSPECIFIED
|
||
- WAR_RISK_TIER_NORMAL
|
||
- WAR_RISK_TIER_ELEVATED
|
||
- WAR_RISK_TIER_HIGH
|
||
- WAR_RISK_TIER_CRITICAL
|
||
- WAR_RISK_TIER_WAR_ZONE
|
||
description: |-
|
||
*
|
||
War risk tier derived from Lloyd's JWC Listed Areas + OSINT threat classification.
|
||
This is a FREE field (no PRO gate) — it exposes the existing server-internal
|
||
threatLevel from ChokepointConfig, making it available to clients for badges
|
||
and bypass corridor scoring.
|
||
hasEnergyModel:
|
||
type: boolean
|
||
description: Whether supply_deficit_pct and coverage_days are modelled (true) or unavailable (false)
|
||
unavailableReason:
|
||
type: string
|
||
description: Null/unavailable explanation for non-energy sectors
|
||
fetchedAt:
|
||
type: string
|