ROA summary

GET /api/v1/bgp/roa/summary

GET /api/v1/bgp/roa/summary?as_id=<uuid>

The tenant's ROA state: the open rule count per source (with last import time), live candidate validation counts, and per-session invalid counts — the mandatory coverage honesty (plan 3c): a session showing zero invalids may simply be filtered upstream of BMP, so "invalid-free" is not validation coverage and must never be read as a green light.

Auth: any authenticated user. Response 200 OK:

{
  "open_roas": 3120,
  "sources": [ { "source": "dn42", "count": 3120, "last_import": "2026-08-18T00:00:00Z" } ],
  "live_valid": 2380, "live_invalid": 12, "live_unknown": 148,
  "session_invalids": [ { "device_id": "uuid", "peer_ip": "172.20.0.1", "address_family": "ipv4", "peer_as": 4242420000, "invalids": 12 } ]
}

roa_status on the candidate readers (join-at-read): GET /bgp/rib-paths rows carry roa_status (valid | invalid | unknown, RFC 6811 against the open ROAs) and GET /bgp/history/candidates intervals carry it as of each interval's start (a registry change never rewrites what an old candidate was). The field is absent when the tenant has no ROAs loaded (no badge, never a fake "unknown" that implies validation is running) or when the row carries no origin.