mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-26 01:24:59 +02:00
feat(supply-chain): Sprint D — GetSectorDependency RPC + vendor route-intelligence API + webhooks (#2905)
* feat(supply-chain): Sprint D — GetSectorDependency RPC + vendor route-intelligence API + webhooks * fix(supply-chain): move bypass-corridors + chokepoint-registry to server/_shared to fix api/ boundary violations * fix(supply-chain): webhooks — persist secret, fix sub-resource routing, add ownership check * fix(supply-chain): address PR #2905 review findings - Use SHA-256(apiKey) for ownerTag instead of last-12-chars (unambiguous ownership) - Implement GET /api/v2/shipping/webhooks list route via per-owner Redis Set index - Tighten SSRF: https-only, expanded metadata hostname blocklist, document DNS rebinding edge-runtime limitation - Fix get-sector-dependency.ts stale src/config/ imports → server/_shared/ (Greptile P1) * fix(supply-chain): getSectorDependency returns blank primaryChokepointId for landlocked countries computeExposures() previously mapped over all of CHOKEPOINT_REGISTRY even when nearestRouteIds was empty, producing a full array of score-0 entries in registry insertion order. The caller's exposures[0] then picked the first registry entry (Suez) as the "primary" chokepoint despite primaryChokepointExposure = 0. LI, AD, SM, BT and other landlocked countries were all silently assigned a fake chokepoint. Fix: guard at the top of computeExposures() -- return [] when input is empty so primaryChokepointId stays '' and primaryChokepointExposure stays 0.
This commit is contained in:
@@ -231,6 +231,44 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
/api/supply-chain/v1/get-sector-dependency:
|
||||
get:
|
||||
tags:
|
||||
- SupplyChainService
|
||||
summary: GetSectorDependency
|
||||
description: GetSectorDependency returns dependency flags and risk profile for a country+HS2 sector. PRO-gated.
|
||||
operationId: GetSectorDependency
|
||||
parameters:
|
||||
- name: iso2
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- name: hs2
|
||||
in: query
|
||||
description: HS2 chapter code, e.g. "27" (mineral fuels), "85" (electronics)
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GetSectorDependencyResponse'
|
||||
"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:
|
||||
@@ -793,3 +831,55 @@ components:
|
||||
description: Null/unavailable explanation for non-energy sectors
|
||||
fetchedAt:
|
||||
type: string
|
||||
GetSectorDependencyRequest:
|
||||
type: object
|
||||
properties:
|
||||
iso2:
|
||||
type: string
|
||||
pattern: ^[A-Z]{2}$
|
||||
hs2:
|
||||
type: string
|
||||
description: HS2 chapter code, e.g. "27" (mineral fuels), "85" (electronics)
|
||||
required:
|
||||
- iso2
|
||||
- hs2
|
||||
GetSectorDependencyResponse:
|
||||
type: object
|
||||
properties:
|
||||
iso2:
|
||||
type: string
|
||||
hs2:
|
||||
type: string
|
||||
hs2Label:
|
||||
type: string
|
||||
description: Human-readable HS2 chapter name.
|
||||
flags:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- DEPENDENCY_FLAG_UNSPECIFIED
|
||||
- DEPENDENCY_FLAG_SINGLE_SOURCE_CRITICAL
|
||||
- DEPENDENCY_FLAG_SINGLE_CORRIDOR_CRITICAL
|
||||
- DEPENDENCY_FLAG_COMPOUND_RISK
|
||||
- DEPENDENCY_FLAG_DIVERSIFIABLE
|
||||
description: DependencyFlag classifies how a country+sector dependency can fail.
|
||||
primaryExporterIso2:
|
||||
type: string
|
||||
description: ISO2 of the country supplying the largest share of this sector's imports.
|
||||
primaryExporterShare:
|
||||
type: number
|
||||
format: double
|
||||
description: Share of imports from the primary exporter (0–1). 0 = no Comtrade data available.
|
||||
primaryChokepointId:
|
||||
type: string
|
||||
description: Chokepoint ID with the highest exposure score for this country+sector.
|
||||
primaryChokepointExposure:
|
||||
type: number
|
||||
format: double
|
||||
description: Exposure score for the primary chokepoint (0–100).
|
||||
hasViableBypass:
|
||||
type: boolean
|
||||
description: Whether at least one viable bypass corridor exists for the primary chokepoint.
|
||||
fetchedAt:
|
||||
type: string
|
||||
|
||||
Reference in New Issue
Block a user