Files
worldmonitor/docs/api/ResilienceService.openapi.yaml
Elie Habib 502bd4472c docs(resilience): sync methodology/proto/widget to 6-domain + 3-pillar reality (#3264)
Brings every user-facing surface into alignment with the live resilience
scorer. Zero behavior change: overall_score is still the 6-domain
weighted aggregate, schemaVersion is still 2.0 default, and every
existing test continues to pass.

Surfaces touched:
- proto + OpenAPI: rewrote the ResiliencePillar + schema_version
  descriptions. 2.0 is correctly documented as default; shaped-but-empty
  language removed.
- Widget: added missing recovery: 'Recovery' label (was rendering
  literal lowercase recovery before), retitled footer data-version chip
  from Data to Seed date so it is clear the value reflects the static
  seed bundle not every live input, rewrote help tooltip for 6 domains
  and 3 pillars and called out the 0.25 recovery weight.
- Methodology doc: domains-and-weights table now carries all 6 rows
  with actual code weights (0.17/0.15/0.11/0.19/0.13/0.25), Recovery
  section header weight corrected from 1.0 to 0.25, new Pillar-combined
  score activation (pending) section with the measured Spearman 0.9935,
  top-5 movers, and the activation checklist.
- documentation.mdx + features.mdx: product blurbs updated from 5
  domains and 13 dimensions to 6 domains and 19 dimensions grouped into
  3 pillars.
- Tests: recovery-label regression pin, Seed date label pin, clarified
  pillar-schema degenerate-input semantics.

New scaffolding for defensibility:
- docs/snapshots/resilience-ranking-2026-04-21.json frozen published
  tables artifact with methodology metadata and commit SHA.
- docs/snapshots/resilience-pillar-sensitivity-2026-04-21.json live
  Redis capture (52-country sample) combining sensitivity stability
  with the current-vs-proposed Spearman comparison.
- scripts/freeze-resilience-ranking.mjs refresh script.
- scripts/compare-resilience-current-vs-proposed.mjs comparison script.
- tests/resilience-ranking-snapshot.test.mts 13 assertions auto
  discovered from any resilience-ranking-YYYY-MM-DD.json in snapshots.

Verification: npm run typecheck:all clean, 390/390 resilience tests
pass.

Follow-up: pillar-combined score activation. The sensitivity artifact
shows rank-preservation Spearman 0.9935 and no ceiling effects, which
clears the methodological bar. Blocker is messaging because every
country drops ~13 points under the penalty, so activation PR ships with
re-anchored release-gate bands, refreshed frozen ranking, and a v2.0
methodology note.
2026-04-21 22:37:27 +04:00

280 lines
11 KiB
YAML

openapi: 3.1.0
info:
title: ResilienceService API
version: 1.0.0
paths:
/api/resilience/v1/get-resilience-score:
get:
tags:
- ResilienceService
summary: GetResilienceScore
operationId: GetResilienceScore
parameters:
- name: countryCode
in: query
required: true
schema:
type: string
responses:
"200":
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/GetResilienceScoreResponse'
"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/resilience/v1/get-resilience-ranking:
get:
tags:
- ResilienceService
summary: GetResilienceRanking
operationId: GetResilienceRanking
responses:
"200":
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/GetResilienceRankingResponse'
"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.
GetResilienceScoreRequest:
type: object
properties:
countryCode:
type: string
GetResilienceScoreResponse:
type: object
properties:
countryCode:
type: string
overallScore:
type: number
format: double
level:
type: string
domains:
type: array
items:
$ref: '#/components/schemas/ResilienceDomain'
trend:
type: string
change30d:
type: number
format: double
lowConfidence:
type: boolean
imputationShare:
type: number
format: double
baselineScore:
type: number
format: double
stressScore:
type: number
format: double
stressFactor:
type: number
format: double
dataVersion:
type: string
scoreInterval:
$ref: '#/components/schemas/ScoreInterval'
pillars:
type: array
items:
$ref: '#/components/schemas/ResiliencePillar'
schemaVersion:
type: string
description: |-
Phase 2 T2.1/T2.3: "2.0" is the current default (adds pillars; keeps
overall_score / baseline_score / etc. populated for backward compat).
"1.0" is the legacy opt-out shape (pillars empty) retained for one
release cycle. Controlled at response build time by the
RESILIENCE_SCHEMA_V2_ENABLED env flag (defaults to "true" → v2).
ResilienceDomain:
type: object
properties:
id:
type: string
score:
type: number
format: double
weight:
type: number
format: double
dimensions:
type: array
items:
$ref: '#/components/schemas/ResilienceDimension'
ResilienceDimension:
type: object
properties:
id:
type: string
score:
type: number
format: double
coverage:
type: number
format: double
observedWeight:
type: number
format: double
imputedWeight:
type: number
format: double
imputationClass:
type: string
description: |-
Four-class imputation taxonomy (Phase 1 T1.7). Empty string when the
dimension has any observed data. One of: "stable-absence", "unmonitored",
"source-failure", "not-applicable". See docs/methodology/country-resilience-index.mdx.
freshness:
$ref: '#/components/schemas/DimensionFreshness'
DimensionFreshness:
type: object
properties:
lastObservedAtMs:
type: string
format: int64
description: |-
Unix milliseconds when the oldest constituent signal in this
dimension was last observed (min fetchedAt across INDICATOR_REGISTRY
entries for this dimension). 0 when no signal has ever been
observed.
staleness:
type: string
description: |-
Worst staleness level across the dimension's constituent signals,
classified by classifyStaleness against each signal's cadence.
One of: "fresh", "aging", "stale". Empty string when no signals.
ScoreInterval:
type: object
properties:
p05:
type: number
format: double
p95:
type: number
format: double
ResiliencePillar:
type: object
properties:
id:
type: string
description: '"structural-readiness" | "live-shock-exposure" | "recovery-capacity".'
score:
type: number
format: double
description: Pillar score in [0, 100], coverage-weighted mean of member domains.
weight:
type: number
format: double
description: 'Pillar weight in the pillar-combined score. Per the plan: 0.40 / 0.35 / 0.25.'
coverage:
type: number
format: double
description: Coverage in [0, 1], mean of member-domain average dimension coverage.
domains:
type: array
items:
$ref: '#/components/schemas/ResilienceDomain'
description: |-
Phase 2 T2.1/T2.3 of the country-resilience reference-grade upgrade plan.
Three-pillar response shape that regroups the 6 ResilienceDomains
(economic, infrastructure, energy, social-governance, health-food,
recovery) into long-run capacity (structural-readiness), current shock
pressure (live-shock-exposure), and recovery capability (recovery-capacity).
Pillar scores and coverage are real coverage-weighted aggregates computed
from the constituent domains; see _pillar-membership.ts for the mapping.
The top-level overall_score on GetResilienceScoreResponse remains a
domain-weighted aggregate (Σ domain.score * domain.weight) for this
release cycle; a pillar-combined score with penalty term is staged in
_shared.ts#penalizedPillarScore and validated by
scripts/validate-resilience-sensitivity.mjs ahead of the activation PR.
GetResilienceRankingRequest:
type: object
GetResilienceRankingResponse:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/ResilienceRankingItem'
greyedOut:
type: array
items:
$ref: '#/components/schemas/ResilienceRankingItem'
ResilienceRankingItem:
type: object
properties:
countryCode:
type: string
overallScore:
type: number
format: double
level:
type: string
lowConfidence:
type: boolean
overallCoverage:
type: number
format: double
rankStable:
type: boolean