Files
worldmonitor/docs/api/InfrastructureService.openapi.yaml
Sebastien Melki e6285e3de0 Add cable health scoring via sebuf InfrastructureService (#220)
* feat: add cable health scoring via sebuf InfrastructureService

Port submarine cable health monitoring from PR #134 to the sebuf
architecture. Adds GetCableHealth RPC to InfrastructureService that
analyzes NGA maritime warnings to detect cable faults and repair
activity, computing health scores with time-decay.

- Proto: GetCableHealthRequest/Response, CableHealthRecord, evidence
- Handler: NGA warning fetch, cable matching (name + proximity), signal
  processing, health computation with redis caching
- Client: circuit breaker, proto enum → frontend string adapter, 1-min cache
- Frontend: health-based cable coloring (fault=red, degraded=orange),
  evidence display in cable popup, SVG + DeckGL support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review feedback for cable health scoring

- Fix geographic proximity: use cosine-latitude correction instead of
  raw Euclidean distance on lat/lon degrees, return distanceKm directly
- Fix signal kind: use 'cable_advisory' (not 'operator_fault') for
  non-fault NGA warnings so advisories don't trigger fault status
- Parallelize loadCableActivity + loadCableHealth with Promise.all
- Remove console.log from client-side cable-health service
- Add in-memory fallback cache on server so transient Redis+NGA
  failures serve stale data instead of empty response

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 03:22:05 +04:00

557 lines
24 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
openapi: 3.1.0
info:
title: InfrastructureService API
version: 1.0.0
paths:
/api/infrastructure/v1/list-internet-outages:
post:
tags:
- InfrastructureService
summary: ListInternetOutages
description: ListInternetOutages retrieves detected internet outages from Cloudflare Radar.
operationId: ListInternetOutages
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ListInternetOutagesRequest'
required: true
responses:
"200":
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ListInternetOutagesResponse'
"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/infrastructure/v1/list-service-statuses:
post:
tags:
- InfrastructureService
summary: ListServiceStatuses
description: ListServiceStatuses retrieves operational status of monitored external services.
operationId: ListServiceStatuses
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ListServiceStatusesRequest'
required: true
responses:
"200":
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ListServiceStatusesResponse'
"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/infrastructure/v1/get-temporal-baseline:
post:
tags:
- InfrastructureService
summary: GetTemporalBaseline
description: GetTemporalBaseline checks current activity count against stored baseline for anomaly detection.
operationId: GetTemporalBaseline
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/GetTemporalBaselineRequest'
required: true
responses:
"200":
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/GetTemporalBaselineResponse'
"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/infrastructure/v1/record-baseline-snapshot:
post:
tags:
- InfrastructureService
summary: RecordBaselineSnapshot
description: RecordBaselineSnapshot batch-updates baseline statistics using Welford's online algorithm.
operationId: RecordBaselineSnapshot
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/RecordBaselineSnapshotRequest'
required: true
responses:
"200":
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/RecordBaselineSnapshotResponse'
"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/infrastructure/v1/get-cable-health:
post:
tags:
- InfrastructureService
summary: GetCableHealth
description: GetCableHealth computes health status for submarine cables from NGA maritime warning signals.
operationId: GetCableHealth
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/GetCableHealthRequest'
required: true
responses:
"200":
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/GetCableHealthResponse'
"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.
ListInternetOutagesRequest:
type: object
properties:
timeRange:
$ref: '#/components/schemas/TimeRange'
pagination:
$ref: '#/components/schemas/PaginationRequest'
country:
type: string
description: Optional country filter (ISO 3166-1 alpha-2).
description: ListInternetOutagesRequest specifies filters for retrieving internet outages.
TimeRange:
type: object
properties:
start:
type: integer
format: int64
description: 'Start of the time range (inclusive), as Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
end:
type: integer
format: int64
description: 'End of the time range (inclusive), as Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
description: |-
TimeRange represents a time interval defined by a start and end timestamp.
Used for filtering data within a specific time period.
PaginationRequest:
type: object
properties:
pageSize:
type: integer
maximum: 100
minimum: 1
format: int32
description: Maximum number of items to return per page (1 to 100).
cursor:
type: string
description: Opaque cursor for fetching the next page. Empty string for the first page.
description: PaginationRequest specifies cursor-based pagination parameters for list endpoints.
ListInternetOutagesResponse:
type: object
properties:
outages:
type: array
items:
$ref: '#/components/schemas/InternetOutage'
pagination:
$ref: '#/components/schemas/PaginationResponse'
description: ListInternetOutagesResponse contains internet outages matching the request.
InternetOutage:
type: object
properties:
id:
type: string
minLength: 1
description: Unique outage identifier.
title:
type: string
description: Outage title.
link:
type: string
description: URL to the outage report.
description:
type: string
description: Outage description.
detectedAt:
type: integer
format: int64
description: 'Detection time, as Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
country:
type: string
description: Affected country (ISO 3166-1 alpha-2).
region:
type: string
description: Affected region within the country.
location:
$ref: '#/components/schemas/GeoCoordinates'
severity:
type: string
enum:
- OUTAGE_SEVERITY_UNSPECIFIED
- OUTAGE_SEVERITY_PARTIAL
- OUTAGE_SEVERITY_MAJOR
- OUTAGE_SEVERITY_TOTAL
description: |-
OutageSeverity represents the severity of an internet outage.
Maps to TS union: 'partial' | 'major' | 'total'.
categories:
type: array
items:
type: string
description: Affected infrastructure categories.
cause:
type: string
description: Root cause, if determined.
outageType:
type: string
description: Outage type classification.
endedAt:
type: integer
format: int64
description: 'End time of the outage, as Unix epoch milliseconds. Zero if ongoing.. Warning: Values > 2^53 may lose precision in JavaScript'
required:
- id
description: InternetOutage represents a detected internet outage event from Cloudflare Radar.
GeoCoordinates:
type: object
properties:
latitude:
type: number
maximum: 90
minimum: -90
format: double
description: Latitude in decimal degrees (-90 to 90).
longitude:
type: number
maximum: 180
minimum: -180
format: double
description: Longitude in decimal degrees (-180 to 180).
description: GeoCoordinates represents a geographic location using WGS84 coordinates.
PaginationResponse:
type: object
properties:
nextCursor:
type: string
description: Cursor for fetching the next page. Empty string indicates no more pages.
totalCount:
type: integer
format: int32
description: Total count of items matching the query, if known. Zero if the total is unknown.
description: PaginationResponse contains pagination metadata returned alongside list results.
ListServiceStatusesRequest:
type: object
properties:
status:
type: string
enum:
- SERVICE_OPERATIONAL_STATUS_UNSPECIFIED
- SERVICE_OPERATIONAL_STATUS_OPERATIONAL
- SERVICE_OPERATIONAL_STATUS_DEGRADED
- SERVICE_OPERATIONAL_STATUS_PARTIAL_OUTAGE
- SERVICE_OPERATIONAL_STATUS_MAJOR_OUTAGE
- SERVICE_OPERATIONAL_STATUS_MAINTENANCE
description: ServiceOperationalStatus represents the current status of a service.
description: ListServiceStatusesRequest specifies filters for retrieving service statuses.
ListServiceStatusesResponse:
type: object
properties:
statuses:
type: array
items:
$ref: '#/components/schemas/ServiceStatus'
description: ListServiceStatusesResponse contains service operational statuses.
ServiceStatus:
type: object
properties:
id:
type: string
description: Service identifier.
name:
type: string
description: Service display name.
status:
type: string
enum:
- SERVICE_OPERATIONAL_STATUS_UNSPECIFIED
- SERVICE_OPERATIONAL_STATUS_OPERATIONAL
- SERVICE_OPERATIONAL_STATUS_DEGRADED
- SERVICE_OPERATIONAL_STATUS_PARTIAL_OUTAGE
- SERVICE_OPERATIONAL_STATUS_MAJOR_OUTAGE
- SERVICE_OPERATIONAL_STATUS_MAINTENANCE
description: ServiceOperationalStatus represents the current status of a service.
description:
type: string
description: Status description.
url:
type: string
description: Service URL or homepage.
checkedAt:
type: integer
format: int64
description: 'Last status check time, as Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
latencyMs:
type: integer
format: int32
description: Response latency in milliseconds.
description: ServiceStatus represents the operational status of a monitored external service.
GetTemporalBaselineRequest:
type: object
properties:
type:
type: string
minLength: 1
description: 'Activity type: "military_flights", "vessels", "protests", "news", "ais_gaps", "satellite_fires".'
region:
type: string
description: Geographic region key, defaults to "global".
count:
type: number
format: double
description: Current observed count to compare against baseline.
required:
- type
description: GetTemporalBaselineRequest checks current activity count against stored baseline.
GetTemporalBaselineResponse:
type: object
properties:
anomaly:
$ref: '#/components/schemas/BaselineAnomaly'
baseline:
$ref: '#/components/schemas/BaselineStats'
learning:
type: boolean
description: True if insufficient samples have been collected.
sampleCount:
type: integer
format: int32
description: Current number of samples stored.
samplesNeeded:
type: integer
format: int32
description: Minimum samples required before anomaly detection activates.
error:
type: string
description: Error message if request was invalid.
description: GetTemporalBaselineResponse returns anomaly info or learning status.
BaselineAnomaly:
type: object
properties:
zScore:
type: number
format: double
description: Number of standard deviations from the mean.
severity:
type: string
description: 'Severity label: "critical", "high", "medium", "normal".'
multiplier:
type: number
format: double
description: Ratio of current count to baseline mean.
description: BaselineAnomaly describes a detected deviation from historical baseline.
BaselineStats:
type: object
properties:
mean:
type: number
format: double
description: Running mean of observed counts.
stdDev:
type: number
format: double
description: Standard deviation derived from Welford's M2.
sampleCount:
type: integer
format: int32
description: Number of samples incorporated so far.
description: BaselineStats contains the running statistics for a baseline key.
RecordBaselineSnapshotRequest:
type: object
properties:
updates:
type: array
items:
$ref: '#/components/schemas/BaselineUpdate'
description: RecordBaselineSnapshotRequest batch-updates baselines using Welford's online algorithm.
BaselineUpdate:
type: object
properties:
type:
type: string
minLength: 1
description: Activity type key.
region:
type: string
description: Geographic region key, defaults to "global".
count:
type: number
format: double
description: Observed count value.
required:
- type
description: BaselineUpdate is a single metric observation to incorporate into the running baseline.
RecordBaselineSnapshotResponse:
type: object
properties:
updated:
type: integer
format: int32
description: Number of baselines that were written.
error:
type: string
description: Error message if the request was invalid.
description: RecordBaselineSnapshotResponse reports how many baselines were successfully updated.
GetCableHealthRequest:
type: object
description: GetCableHealthRequest requests the current health status of all monitored submarine cables.
GetCableHealthResponse:
type: object
properties:
generatedAt:
type: integer
format: int64
description: 'Generation timestamp, as Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
cables:
type: object
additionalProperties:
$ref: '#/components/schemas/CableHealthRecord'
description: Health records keyed by cable identifier.
description: GetCableHealthResponse contains health status for submarine cables with active signals.
CablesEntry:
type: object
properties:
key:
type: string
value:
$ref: '#/components/schemas/CableHealthRecord'
CableHealthRecord:
type: object
properties:
status:
type: string
enum:
- CABLE_HEALTH_STATUS_UNSPECIFIED
- CABLE_HEALTH_STATUS_OK
- CABLE_HEALTH_STATUS_DEGRADED
- CABLE_HEALTH_STATUS_FAULT
description: CableHealthStatus represents the computed health status of a submarine cable.
score:
type: number
format: double
description: Composite health score (0.0 = healthy, 1.0 = confirmed fault).
confidence:
type: number
format: double
description: Confidence in the health assessment (0.01.0).
lastUpdated:
type: integer
format: int64
description: 'Last signal update time, as Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
evidence:
type: array
items:
$ref: '#/components/schemas/CableHealthEvidence'
description: CableHealthRecord contains the computed health status and supporting evidence for a cable.
CableHealthEvidence:
type: object
properties:
source:
type: string
description: Evidence source (e.g. "NGA").
summary:
type: string
description: Human-readable summary of the evidence.
ts:
type: integer
format: int64
description: 'Evidence timestamp, as Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
description: CableHealthEvidence represents a single piece of evidence supporting a health assessment.