GET /api/v1/reports/dependencies

GET /api/v1/reports/dependencies?pi_id=<uuid>
GET /api/v1/reports/dependencies?as_id=<uuid>&pi_id=<uuid>

Dependency analysis overview across three dimensions: peer AS dependencies (BGP/BMP), critical link pairs (topology), and SRLG/device failure candidates.

Auth: Any authenticated user.

Query parameters:

Response: 200 OK

{
  "peer_as_summary": [
    { "peer_as": 64512, "peer_count": 2, "total_prefixes": 150, "ipv4_space": 65536, "cidr_equiv": "/16.0", "severity": "yellow",
      "flaps": 3, "uptime_pct": 87.5, "churn_share": 75.0, "median_path_life_s": 240, "path_life_closed": 8, "path_life_open": 3 }
  ],
  "critical_pairs": [
    { "edge_a": { "u": "10.0.0.1", "v": "10.0.0.2", "link_id": "uuid" }, "edge_b": { "u": "10.0.0.3", "v": "10.0.0.4", "link_id": "uuid" }, "small_side": 3, "shared_srlgs": ["fiber-ring-1"] }
  ],
  "srlg_devices": [
    { "type": "device", "id": "uuid", "name": "core-rtr-1", "member_count": 0, "neighbor_count": 4 }
  ],
  "bgp_available": true,
  "peer_sessions": [
    { "device_id": "uuid", "hostname": "gw1", "peer_ip": "198.51.100.1", "address_family": "ipv4", "peer_as": 64512,
      "peer_type": "ebgp", "state": "up", "flaps": 3, "uptime_seconds": 6300, "window_seconds": 86400,
      "churn_opens": 412, "last_dump_seconds": 12.5, "last_dump_routes": 902 }
  ],
  "observability": { "peer_count": 4, "peers": [], "suppressions": [] },
  "window_from": "2026-08-17T00:00:00Z",
  "window_to": "2026-08-18T00:00:00Z",
  "full_rib_available": true,
  "computation_time_ms": 42
}

Severity (D-04): red = single-homed + >50% no-alternative, yellow = multi-homed with some unprotected, green = fully protected.

Scorecard block: peer_sessions carries one window scorecard per recorded session — a session that is down right now still scores (and bgp_available is true whenever session history exists, even with an empty live summary; that is exactly the BMP-settle case). Recorded uptime is clamped to the window; flaps counts in-window state transitions with seed re-baselines excluded; churn_opens counts the candidate-path opens received from that session; last_dump_seconds/last_dump_routes measure the table dump after the last session-up (receive-time based over a 10-minute horizon — an approximation by design, not a convergence measurement). Sentinel discipline: -1 means "not measurable" — no enabled history_mode: full target on the session's device (churn/dump), no sessions recorded (the aggregated summary columns), or no full-RIB history at all (median_path_life_s) — and is never conflated with a genuine quiet 0. The aggregated summary columns weight uptime by session-time, and churn_share is the AS's share of ALL measurable sessions' churn (shares sum to ≤100%). observability embeds the blind-spot ledger for the same window; read it before reading stability off quiet numbers, and treat full_rib_available: false as "churn/half-life emptiness is a coverage refusal, not stability".

ipv4_space semantics: the peer AS's unique IPv4 address space — the interval union of its distinct prefixes, so a covering aggregate and its more-specifics count once — and the report's sort key. The same union semantics apply to ipv4_space_lost, the per-device ipv4_space, and total_ipv4_space in the dependency-impact response below (the drill-down's per-prefix ipv4_space reports that one prefix's own size).