feat(resilience): add service proto and stub handlers (#2657)

* feat(resilience): add service proto and stub handlers

Add the worldmonitor.resilience.v1 proto package, generated client/server artifacts, edge routing, and zero-state handler stubs so the domain is deployable before the seed and scoring layers land.

Validation:
- PATH="/Users/lucaspassos/go/bin:/Users/lucaspassos/.codex/tmp/arg0/codex-arg06nbVvG:/Users/lucaspassos/.antigravity/antigravity/bin:/Users/lucaspassos/.local/bin:/Users/lucaspassos/.codeium/windsurf/bin:/Users/lucaspassos/Library/Python/3.12/bin:/Library/Frameworks/Python.framework/Versions/3.12/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pkg/env/active/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/opt/homebrew/bin:/Applications/Codex.app/Contents/Resources" make generate
- PATH="/Users/lucaspassos/go/bin:/Users/lucaspassos/.codex/tmp/arg0/codex-arg06nbVvG:/Users/lucaspassos/.antigravity/antigravity/bin:/Users/lucaspassos/.local/bin:/Users/lucaspassos/.codeium/windsurf/bin:/Users/lucaspassos/Library/Python/3.12/bin:/Library/Frameworks/Python.framework/Versions/3.12/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pkg/env/active/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/opt/homebrew/bin:/Applications/Codex.app/Contents/Resources" npx tsx --test tests/route-cache-tier.test.mjs tests/edge-functions.test.mjs
- npm run typecheck (fails on upstream Dodo/Clerk baseline)
- npm run typecheck:api (fails on upstream vitest baseline)
- npm run test:data (fails on upstream dodopayments-checkout baseline via tests/runtime-config-panel-visibility.test.mjs)

* fix(resilience): add countryCode validation to get-resilience-score

Throw ValidationError when countryCode is missing instead of silently
returning a zero-state response with an empty string country code.

* fix(resilience): validate countryCode format and mark required in spec

- Trim whitespace and reject non-ISO-3166-1 alpha-2 codes to prevent
  cache pollution from malformed aliases (e.g. 'USA', '  us  ', 'foobar')
- Add required: true to proto QueryConfig so generated OpenAPI spec
  matches runtime validation behavior
- Regenerated OpenAPI artifacts via make generate

---------

Co-authored-by: Elie Habib <elie.habib@gmail.com>
This commit is contained in:
Lucas Passos
2026-04-04 05:04:46 +01:00
committed by GitHub
parent e0fc8bc136
commit 4b67012260
14 changed files with 660 additions and 0 deletions

View File

@@ -0,0 +1 @@
{"components":{"schemas":{"Error":{"description":"Error is returned when a handler encounters an error. It contains a simple error message that the developer can customize.","properties":{"message":{"description":"Error message (e.g., 'user not found', 'database connection failed')","type":"string"}},"type":"object"},"FieldViolation":{"description":"FieldViolation describes a single validation error for a specific field.","properties":{"description":{"description":"Human-readable description of the validation violation (e.g., 'must be a valid email address', 'required field missing')","type":"string"},"field":{"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')","type":"string"}},"required":["field","description"],"type":"object"},"GetResilienceRankingRequest":{"type":"object"},"GetResilienceRankingResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ResilienceRankingItem"},"type":"array"}},"type":"object"},"GetResilienceScoreRequest":{"properties":{"countryCode":{"type":"string"}},"type":"object"},"GetResilienceScoreResponse":{"properties":{"change30d":{"format":"double","type":"number"},"countryCode":{"type":"string"},"cronbachAlpha":{"format":"double","type":"number"},"domains":{"items":{"$ref":"#/components/schemas/ResilienceDomain"},"type":"array"},"level":{"type":"string"},"lowConfidence":{"type":"boolean"},"overallScore":{"format":"double","type":"number"},"trend":{"type":"string"}},"type":"object"},"ResilienceDimension":{"properties":{"coverage":{"format":"double","type":"number"},"id":{"type":"string"},"score":{"format":"double","type":"number"}},"type":"object"},"ResilienceDomain":{"properties":{"dimensions":{"items":{"$ref":"#/components/schemas/ResilienceDimension"},"type":"array"},"id":{"type":"string"},"score":{"format":"double","type":"number"},"weight":{"format":"double","type":"number"}},"type":"object"},"ResilienceRankingItem":{"properties":{"countryCode":{"type":"string"},"level":{"type":"string"},"lowConfidence":{"type":"boolean"},"overallScore":{"format":"double","type":"number"}},"type":"object"},"ValidationError":{"description":"ValidationError is returned when request validation fails. It contains a list of field violations describing what went wrong.","properties":{"violations":{"description":"List of validation violations","items":{"$ref":"#/components/schemas/FieldViolation"},"type":"array"}},"required":["violations"],"type":"object"}}},"info":{"title":"ResilienceService API","version":"1.0.0"},"openapi":"3.1.0","paths":{"/api/resilience/v1/get-resilience-ranking":{"get":{"operationId":"GetResilienceRanking","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetResilienceRankingResponse"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error response"}},"summary":"GetResilienceRanking","tags":["ResilienceService"]}},"/api/resilience/v1/get-resilience-score":{"get":{"operationId":"GetResilienceScore","parameters":[{"in":"query","name":"countryCode","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetResilienceScoreResponse"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error response"}},"summary":"GetResilienceScore","tags":["ResilienceService"]}}}}