{"openapi":"3.0.3","info":{"title":"AS204921 gobgp-platform API","version":"2026-09-10","description":"稳定接口集。认证:`Authorization: Bearer <api token>`(POST /api/auth/tokens 创建,scope read/write/admin)或浏览器会话 Cookie。未列出的 /api 路径为内部接口。"},"servers":[{"url":"https://gobgp.yunzheng.space"}],"tags":[{"name":"auth"},{"name":"nodes"},{"name":"sessions"},{"name":"push"},{"name":"prefixes"},{"name":"orbit"},{"name":"tunnels"},{"name":"ospf"},{"name":"topology"},{"name":"rdns"},{"name":"telemetry"},{"name":"anycast"},{"name":"agent"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer"},"cookie":{"type":"apiKey","in":"cookie","name":"session"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]},"IpamEventKind":{"type":"string","enum":["created","updated","released","route_installed","route_failed","block.created","block.updated","block.deleted"],"description":"block.* 为块(VPC / 子网)事件:allocation_id 空、prefix_id 填,payload 带 block_id / cidr / name / kind / scope / node_id / external_ref / tenant_ref / parent_block_id"},"IpamMapsTo":{"type":"object","nullable":true,"properties":{"allocation_id":{"type":"integer"},"cidr":{"type":"string"},"external_ref":{"type":"string","nullable":true}}},"IpamNatMapEntry":{"type":"object","properties":{"public_cidr":{"type":"string"},"private_cidr":{"type":"string"},"allocation_id":{"type":"integer"},"private_allocation_id":{"type":"integer"},"vpc_block_id":{"type":"integer","nullable":true,"description":"私网分配所在块向上追到的顶层块(VPC)"},"subnet_block_id":{"type":"integer","nullable":true,"description":"所在块本身(只有它有父块时才填)"},"tenant_ref":{"type":"string","nullable":true},"external_ref":{"type":"string","nullable":true,"description":"公网分配的 external_ref"},"nexthop":{"type":"string","nullable":true},"attach":{"type":"string","enum":["static_nexthop","node_local"]}}},"IpamRouteState":{"type":"object","properties":{"node_id":{"type":"integer"},"role":{"type":"string","enum":["install","withdraw"],"description":"withdraw = 改绑后旧节点的撤销状态"},"state":{"type":"string","enum":["pending","installed","failed"]},"push_run_id":{"type":"integer","nullable":true},"at":{"type":"string","nullable":true},"error":{"type":"string","nullable":true},"pending_since":{"type":"string","nullable":true},"warning":{"type":"string","nullable":true,"description":"static_nexthop 未推导出接口时:路由照装但该节点不放行 forward"}}},"IpamAllocation":{"type":"object","properties":{"id":{"type":"integer"},"prefix_id":{"type":"integer"},"block_id":{"type":"integer","nullable":true},"family":{"type":"string","enum":["v4","v6"]},"cidr":{"type":"string"},"kind":{"type":"string","enum":["host","block"]},"scope":{"type":"string","enum":["platform","svc","vm"]},"attach":{"type":"string","enum":["none","l2_gateway","static_nexthop","node_local","elastic_ip","anycast_service","internal_pool","vpc_private"]},"status":{"type":"string","enum":["reserved","active","released"]},"node_id":{"type":"integer","nullable":true},"iface":{"type":"string","nullable":true,"description":"路由类 attach:validateNexthop 推导的接口(不接受客户端填写)"},"nexthop":{"type":"string","nullable":true},"static_route_id":{"type":"integer","nullable":true},"elastic_ip_id":{"type":"integer","nullable":true},"tenant_ref":{"type":"string","nullable":true},"external_ref":{"type":"string","nullable":true},"owner":{"type":"string"},"expires_at":{"type":"string","nullable":true},"released_at":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"},"prefix_len":{"type":"integer","description":"l2_gateway:所在池块(否则前缀)掩码;其他:cidr 掩码"},"gateway":{"type":"string","nullable":true,"description":"l2_gateway:所在块/前缀的网关(首地址 +1);其他 null"},"route_state":{"type":"array","items":{"$ref":"#/components/schemas/IpamRouteState"}},"maps_to_allocation_id":{"type":"integer","nullable":true},"maps_to":{"$ref":"#/components/schemas/IpamMapsTo","description":"公网 EIP(static_nexthop / node_local)映射到的 vpc_private 分配;其他 null"},"mapped_by":{"$ref":"#/components/schemas/IpamMapsTo","description":"vpc_private 分配被哪条公网分配映射(1:1);其他 null"}}},"IpamAllocationWrite":{"type":"object","properties":{"ok":{"type":"boolean"},"created":{"type":"boolean"},"allocation":{"$ref":"#/components/schemas/IpamAllocation"},"pending_push_nodes":{"type":"array","items":{"type":"integer"}},"route_state":{"type":"array","items":{"$ref":"#/components/schemas/IpamRouteState"}}}},"IpamBlock":{"type":"object","properties":{"id":{"type":"integer"},"prefix_id":{"type":"integer"},"parent_block_id":{"type":"integer","nullable":true},"family":{"type":"string"},"cidr":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["plan","pool","reserved"]},"scope":{"type":"string","nullable":true},"node_id":{"type":"integer","nullable":true},"tenant_ref":{"type":"string","nullable":true},"external_ref":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"cooldown_hours":{"type":"integer","nullable":true,"description":"释放冷却期小时;null = 默认 24;上限 168"},"cooldown_hours_effective":{"type":"integer"},"downstream_iface":{"type":"string","nullable":true,"description":"下联接口白名单(运营填):static_nexthop 只在它的直连段里判定 nexthop,iface / FORWARD 放行只取它;wg/gre/tun/ovpn/lo 等隧道/回环名拒绝"},"created_at":{"type":"string"},"updated_at":{"type":"string"}}},"IpamPool":{"type":"object","properties":{"block_id":{"type":"integer"},"cidr":{"type":"string"},"family":{"type":"string"},"name":{"type":"string"},"total":{"type":"string"},"free":{"type":"string"},"free_pct":{"type":"number"}}},"IpamNode":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"site":{"type":"string","nullable":true},"agent_type":{"type":"string","enum":["bird","routeros","linux"]},"status":{"type":"string"},"pools":{"type":"array","items":{"$ref":"#/components/schemas/IpamPool"}}}},"IpamNexthopCheck":{"type":"object","properties":{"ok":{"type":"boolean"},"via":{"type":"string","nullable":true,"enum":["connected",null]},"iface":{"type":"string","nullable":true,"description":"= 池块 downstream_iface"},"reason":{"type":"string","nullable":true},"block_id":{"type":"integer","nullable":true,"description":"判定所用的池块"}}},"IpamEvent":{"type":"object","properties":{"id":{"type":"integer"},"allocation_id":{"type":"integer","nullable":true},"prefix_id":{"type":"integer","nullable":true},"kind":{"$ref":"#/components/schemas/IpamEventKind"},"created_at":{"type":"string"},"payload":{"type":"object","properties":{"cidr":{"type":"string"},"external_ref":{"type":"string","nullable":true},"tenant_ref":{"type":"string","nullable":true},"scope":{"type":"string"},"attach":{"type":"string"},"status":{"type":"string"},"expires_at":{"type":"string","nullable":true},"node_id":{"type":"integer","nullable":true},"nexthop":{"type":"string","nullable":true},"reason":{"type":"string","nullable":true,"enum":["released","expired","admin",null],"description":"released 时"},"nexthop_old":{"type":"string","nullable":true},"nexthop_new":{"type":"string","nullable":true},"node_id_old":{"type":"integer","nullable":true},"node_id_new":{"type":"integer","nullable":true},"maps_to_allocation_id":{"type":"integer","nullable":true},"maps_to_old":{"type":"string","nullable":true,"description":"updated / released:映射变更前的私网 cidr"},"maps_to_new":{"type":"string","nullable":true},"block_id":{"type":"integer","nullable":true,"description":"block.* 事件"},"name":{"type":"string","nullable":true},"kind":{"type":"string","nullable":true},"parent_block_id":{"type":"integer","nullable":true},"push_run_id":{"type":"integer","nullable":true,"description":"route_installed / route_failed"},"error":{"type":"string","nullable":true}}}}},"IpamEvents":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/IpamEvent"}},"next_since":{"type":"integer","description":"下次轮询的 since(本页最大 id;空页 = 请求的 since)"},"oldest_id":{"type":"integer","nullable":true,"description":"现存最早事件 id;since+1 < oldest_id 说明有事件已被 30 天清理 → 410"}}},"IpamCursorExpired":{"type":"object","properties":{"error":{"type":"string","enum":["cursor expired"]},"oldest_id":{"type":"integer"}},"required":["error","oldest_id"]},"ByoipState":{"type":"string","enum":["pending","validated","pending_review","approved","announced","rejected","withdrawn"],"description":"pending→validated(自动)/pending_review(有 warning,需 admin approve)/rejected;validated|approved + loa_ref → announced;DELETE → withdrawn(记录保留 30 天)"},"PrefixEventKind":{"type":"string","enum":["prefix.created","prefix.validated","prefix.pending_review","prefix.approved","prefix.rejected","prefix.announced","prefix.updated","prefix.withdrawn"]},"ByoipValidation":{"type":"object","properties":{"outcome":{"type":"string","enum":["validated","pending_review","rejected"]},"rpki":{"type":"object","properties":{"state":{"type":"string","enum":["valid","invalid","unknown"],"description":"Cloudflare validity API;unknown 含查询失败/超时 → pending_review"},"description":{"type":"string","nullable":true},"error":{"type":"string","nullable":true}}},"irr":{"type":"object","properties":{"matched":{"type":"boolean"},"authoritative":{"type":"boolean","description":"route/route6 对象在 RIPE/APNIC/ARIN/LACNIC/AFRINIC 任一权威源精确匹配;只在 RADB → false(pending_review)"},"object":{"type":"string"},"source":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"error":{"type":"string","nullable":true}}},"overlap":{"type":"object","properties":{"ok":{"type":"boolean"},"with":{"type":"string","nullable":true,"description":"撞上的现有前缀(Built-in 或活着的 Orbit 段)"}}},"length":{"type":"object","properties":{"ok":{"type":"boolean"},"error":{"type":"string","nullable":true}}},"reasons":{"type":"array","items":{"type":"string"},"description":"硬伤 → rejected"},"warnings":{"type":"array","items":{"type":"string"},"description":"软伤 → pending_review"},"checked_at":{"type":"string"},"approved_by":{"type":"string","nullable":true},"approved_at":{"type":"string","nullable":true}}},"OrbitPrefix":{"type":"object","properties":{"id":{"type":"integer"},"cidr":{"type":"string"},"family":{"type":"string","enum":["v4","v6"]},"name":{"type":"string","nullable":true},"origin_asn":{"type":"integer"},"kind":{"type":"string","description":"恒 default"},"purpose":{"type":"string","description":"恒 service"},"managed_by":{"type":"string","enum":["orbit"]},"external_ref":{"type":"string","nullable":true},"tenant_ref":{"type":"string","nullable":true},"loa_ref":{"type":"string","nullable":true,"description":"LOA 引用;为空不能宣告"},"byoip_state":{"$ref":"#/components/schemas/ByoipState"},"announce_scope":{"type":"string","nullable":true,"enum":["all_edges",null]},"no_bind":{"type":"boolean","description":"恒 true:不绑首地址、不回源"},"validation":{"$ref":"#/components/schemas/ByoipValidation","nullable":true},"announce_nodes":{"type":"array","items":{"type":"integer"},"description":"当前 force ON 的节点(prefix_announcements enabled=1)"},"announce_blocked":{"type":"string","nullable":true,"description":"为什么现在不能宣告(状态 / 缺 LOA);null = 可以或已宣告"},"description":{"type":"string","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"}}},"OrbitPrefixWrite":{"type":"object","properties":{"ok":{"type":"boolean","description":"校验是否通过(validated)"},"created":{"type":"boolean"},"unchanged":{"type":"boolean"},"state":{"$ref":"#/components/schemas/ByoipState"},"prefix":{"$ref":"#/components/schemas/OrbitPrefix"},"validation":{"$ref":"#/components/schemas/ByoipValidation","nullable":true},"announce_nodes":{"type":"array","items":{"type":"integer"}},"pending_push_nodes":{"type":"array","items":{"type":"integer"}},"announce_blocked":{"type":"string","nullable":true}}},"OrbitPrefixInput":{"type":"object","properties":{"cidr":{"type":"string","description":"v4 ≥ /24(prefixLen ≤ 24),v6 ≥ /48"},"origin_asn":{"type":"integer","description":"默认 204921;其它 ASN 需在 BYOIP_ORIGIN_ASN_ALLOWLIST"},"announce_nodes":{"type":"array","items":{"type":"integer"},"description":"宣告节点 id(bird/routeros)"},"scope":{"type":"string","enum":["all_edges"],"description":"代替 announce_nodes:全部 edge 角色节点"},"announce":{"type":"boolean","description":"false = 校验通过也先不宣告(默认 true)"},"tenant_ref":{"type":"string"},"external_ref":{"type":"string","description":"幂等键:同 ref 再 POST = 更新;withdrawn 的同 ref/同 cidr 记录复活"},"loa_ref":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"}}},"PrefixEvent":{"type":"object","properties":{"id":{"type":"integer"},"prefix_id":{"type":"integer"},"kind":{"$ref":"#/components/schemas/PrefixEventKind"},"created_at":{"type":"string"},"payload":{"type":"object","properties":{"cidr":{"type":"string"},"family":{"type":"string"},"origin_asn":{"type":"integer"},"managed_by":{"type":"string"},"external_ref":{"type":"string","nullable":true},"tenant_ref":{"type":"string","nullable":true},"loa_ref":{"type":"string","nullable":true},"byoip_state":{"$ref":"#/components/schemas/ByoipState"},"announce_scope":{"type":"string","nullable":true},"reasons":{"type":"array","items":{"type":"string"}},"warnings":{"type":"array","items":{"type":"string"}},"announce_nodes":{"type":"array","items":{"type":"integer"}},"removed_nodes":{"type":"array","items":{"type":"integer"}},"announce_nodes_before":{"type":"array","items":{"type":"integer"}},"by":{"type":"string","nullable":true},"approved_by":{"type":"string","nullable":true},"reason":{"type":"string","nullable":true,"description":"prefix.withdrawn:user:<id> / client:<name> / revalidation(定期重验未通过自动撤)"},"outcome":{"type":"string","nullable":true},"revived":{"type":"boolean"},"manual":{"type":"boolean"},"changes":{"type":"object"}}}}},"PrefixEvents":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/PrefixEvent"}},"next_since":{"type":"integer","description":"下次轮询的 since(本页最大 id;空页 = 请求的 since)"},"oldest_id":{"type":"integer","nullable":true,"description":"现存最早事件 id;since+1 < oldest_id 说明有事件已被 30 天清理 → 410"}}},"IxEventKind":{"type":"string","enum":["ix.created","ix.updated","rs.created","rs.updated","rs.deleted","rs.up","rs.down","rs.restarted","rs.restart_failed","rs.instance_removed","rs.instance_remove_failed","member.created","member.updated","member.suspended","member.activated","member.deleted","member.session_up","member.session_down","member.max_prefix","port.created","port.updated","port.deleted","push.queued","push.ok","push.failed","push.error","push.skipped"]},"IxEvent":{"type":"object","properties":{"id":{"type":"integer"},"kind":{"$ref":"#/components/schemas/IxEventKind"},"member_id":{"type":"integer","nullable":true},"rs_id":{"type":"integer","nullable":true},"payload":{"type":"object","nullable":true,"description":"按 kind 不同;member.max_prefix = {member_id, rs_id, family, limit, received};永不含 md5"},"created_at":{"type":"string"}}},"IxEvents":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/IxEvent"}},"next_since":{"type":"integer","description":"下次轮询的 since(本页最大 id;空页 = 请求的 since)"},"oldest_id":{"type":"integer","nullable":true,"description":"现存最早事件 id;since+1 < oldest_id 说明有事件已被 30 天清理 → 410"}}},"IxPort":{"type":"object","properties":{"id":{"type":"integer"},"member_id":{"type":"integer"},"ipv4":{"type":"string","nullable":true},"ipv6":{"type":"string","nullable":true},"mac":{"type":"string","nullable":true},"external_ref":{"type":"string","nullable":true},"enabled":{"type":"boolean"},"session_v4":{"type":"boolean"},"session_v6":{"type":"boolean"}}},"IxPortInput":{"type":"object","properties":{"ipv4":{"type":"string"},"ipv6":{"type":"string"},"mac":{"type":"string"},"external_ref":{"type":"string","description":"外部引用;ports[] 整组覆盖时的配对键,/ports/ext:<ref> 寻址"},"enabled":{"type":"boolean"},"session_v4":{"type":"boolean"},"session_v6":{"type":"boolean"}}},"IxMember":{"type":"object","properties":{"id":{"type":"integer"},"ix_id":{"type":"integer"},"asn":{"type":"integer"},"name":{"type":"string"},"external_ref":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","active","suspended","disabled"]},"irr_as_set":{"type":"string","nullable":true,"description":"空 = 按 AS<asn> 展开 route 对象(仍有 IRR 过滤)"},"irr_sources":{"type":"string","nullable":true},"irr_loose":{"type":"boolean","description":"true 才不做前缀过滤;仅平台用户可写"},"rpki_override":{"type":"string","nullable":true},"max_prefix_v4":{"type":"integer","nullable":true},"max_prefix_v6":{"type":"integer","nullable":true},"has_md5":{"type":"boolean"},"transit_enabled":{"type":"boolean"},"transit_default_route":{"type":"boolean"},"transit_announce":{"type":"boolean"},"passive":{"type":"boolean"},"rs_ids":{"type":"array","nullable":true,"items":{"type":"integer"}},"version":{"type":"integer","nullable":true,"description":"门户的乐观并发版本号"},"notes":{"type":"string","nullable":true},"ports":{"type":"array","items":{"$ref":"#/components/schemas/IxPort"}},"created_at":{"type":"string"},"updated_at":{"type":"string"}}},"IxMemberWrite":{"type":"object","properties":{"ok":{"type":"boolean"},"created":{"type":"boolean"},"unchanged":{"type":"boolean","description":"version 等于库里 → true,未写入未推送"},"member":{"$ref":"#/components/schemas/IxMember"},"push_run_ids":{"type":"array","items":{"type":"integer"}}}},"IxStaleVersion":{"type":"object","properties":{"error":{"type":"string","enum":["stale version"]},"current_version":{"type":"integer"}},"required":["error","current_version"]},"IxIrrPreview":{"type":"object","properties":{"object":{"type":"string"},"sources":{"type":"string"},"v4_count":{"type":"integer"},"v6_count":{"type":"integer"},"sample_v4":{"type":"array","items":{"type":"string"}},"sample_v6":{"type":"array","items":{"type":"string"}},"notes":{"type":"array","items":{"type":"string"}},"error":{"type":"string","nullable":true}}},"IxRouteServer":{"type":"object","properties":{"id":{"type":"integer"},"ix_id":{"type":"integer"},"node_id":{"type":"integer"},"name":{"type":"string"},"instance":{"type":"string"},"rs_ipv4":{"type":"string","nullable":true},"rs_ipv6":{"type":"string","nullable":true},"iface":{"type":"string"},"router_id":{"type":"string"},"enabled":{"type":"boolean"},"state":{"type":"string"},"last_pushed_at":{"type":"string","nullable":true},"last_error":{"type":"string","nullable":true}}},"Ix":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"asn":{"type":"integer"},"peering_lan_v4":{"type":"string","nullable":true},"peering_lan_v6":{"type":"string","nullable":true},"rs_mode":{"type":"string","enum":["reflect","transit"]},"transit_default_only":{"type":"boolean"},"rpki_mode":{"type":"string","enum":["reject","tag","off"]},"irr_sources":{"type":"string","description":"逗号分隔、大写,如 RIPE,APNIC,RADB"},"default_max_prefix_v4":{"type":"integer"},"default_max_prefix_v6":{"type":"integer"},"rtr_servers":{"type":"array","items":{"type":"string"},"description":"RPKI RTR 服务器 host:port 列表(空 = 平台默认);每个各起一个 protocol rpki 共用 roa 表,顺序即优先"},"max_prefix_hold_minutes":{"type":"integer","description":"会话因 max-prefix 被 disable 后 agent 多少分钟后 enable 回来(默认 30)"},"auto_push":{"type":"boolean"},"enabled":{"type":"boolean"},"notes":{"type":"string","nullable":true}}}}},"paths":{"/api/auth/me":{"get":{"summary":"当前身份(会话或令牌)","tags":["auth"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/auth/tokens":{"get":{"summary":"列出我的 API 令牌","tags":["auth"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"创建 API 令牌(明文只返回一次)。restrict 可选:限定用途令牌给外部平台——{kind:'ix', ix_id|null, scopes:[members:read|members:write|status:read]} 只在 /api/ix 下有效;{kind:'ipam', scope:'svc'|'vm'|null, scopes:[space:read|alloc:read|alloc:write]} 只在 /api/ipam 下有效;{kind:'prefix', scopes:[prefix:read|prefix:write]} 只在 /api/orbit/prefixes 下有效(Orbit BYOIP;只能看/改 managed_by=orbit 的前缀)。限定令牌 admin 才能签","tags":["auth"],"description":"令牌 scope 至少 admin","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"scope":{"type":"string","enum":["read","write","admin"],"default":"admin"},"ttl_seconds":{"type":"integer"},"restrict":{"type":"object","properties":{"kind":{"type":"string","enum":["ix","ipam","prefix"]},"ix_id":{"type":"integer"},"scope":{"type":"string","enum":["svc","vm"]},"scopes":{"type":"array","items":{"type":"string"}}}}}}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/auth/tokens/{id}":{"delete":{"summary":"删除令牌","tags":["auth"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"令牌 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes":{"get":{"summary":"节点列表(含状态/漂移/角色)","tags":["nodes"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"创建节点","tags":["nodes"],"description":"令牌 scope 至少 write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"asn":{"type":"integer"},"region":{"type":"string"},"agent_type":{"type":"string","enum":["bird","routeros","relay"]},"roles":{"type":"array","items":{"type":"string"}}},"required":["name"]}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/{id}":{"get":{"summary":"节点详情","tags":["nodes"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"put":{"summary":"更新节点(角色、loopback、rDNS 编码、DIA 开关等)","tags":["nodes"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"delete":{"summary":"删除节点","tags":["nodes"],"description":"令牌 scope 至少 admin","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/{id}/bgp-sessions":{"get":{"summary":"节点 BGP 会话(平台配置 + live 合并)","tags":["sessions"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"创建 BGP 会话","tags":["sessions"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"kind":{"type":"string","enum":["upstream","peer","downstream","ibgp","ix","route_collector"]},"family":{"type":"string","enum":["v4","v6"]},"neighbor_asn":{"type":"integer"},"neighbor_ip":{"type":"string"},"source_ip":{"type":"string"}},"required":["name","kind","family","neighbor_asn","neighbor_ip"]}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/{id}/bgp-sessions/{sid}":{"put":{"summary":"更新 BGP 会话","tags":["sessions"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"},{"name":"sid","in":"path","required":true,"schema":{"type":"integer"},"description":"会话 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"delete":{"summary":"删除 BGP 会话","tags":["sessions"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"},{"name":"sid","in":"path","required":true,"schema":{"type":"integer"},"description":"会话 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/{id}/static-routes":{"get":{"summary":"节点静态路由","tags":["nodes"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"新增静态路由","tags":["nodes"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"family":{"type":"string"},"cidr":{"type":"string"},"kind":{"type":"string"},"via_gateway":{"type":"string"},"via_iface":{"type":"string"}},"required":["family","cidr","kind"]}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/{id}/config/render":{"post":{"summary":"dry-run 渲染配置(?contents=1 带文件内容)","tags":["push"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"},{"name":"contents","in":"query","required":false,"schema":{"type":"string"},"description":"1 = 返回文件内容"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/{id}/config/push":{"post":{"summary":"同步推送(阻塞到结束)","tags":["push"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"},{"name":"phases","in":"query","required":false,"schema":{"type":"string"},"description":"RouterOS 分相,逗号分隔"},{"name":"scope","in":"query","required":false,"schema":{"type":"string"},"description":"full | prefix_policy"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/{id}/config/push-async":{"post":{"summary":"异步推送,返回 run_id","tags":["push"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"},{"name":"phases","in":"query","required":false,"schema":{"type":"string"},"description":"RouterOS 分相,逗号分隔"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix":{"get":{"summary":"IX 列表(ixc_ 客户端只看到自己的 IX)","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ix":{"type":"array","items":{"$ref":"#/components/schemas/Ix"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"创建 IX(平台 admin)。irr_sources:逗号分隔、大写(RIPE,APNIC,RADB);rtr_servers:[\"host:port\",…] 空 = 平台默认","tags":["ix"],"description":"令牌 scope 至少 admin","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"asn":{"type":"integer"},"peering_lan_v4":{"type":"string"},"peering_lan_v6":{"type":"string"},"rs_mode":{"type":"string","enum":["reflect","transit"]},"transit_default_only":{"type":"boolean"},"rpki_mode":{"type":"string","enum":["reject","tag","off"]},"irr_sources":{"type":"string"},"default_max_prefix_v4":{"type":"integer"},"default_max_prefix_v6":{"type":"integer"},"auto_push":{"type":"boolean"},"rtr_servers":{"type":"array","items":{"type":"string"}},"max_prefix_hold_minutes":{"type":"integer"}},"required":["slug","name","asn"]}}}},"responses":{"200":{"description":"OK"},"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"ix":{"$ref":"#/components/schemas/Ix"}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}":{"get":{"summary":"IX 详情(RS + 成员 + 端口)","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ix":{"$ref":"#/components/schemas/Ix"},"route_servers":{"type":"array","items":{"$ref":"#/components/schemas/IxRouteServer"}},"members":{"type":"array","items":{"$ref":"#/components/schemas/IxMember"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"patch":{"summary":"更新 IX(admin;字段同创建,另可改 enabled / notes)","tags":["ix"],"description":"令牌 scope 至少 admin","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"asn":{"type":"integer"},"peering_lan_v4":{"type":"string"},"peering_lan_v6":{"type":"string"},"rs_mode":{"type":"string","enum":["reflect","transit"]},"transit_default_only":{"type":"boolean"},"rpki_mode":{"type":"string","enum":["reject","tag","off"]},"irr_sources":{"type":"string"},"default_max_prefix_v4":{"type":"integer"},"default_max_prefix_v6":{"type":"integer"},"auto_push":{"type":"boolean"},"enabled":{"type":"boolean"},"notes":{"type":"string"},"rtr_servers":{"type":"array","items":{"type":"string"}},"max_prefix_hold_minutes":{"type":"integer"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"ix":{"$ref":"#/components/schemas/Ix"},"push_run_ids":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"delete":{"summary":"删除 IX:下发移除实例、清理 transit 托管会话(admin)","tags":["ix"],"description":"令牌 scope 至少 admin","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/push":{"post":{"summary":"重推全部 RS 实例(members:write)","tags":["ix"],"description":"令牌 scope 至少 write","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/route-servers":{"get":{"summary":"RS 列表(status:read)","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"route_servers":{"type":"array","items":{"$ref":"#/components/schemas/IxRouteServer"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"创建 RS(admin;节点须为 Bird、全部会话有 source address;先推主 Bird 再推实例)","tags":["ix"],"description":"令牌 scope 至少 admin","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"node_id":{"type":"integer"},"iface":{"type":"string"},"rs_ipv4":{"type":"string"},"rs_ipv6":{"type":"string"},"router_id":{"type":"string"}},"required":["node_id","iface"]}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/route-servers/{rs}":{"patch":{"summary":"更新 RS(admin)","tags":["ix"],"description":"令牌 scope 至少 admin","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"rs","in":"path","required":true,"schema":{"type":"integer"},"description":"RS 名或 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"delete":{"summary":"删除 RS:节点上 REMOVE 实例并重推主 Bird(admin)","tags":["ix"],"description":"令牌 scope 至少 admin","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"rs","in":"path","required":true,"schema":{"type":"integer"},"description":"RS 名或 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/route-servers/{rs}/push":{"post":{"summary":"重推单台 RS(members:write)","tags":["ix"],"description":"令牌 scope 至少 write","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"rs","in":"path","required":true,"schema":{"type":"integer"},"description":"RS 名或 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/route-servers/{rs}/restart":{"post":{"summary":"重启 RS 实例进程(配置不变;admin)","tags":["ix"],"description":"令牌 scope 至少 admin","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"rs","in":"path","required":true,"schema":{"type":"integer"},"description":"RS 名或 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/route-servers/{rs}/status":{"get":{"summary":"RS 状态:DB 会话 + agent 实时实例状态(status:read)","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"rs","in":"path","required":true,"schema":{"type":"integer"},"description":"RS 名或 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/members":{"get":{"summary":"成员列表(members:read)","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/IxMember"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"创建成员(members:write;带 external_ref 且已存在则当 PATCH;?push=false 不自动推送)。irr_as_set 空 = 按 AS<asn> 展开(仍过滤);irr_loose 仅平台用户(门户令牌 → 422)。version(IX-3):小于库里 → 409 {error:'stale version', current_version};等于 → 200 {unchanged:true} 不写不推;大于/库里为空 → 写入。ports[](IX-8/10):出现即整组覆盖——元素带 external_ref 按它配对,否则按 ipv4/ipv6 任一相同配对;缺的删、多的加、变的改;不出现则端口不动","tags":["ix"],"description":"令牌 scope 至少 write","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"push","in":"query","required":false,"schema":{"type":"string"},"description":"false 则不触发自动推送"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"asn":{"type":"integer"},"name":{"type":"string"},"external_ref":{"type":"string"},"irr_as_set":{"type":"string"},"irr_sources":{"type":"string","description":"逗号分隔、大写,如 RIPE,APNIC;空 = 跟 IX"},"irr_loose":{"type":"boolean"},"rpki_override":{"type":"string"},"max_prefix_v4":{"type":"integer"},"max_prefix_v6":{"type":"integer"},"md5":{"type":"string"},"transit_enabled":{"type":"boolean"},"transit_default_route":{"type":"boolean"},"transit_announce":{"type":"boolean"},"passive":{"type":"boolean"},"rs_ids":{"type":"array","items":{"type":"integer"},"description":"对等的 RS id;空/不传 = 全部"},"status":{"type":"string","enum":["active","suspended"]},"version":{"type":"integer"},"ports":{"type":"array","items":{"$ref":"#/components/schemas/IxPortInput"}}},"required":["asn","name"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IxMemberWrite"}}}},"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IxMemberWrite"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"409":{"description":"HTTP 409","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IxStaleVersion"}}}},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/members/{member}":{"get":{"summary":"成员详情(members:read;member = id | ext:<external_ref> | as:<asn>)","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"member":{"$ref":"#/components/schemas/IxMember"}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"patch":{"summary":"更新成员(members:write;字段同创建,version / ports[] 语义同创建)","tags":["ix"],"description":"令牌 scope 至少 write","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"external_ref":{"type":"string"},"irr_as_set":{"type":"string"},"irr_sources":{"type":"string"},"irr_loose":{"type":"boolean"},"rpki_override":{"type":"string"},"max_prefix_v4":{"type":"integer"},"max_prefix_v6":{"type":"integer"},"md5":{"type":"string"},"transit_enabled":{"type":"boolean"},"transit_default_route":{"type":"boolean"},"transit_announce":{"type":"boolean"},"passive":{"type":"boolean"},"rs_ids":{"type":"array","items":{"type":"integer"}},"status":{"type":"string"},"version":{"type":"integer"},"notes":{"type":"string"},"ports":{"type":"array","items":{"$ref":"#/components/schemas/IxPortInput"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IxMemberWrite"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"409":{"description":"HTTP 409","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IxStaleVersion"}}}},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"delete":{"summary":"删除成员(members:write)","tags":["ix"],"description":"令牌 scope 至少 write","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"push_run_ids":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/members/{member}/suspend":{"post":{"summary":"暂停成员(会话从 RS 移除)","tags":["ix"],"description":"令牌 scope 至少 write","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IxMemberWrite"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/members/{member}/activate":{"post":{"summary":"恢复成员","tags":["ix"],"description":"令牌 scope 至少 write","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IxMemberWrite"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/members/{member}/irr-preview":{"get":{"summary":"IRR 展开预览(status:read;不落库)。as_set 缺省用成员的 irr_as_set,再缺省 AS<asn>;sources 缺省成员 → IX。解析失败放 error 字段(HTTP 200)","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"},{"name":"as_set","in":"query","required":false,"schema":{"type":"string"},"description":"AS-SET 或 ASN"},{"name":"sources","in":"query","required":false,"schema":{"type":"string"},"description":"逗号分隔 IRR 源"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IxIrrPreview"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/members/{member}/irr-refresh":{"post":{"summary":"清掉该成员 IRR 对象的缓存并重推全部 RS(members:write)","tags":["ix"],"description":"令牌 scope 至少 write","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"},{"name":"push","in":"query","required":false,"schema":{"type":"string"},"description":"false 则只清缓存"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"object":{"type":"string"},"sources":{"type":"string"},"push_run_ids":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/members/{member}/ports":{"post":{"summary":"新增端口(members:write;同 external_ref / 同地址已存在则返回已有,不重复建)","tags":["ix"],"description":"令牌 scope 至少 write","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IxPortInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"created":{"type":"boolean"},"port":{"$ref":"#/components/schemas/IxPort"},"push_run_ids":{"type":"array","items":{"type":"integer"}}}}}}},"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"created":{"type":"boolean"},"port":{"$ref":"#/components/schemas/IxPort"},"push_run_ids":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/members/{member}/ports/{port}":{"patch":{"summary":"更新端口(port = id | ext:<external_ref>)","tags":["ix"],"description":"令牌 scope 至少 write","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"},{"name":"port","in":"path","required":true,"schema":{"type":"string"},"description":"端口 id 或 ext:<external_ref>"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IxPortInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"port":{"$ref":"#/components/schemas/IxPort"},"push_run_ids":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"delete":{"summary":"删除端口(port = id | ext:<external_ref>)","tags":["ix"],"description":"令牌 scope 至少 write","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"},{"name":"port","in":"path","required":true,"schema":{"type":"string"},"description":"端口 id 或 ext:<external_ref>"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"push_run_ids":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/members/{member}/sessions":{"get":{"summary":"成员在各 RS 的会话状态(status:read)","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/members/{member}/routes":{"get":{"summary":"成员送进 RS 的路由(实时 birdc;含被 IRR/RPKI 标记不导出的,filtered_reason)","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"member","in":"path","required":true,"schema":{"type":"integer"},"description":"成员定位"},{"name":"family","in":"query","required":false,"schema":{"type":"string"},"description":"v4|v6"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"条数"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/looking-glass":{"get":{"summary":"looking glass:前缀在各 RS 的路径(status:read)","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"prefix","in":"query","required":true,"schema":{"type":"string"},"description":"前缀或地址"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/stats":{"get":{"summary":"IX 统计(成员/会话/RS 状态计数)","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ix/{slug}/events":{"get":{"summary":"事件流(status:read;?since=<id> 增量)。保留 30 天;since 之后紧接的事件已被清理 → 410 {error:'cursor expired', oldest_id},从 since=0 重新同步。kind 见 IxEventKind;payload 永不含 md5","tags":["ix"],"description":"令牌 scope 至少 read","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"integer"},"description":"IX slug"},{"name":"since","in":"query","required":false,"schema":{"type":"integer"},"description":"上次看到的事件 id(next_since)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"条数(≤1000)"},{"name":"order","in":"query","required":false,"schema":{"type":"string"},"description":"asc(默认,增量轮询)| desc(最新优先)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IxEvents"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"410":{"description":"HTTP 410","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["cursor expired"]},"oldest_id":{"type":"integer","nullable":true}}}}}},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/prefixes":{"get":{"summary":"可管理前缀 + 用量 + 各 scope 允许的 attach。purpose=vpc_pool 为 VPC 私网池(spec §2.9:RFC1918/ULA,只记账,owner_node_id = 归属节点;块强制绑它,只开放 attach vpc_private)","tags":["ipam"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"prefixes":{"type":"array","items":{"type":"object","properties":{"prefix_id":{"type":"integer"},"cidr":{"type":"string"},"family":{"type":"string"},"purpose":{"type":"string"},"anycast":{"type":"boolean"},"vpc_pool":{"type":"boolean"},"owner_node_id":{"type":"integer","nullable":true},"name":{"type":"string","nullable":true},"total":{"type":"string"},"used":{"type":"string"},"used_pct":{"type":"number"},"occupied_ranges":{"type":"integer"},"blocks":{"type":"integer"},"allocations":{"type":"array","items":{"type":"object","properties":{"scope":{"type":"string"},"status":{"type":"string"},"attach":{"type":"string"},"n":{"type":"integer"}}}},"allowed_attaches":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/prefixes/{id}":{"get":{"summary":"前缀详情:用量、块树、分配(?status=)","tags":["ipam"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id"},{"name":"status","in":"query","required":false,"schema":{"type":"string"},"description":"reserved|active|released"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"prefix":{"type":"object"},"blocks":{"type":"array","items":{"$ref":"#/components/schemas/IpamBlock"}},"allocations":{"type":"array","items":{"$ref":"#/components/schemas/IpamAllocation"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"404":{"description":"前缀不存在"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/prefixes/{id}/candidates":{"get":{"summary":"空闲候选(?block_id&len&count)","tags":["ipam"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id"},{"name":"block_id","in":"query","required":false,"schema":{"type":"integer"},"description":"池块 id"},{"name":"len","in":"query","required":false,"schema":{"type":"integer"},"description":"前缀长度(默认单地址)"},{"name":"count","in":"query","required":false,"schema":{"type":"integer"},"description":"条数"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"prefix_id":{"type":"integer"},"parent":{"type":"string"},"len":{"type":"integer"},"candidates":{"type":"array","items":{"type":"string"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"404":{"description":"前缀不存在"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/pools":{"get":{"summary":"外部平台可用的池块(?scope&node_id&family)+ 剩余量;Orbit 按 node_id 发现自己能要地址的地方","tags":["ipam"],"description":"令牌 scope 至少 read","parameters":[{"name":"scope","in":"query","required":false,"schema":{"type":"string"},"description":"platform|svc|vm(客户端固定自己的)"},{"name":"node_id","in":"query","required":false,"schema":{"type":"integer"},"description":"节点"},{"name":"family","in":"query","required":false,"schema":{"type":"string"},"description":"v4|v6"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"string"},"pools":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"cidr":{"type":"string"},"name":{"type":"string"},"node_id":{"type":"integer","nullable":true},"prefix_cidr":{"type":"string"},"total":{"type":"string"},"free":{"type":"string"},"free_pct":{"type":"number"}}}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/nodes":{"get":{"summary":"节点 + 各自绑定的、本 scope 可用的池块与剩余量(spec 2.8):Orbit 据此挑宿主;pools 按令牌 scope 过滤(平台用户 ?scope= 默认 vm)","tags":["ipam"],"description":"令牌 scope 至少 read","parameters":[{"name":"scope","in":"query","required":false,"schema":{"type":"string"},"description":"platform|svc|vm(客户端固定自己的)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"string"},"nodes":{"type":"array","items":{"$ref":"#/components/schemas/IpamNode"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/nexthop-check":{"post":{"summary":"static_nexthop 的 nexthop 预校验(spec 2.2 + 安全定案):只在池块 downstream_iface(运营白名单)这一个接口的直连段里判定;隧道/回环类接口、节点隧道口、BGP 会话 source 所在口一律拒绝;不能是节点自己的地址、不能落在 anycast / OOB 段。给 block_id 用那个块,否则在绑到 node_id 的池块里逐个试。创建 / PATCH 时同样校验;分配的 iface = 块的 downstream_iface","tags":["ipam"],"description":"令牌 scope 至少 read","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"node_id":{"type":"integer"},"nexthop":{"type":"string"},"block_id":{"type":"integer"}},"required":["node_id","nexthop"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpamNexthopCheck"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/prefixes/{id}/blocks":{"post":{"summary":"新建块(plan|pool|reserved)。cidr 与 len 二选一:不传 cidr 就在父块(parent_block_id)/ 前缀里按 len 挑第一段空闲(vpc_pool:v4 /20–/28、v6 /56–/64,缺省 /24、/64;其它前缀 v4 /16–/32、v6 /32–/128)。vpc_pool 下 = VPC(external_ref=vpc:<id>)与子网(parent_block_id + external_ref=subnet:<id>):scope 缺省 vm、node_id 强制为前缀归属节点、不接受 downstream_iface;外部 vm 令牌只能在 vpc_pool 前缀下建块(其它前缀 403),scope 固定为令牌 scope。事件 block.created","tags":["ipam"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cidr":{"type":"string","description":"与 len 二选一"},"len":{"type":"integer","description":"不传 cidr 时按长度自动挑"},"name":{"type":"string"},"kind":{"type":"string","enum":["plan","pool","reserved"]},"scope":{"type":"string","enum":["platform","svc","vm"]},"parent_block_id":{"type":"integer"},"node_id":{"type":"integer"},"tenant_ref":{"type":"string"},"external_ref":{"type":"string","description":"全局唯一(重复 422);vpc:<id> / subnet:<id>"},"notes":{"type":"string"},"cooldown_hours":{"type":"integer","description":"释放冷却期小时(0–168;空 = 默认 24)"},"downstream_iface":{"type":"string","description":"下联接口白名单(宿主机所在的接口,如 vlan30-biz);static_nexthop 分配必须落在带它的池块里"}},"required":["name"]}}}},"responses":{"200":{"description":"OK"},"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"block":{"$ref":"#/components/schemas/IpamBlock"}}}}}},"401":{"description":"未认证"},"403":{"description":"外部令牌在非 vpc_pool 前缀下建块"},"404":{"description":"前缀不存在"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/blocks/{id}":{"patch":{"summary":"更新块(name / kind / scope / node_id / tenant_ref / notes / cooldown_hours / downstream_iface)。vpc_pool 下 node_id 不可改;外部令牌只能改自己 scope 的 vpc_pool 块且不能改 scope。事件 block.updated","tags":["ipam"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"块 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"kind":{"type":"string","enum":["plan","pool","reserved"]},"scope":{"type":"string","enum":["platform","svc","vm"]},"node_id":{"type":"integer"},"tenant_ref":{"type":"string"},"notes":{"type":"string"},"cooldown_hours":{"type":"integer"},"downstream_iface":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"block":{"$ref":"#/components/schemas/IpamBlock"}}}}}},"401":{"description":"未认证"},"403":{"description":"外部令牌动非 vpc_pool / 他人 scope 的块"},"404":{"description":"块不存在"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"delete":{"summary":"删除块(无在用分配/子块;外部令牌同 PATCH 的限制)。事件 block.deleted","tags":["ipam"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"块 id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}},"401":{"description":"未认证"},"403":{"description":"外部令牌动非 vpc_pool / 他人 scope 的块"},"404":{"description":"块不存在"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/allocations":{"get":{"summary":"分配列表(客户端只见自己 scope;每条带 route_state)","tags":["ipam"],"description":"令牌 scope 至少 read","parameters":[{"name":"prefix_id","in":"query","required":false,"schema":{"type":"integer"},"description":"前缀"},{"name":"scope","in":"query","required":false,"schema":{"type":"string"},"description":"platform|svc|vm"},{"name":"status","in":"query","required":false,"schema":{"type":"string"},"description":"reserved|active|released"},{"name":"tenant_ref","in":"query","required":false,"schema":{"type":"string"},"description":"租户"},{"name":"tenant_ref_prefix","in":"query","required":false,"schema":{"type":"string"},"description":"租户引用前缀匹配"},{"name":"external_ref_prefix","in":"query","required":false,"schema":{"type":"string"},"description":"外部引用前缀匹配"},{"name":"node_id","in":"query","required":false,"schema":{"type":"integer"},"description":"节点"},{"name":"attach","in":"query","required":false,"schema":{"type":"string"},"description":"attach"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"条数(默认 500,最多 2000)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"allocations":{"type":"array","items":{"$ref":"#/components/schemas/IpamAllocation"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"分配。三种定位:① cidr(必须严格对齐,自动归最具体前缀/池块);② prefix_id|block_id + len 自动挑;③ node_id + len(+family)在绑到该节点的池块里挑。external_ref 幂等(全局命名空间,各平台加前缀;命中返回 200 + created:false);status=reserved 不带 expires_at 时外部平台默认 30 分钟后回收,VM 建好后 PATCH 成 active;attach 决定路由联动:static_nexthop 下发静态路由(必须落在带 downstream_iface 的池块里,nexthop 经 nexthop-check 在该接口直连段校验;iface = 块的 downstream_iface,不接受客户端填写),node_local 只落 blackhole 锚定路由给 iBGP 起源、不进内核(RouterOS 节点 422);两者都给归属节点 + 全网标 pending push。刚释放的地址在块级冷却期内(默认 24h)不能再分配(422 in cooldown until …)。vpc_private(spec §2.9):VM 私网 IP,仅 vpc_pool 前缀、scope vm/svc,必须给 block_id(VPC / 子网块)或 cidr,单地址,自动挑跳过网络/网关/广播,只记账不动路由。maps_to(仅 static_nexthop / node_local):\"ext:<external_ref>\" 或分配 id,把这条公网 EIP 1:1 映射到一条同 scope、未释放的 vpc_private 分配,且其 vpc_pool 的归属节点必须 = 本分配 node_id;目标已被映射 → 422","tags":["ipam"],"description":"令牌 scope 至少 write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"family":{"type":"string","enum":["v4","v6"]},"scope":{"type":"string","enum":["platform","svc","vm"]},"attach":{"type":"string","enum":["none","l2_gateway","static_nexthop","node_local","elastic_ip","anycast_service","internal_pool","vpc_private"]},"cidr":{"type":"string"},"prefix_id":{"type":"integer"},"block_id":{"type":"integer"},"len":{"type":"integer"},"status":{"type":"string","enum":["reserved","active"]},"node_id":{"type":"integer"},"nexthop":{"type":"string","description":"static_nexthop 必填;node_local 必须为空"},"iface":{"type":"string","description":"只对无路由动作的 attach 记账用;路由类 attach 忽略"},"tenant_ref":{"type":"string"},"external_ref":{"type":"string"},"expires_at":{"type":"string"},"notes":{"type":"string"},"maps_to":{"type":"string","nullable":true,"description":"\"ext:<external_ref>\" | 分配 id;仅 static_nexthop / node_local"}},"required":["scope"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpamAllocationWrite"}}}},"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpamAllocationWrite"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/allocations/{id}":{"get":{"summary":"分配详情(含 route_state,改绑后带旧节点撤销状态)+ 观测(seen_on)+ 事件;id | ext:<ref> | cidr:<cidr>","tags":["ipam"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"分配定位"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"allocation":{"$ref":"#/components/schemas/IpamAllocation"},"seen_on":{"type":"array","items":{"type":"object","properties":{"node_id":{"type":"integer"},"node_name":{"type":"string"},"iface":{"type":"string"},"last_seen":{"type":"string","nullable":true}}}},"events":{"type":"array","items":{"$ref":"#/components/schemas/IpamEvent"}}}}}}},"401":{"description":"未认证"},"403":{"description":"其他 scope 的分配"},"404":{"description":"分配不存在"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"patch":{"summary":"更新:status reserved↔active、tenant_ref、expires_at、notes;static_nexthop / node_local 还可改 nexthop、node_id(spec 2.3:删旧路由行建新行,旧/新节点都标 pending,事件 updated 带 *_old/*_new;nexthop 同样过校验)与 maps_to(spec §2.9:与 node_id 同一事务,null 解绑;事件 updated 带 maps_to_old / maps_to_new;只改 node_id 而旧映射的 VPC 不在新节点 → 422 先解绑)","tags":["ipam"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"分配定位"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["reserved","active"]},"tenant_ref":{"type":"string"},"expires_at":{"type":"string"},"notes":{"type":"string"},"nexthop":{"type":"string"},"node_id":{"type":"integer"},"maps_to":{"type":"string","nullable":true,"description":"\"ext:<external_ref>\" | 分配 id | null 解绑"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpamAllocationWrite"}}}},"401":{"description":"未认证"},"403":{"description":"其他 scope 的分配"},"404":{"description":"分配不存在"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"delete":{"summary":"释放(撤销路由联动,全网标 pending;事件 reason:外部令牌 released、平台用户 admin、到期 expired;冷却期后可再分配,7 天后清理)。释放公网 EIP 会清掉它的 maps_to;释放仍被映射的 vpc_private → 422 \"mapped by <cidr>; unmap first\"","tags":["ipam"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"分配定位"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"allocation":{"$ref":"#/components/schemas/IpamAllocation"},"pending_push_nodes":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"未认证"},"403":{"description":"其他 scope 的分配"},"404":{"description":"分配不存在"},"422":{"description":"被映射的私网分配"}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/nat-map":{"get":{"summary":"NAT 对账表(spec §2.9,Orbit 每小时对账):某节点上全部\"公网 EIP → 私网 IP\"映射(公网分配 node_id = 该节点、未释放、带 maps_to);外部令牌只看自己 scope","tags":["ipam"],"description":"令牌 scope 至少 read","parameters":[{"name":"node_id","in":"query","required":true,"schema":{"type":"integer"},"description":"节点 id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"node_id":{"type":"integer"},"entries":{"type":"array","items":{"$ref":"#/components/schemas/IpamNatMapEntry"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"缺 node_id"}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/events":{"get":{"summary":"事件流(?since=<上次 next_since>;asc 增量轮询)。保留 30 天、承诺 7 天;since 落在已清理区间 → 410 {error:'cursor expired', oldest_id},从 oldest_id-1 重新同步","tags":["ipam"],"description":"令牌 scope 至少 read","parameters":[{"name":"since","in":"query","required":false,"schema":{"type":"integer"},"description":"上次看到的事件 id(0 = 从头)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"条数(≤1000)"},{"name":"order","in":"query","required":false,"schema":{"type":"string"},"description":"asc|desc"},{"name":"prefix_id","in":"query","required":false,"schema":{"type":"integer"},"description":"前缀"},{"name":"kind","in":"query","required":false,"schema":{"type":"string"},"description":"只看某类事件"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpamEvents"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"410":{"description":"HTTP 410","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpamCursorExpired"}}}},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ipam/meta":{"get":{"summary":"枚举:scopes / attaches / event_kinds","tags":["ipam"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"scopes":{"type":"array","items":{"type":"string"}},"attaches":{"type":"array","items":{"type":"string"}},"event_kinds":{"type":"array","items":{"$ref":"#/components/schemas/IpamEventKind"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/push-runs":{"get":{"summary":"推送记录","tags":["push"],"description":"令牌 scope 至少 read","parameters":[{"name":"node_id","in":"query","required":false,"schema":{"type":"integer"},"description":"节点 id"},{"name":"status","in":"query","required":false,"schema":{"type":"string"},"description":"queued|running|success|failed"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"条数"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/push-runs/{id}":{"get":{"summary":"单次推送详情(含分相结果)","tags":["push"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"run id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/{id}/agent-diag":{"post":{"summary":"Bird 节点只读诊断(ping/mtr/birdc/gobgp + ss/ip/sysctl/nft;白名单校验,写操作与长选项赋值一律拒绝)","tags":["nodes"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cmd":{"type":"string","enum":["ping","ping6","mtr","birdc","gobgp","ss","ip","sysctl","nft"]},"args":{"type":"array","items":{"type":"string"}}},"required":["cmd"]}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/{id}/bird-reload-in":{"post":{"summary":"让 Bird 对已收路由重跑 import filter(改过滤策略后必须做)","tags":["nodes"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"protocols":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/{id}/routeros/print":{"get":{"summary":"RouterOS 只读 print(path + 过滤参数)","tags":["nodes"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"},{"name":"path","in":"query","required":true,"schema":{"type":"string"},"description":"如 /routing/route"},{"name":"proplist","in":"query","required":false,"schema":{"type":"string"},"description":"逗号分隔字段"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/prefixes":{"get":{"summary":"前缀列表(四类:Default/Anycast/Bond/Area;每条带 managed_by=platform|orbit 与 BYOIP 字段)","tags":["prefixes"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"添加 Built-in 前缀(managed_by=orbit → 422,BYOIP 走 /api/orbit/prefixes)","tags":["prefixes"],"description":"令牌 scope 至少 write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cidr":{"type":"string"},"family":{"type":"string"},"name":{"type":"string"},"anycast":{"type":"boolean"},"bond":{"type":"boolean"},"ospf_area_id":{"type":"integer"},"purpose":{"type":"string"}},"required":["cidr","family"]}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/prefixes/anycast-readiness":{"get":{"summary":"anycast/area 段就绪核对(绑了段内地址却没对外宣告的节点)","tags":["prefixes"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/prefixes/{id}":{"get":{"summary":"前缀详情","tags":["prefixes"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"patch":{"summary":"更新前缀(绑区 / anycast / 默认目标);Orbit 段 → 422(用 /api/orbit/prefixes)","tags":["prefixes"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"delete":{"summary":"删除前缀(Built-in 物理删 204;Orbit 段 = 撤回 withdrawn 200)","tags":["prefixes"],"description":"令牌 scope 至少 admin","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/orbit/prefixes":{"get":{"summary":"Orbit 前缀列表(?state=&tenant_ref=)","tags":["orbit"],"description":"令牌 scope 至少 read","parameters":[{"name":"state","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ByoipState"},"description":"按 byoip_state 过滤"},{"name":"tenant_ref","in":"query","required":false,"schema":{"type":"string"},"description":"按租户过滤"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"prefixes":{"type":"array","items":{"$ref":"#/components/schemas/OrbitPrefix"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"建 BYOIP 前缀并校验(prefix:write)。强制 managed_by=orbit / purpose=service / no_bind=1;anycast/bond/ospf_area_id/default_announce 忽略。校验:不与任何前缀重叠 + RPKI(Cloudflare)+ IRR route 对象精确匹配(权威源)。RPKI valid 且权威 IRR 命中且无 warning → validated,有 loa_ref 且给了节点就直接 announced;RPKI unknown / IRR 只在 RADB → pending_review(需 admin approve);invalid / 重叠 / IRR 不匹配 → rejected(仍 201,ok:false)。external_ref 幂等:同 ref 再 POST = 更新(200 created:false);withdrawn 的同 ref/同 cidr 记录复活","tags":["orbit"],"description":"令牌 scope 至少 write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrbitPrefixInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrbitPrefixWrite"}}}},"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrbitPrefixWrite"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"cidr 不合法 / 长度不够(v4 ≥ /24,v6 ≥ /48)/ 同 cidr 已存在 / origin_asn 不在白名单 / announce_nodes 不合法 / 同 ref 改 cidr"}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/orbit/prefixes/events":{"get":{"summary":"事件流(?since=<上次 next_since>;asc 增量)。保留 30 天;since 落在已清理区间 → 410 {error:'cursor expired', oldest_id}。kind 见 PrefixEventKind;payload 固定带前缀快照","tags":["orbit"],"description":"令牌 scope 至少 read","parameters":[{"name":"since","in":"query","required":false,"schema":{"type":"integer"},"description":"上次看到的事件 id(0 = 从头)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"条数(≤1000)"},{"name":"order","in":"query","required":false,"schema":{"type":"string"},"description":"asc|desc"},{"name":"prefix_id","in":"query","required":false,"schema":{"type":"integer"},"description":"前缀"},{"name":"kind","in":"query","required":false,"schema":{"$ref":"#/components/schemas/PrefixEventKind"},"description":"只看某类事件"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrefixEvents"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"410":{"description":"HTTP 410","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpamCursorExpired"}}}},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/orbit/prefixes/meta":{"get":{"summary":"枚举:states / event_kinds / scopes / allowed_origin_asns","tags":["orbit"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"states":{"type":"array","items":{"$ref":"#/components/schemas/ByoipState"}},"event_kinds":{"type":"array","items":{"$ref":"#/components/schemas/PrefixEventKind"}},"scopes":{"type":"array","items":{"type":"string"}},"allowed_origin_asns":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/orbit/prefixes/{id}":{"get":{"summary":"详情;id | ext:<external_ref>","tags":["orbit"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id 或 ext:<ref>"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"prefix":{"$ref":"#/components/schemas/OrbitPrefix"}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"404":{"description":"不存在或不是 Orbit 前缀"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"patch":{"summary":"改 announce_nodes|scope / tenant_ref / loa_ref / origin_asn / name / description / announce。origin_asn 变了重验(未通过则撤宣告);cidr 不可改;withdrawn → 422","tags":["orbit"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id 或 ext:<ref>"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrbitPrefixInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrbitPrefixWrite"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"404":{"description":"不是 Orbit 前缀"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"delete":{"summary":"撤回:prefix_announcements 禁用、全网打标、state=withdrawn;记录保留 30 天(cron prefix-events-cleanup);external_ref / cidr 可被下次 POST 复用。幂等","tags":["orbit"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id 或 ext:<ref>"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"already_withdrawn":{"type":"boolean"},"state":{"$ref":"#/components/schemas/ByoipState"},"prefix":{"$ref":"#/components/schemas/OrbitPrefix"}}}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"404":{"description":"不是 Orbit 前缀"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/orbit/prefixes/{id}/revalidate":{"post":{"summary":"重验(rejected / pending_review);通过且原本已宣告或 body 带 announce_nodes 则宣告;未通过撤宣告","tags":["orbit"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id 或 ext:<ref>"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"announce_nodes":{"type":"array","items":{"type":"integer"}},"scope":{"type":"string","enum":["all_edges"]},"announce":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrbitPrefixWrite"}}}},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"withdrawn"}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/orbit/prefixes/{id}/approve":{"post":{"summary":"审批(仅平台 admin,prefix 令牌 403):pending_review → approved;有 loa_ref 且给了节点(body 或 announce_scope=all_edges)则直接 announced。validation.approved_by 记审批人,事件 prefix.approved","tags":["orbit"],"description":"令牌 scope 至少 admin","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id 或 ext:<ref>"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"announce_nodes":{"type":"array","items":{"type":"integer"}},"scope":{"type":"string","enum":["all_edges"]},"announce":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrbitPrefixWrite"}}}},"401":{"description":"未认证"},"403":{"description":"非平台 admin"},"422":{"description":"不是 pending_review"}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/orbit/prefixes/{id}/reject":{"post":{"summary":"驳回(仅平台 admin):任意非 withdrawn → rejected;已宣告的先撤宣告。事件 prefix.rejected {manual:true, reasons:[reason]}","tags":["orbit"],"description":"令牌 scope 至少 admin","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"前缀 id 或 ext:<ref>"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"state":{"$ref":"#/components/schemas/ByoipState"},"prefix":{"$ref":"#/components/schemas/OrbitPrefix"}}}}}},"401":{"description":"未认证"},"403":{"description":"非平台 admin"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/tunnels":{"get":{"summary":"隧道列表","tags":["tunnels"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"创建隧道(勾 ospf_enabled 即自动收敛 OSPF 接口与 iBGP)","tags":["tunnels"],"description":"令牌 scope 至少 write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"node_a_id":{"type":"integer"},"node_b_id":{"type":"integer"},"type":{"type":"string","enum":["wg","gre","direct"]},"ospf_enabled":{"type":"boolean"},"ospf_area_id":{"type":"integer"},"endpoint_mode":{"type":"string"},"mtu":{"type":"integer"}},"required":["node_a_id","node_b_id"]}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/tunnels/{id}":{"patch":{"summary":"热更新隧道","tags":["tunnels"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"隧道 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"delete":{"summary":"删除隧道(?force=1 需 admin)","tags":["tunnels"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"隧道 id"},{"name":"force","in":"query","required":false,"schema":{"type":"string"},"description":"1 = 只删平台记录"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/tunnels/{id}/toggle":{"post":{"summary":"启用/禁用隧道","tags":["tunnels"],"description":"令牌 scope 至少 write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"隧道 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ospf/overview":{"get":{"summary":"OSPF 区/接口/fabric 概览","tags":["ospf"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ospf/fabric-sync":{"post":{"summary":"重算骨干 OSPF 接口行与 ibgp_bb 会话(只改 D1)","tags":["ospf"],"description":"令牌 scope 至少 write","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ospf/areas/{area}/oob":{"get":{"summary":"Area OOB 绑定与分配(v4/v6)","tags":["ospf"],"description":"令牌 scope 至少 read","parameters":[{"name":"area","in":"path","required":true,"schema":{"type":"integer"},"description":"area 行 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ospf/areas/{area}/oob-prefix":{"put":{"summary":"绑定 Area OOB 段(v4 或 v6)","tags":["ospf"],"description":"令牌 scope 至少 admin","parameters":[{"name":"area","in":"path","required":true,"schema":{"type":"integer"},"description":"area 行 id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prefix":{"type":"string"},"announce":{"type":"boolean"}},"required":["prefix"]}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/ospf/areas/{area}/oob-assign":{"post":{"summary":"分配区内节点 OOB 地址(幂等)","tags":["ospf"],"description":"令牌 scope 至少 admin","parameters":[{"name":"area","in":"path","required":true,"schema":{"type":"integer"},"description":"area 行 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/topology":{"get":{"summary":"拓扑(节点/隧道/iBGP 边/RR 分析/地理)","tags":["topology"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/rdns/preview":{"get":{"summary":"rDNS 生成预览(含 Orbit 区匹配与同步状态)","tags":["rdns"],"description":"令牌 scope 至少 read","parameters":[{"name":"node_id","in":"query","required":false,"schema":{"type":"integer"},"description":"只看某节点"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/rdns/sync":{"post":{"summary":"同步 PTR 到 Orbit(?dry_run=1)","tags":["rdns"],"description":"令牌 scope 至少 admin","parameters":[{"name":"dry_run","in":"query","required":false,"schema":{"type":"string"},"description":"1 = 只算不写"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/telemetry/status":{"get":{"summary":"全节点实时状态聚合(在线/漂移/会话/隧道/延迟)","tags":["telemetry"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/telemetry/nodes/{id}":{"get":{"summary":"节点指标时间线 + 最近完整载荷","tags":["telemetry"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"},{"name":"range","in":"query","required":false,"schema":{"type":"string","default":"24h"},"description":"1h|6h|24h|7d|30d|1y"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/telemetry/links":{"get":{"summary":"两节点间延迟/丢包时间线","tags":["telemetry"],"description":"令牌 scope 至少 read","parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"integer"},"description":"源节点 id"},{"name":"to","in":"query","required":true,"schema":{"type":"integer"},"description":"目的节点 id"},{"name":"family","in":"query","required":false,"schema":{"type":"string"},"description":"v4|v6"},{"name":"kind","in":"query","required":false,"schema":{"type":"string"},"description":"tunnel|loopback"},{"name":"range","in":"query","required":false,"schema":{"type":"string"},"description":"1h|6h|24h|7d|30d|1y"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/telemetry/matrix":{"get":{"summary":"最新延迟矩阵(10 分钟内每对节点)","tags":["telemetry"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/telemetry/adjacency":{"get":{"summary":"骨干邻接实况(该有 OSPF 邻接的隧道里哪些没起来)","tags":["telemetry"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/pending-push":{"get":{"summary":"有平台改动尚未推送的节点","tags":["push"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/nodes/push-pending":{"post":{"summary":"一键推送待更新节点(ROS 只推标记相位)","tags":["push"],"description":"令牌 scope 至少 write","parameters":[{"name":"node_ids","in":"query","required":false,"schema":{"type":"string"},"description":"限定节点 id,逗号分隔"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/anycast-obs/overview":{"get":{"summary":"Anycast 可观测性总览:段内出网自检 + RIS AS-path + catchment/prepend 建议","tags":["anycast"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/anycast-obs/egress-check":{"get":{"summary":"最近一轮 anycast 段内出网自检结果","tags":["anycast"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"post":{"summary":"立即跑一轮出网自检","tags":["anycast"],"description":"令牌 scope 至少 write","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/anycast-obs/ris":{"get":{"summary":"RIS 观测汇总(各采集点看到的 AS path / prepend / 第一跳上游)","tags":["anycast"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/anycast-obs/ris-observe":{"post":{"summary":"立即从 RIPE RIS 拉一次观测","tags":["anycast"],"description":"令牌 scope 至少 write","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/anycast-obs/catchment":{"get":{"summary":"Atlas catchment 明细与 prepend 建议","tags":["anycast"],"description":"令牌 scope 至少 read","parameters":[{"name":"prefix","in":"query","required":false,"schema":{"type":"string"},"description":"只看某个前缀"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/anycast-obs/atlas/schedule":{"post":{"summary":"向 RIPE Atlas 排一轮 catchment 测量(消耗 credits)","tags":["anycast"],"description":"令牌 scope 至少 admin","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/anycast-obs/atlas/collect":{"post":{"summary":"抓取已排 Atlas 测量的结果并解析 catchment","tags":["anycast"],"description":"令牌 scope 至少 write","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/anycast-obs/settings":{"get":{"summary":"Anycast 观测设置(Atlas key 不回显)","tags":["anycast"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]},"patch":{"summary":"改设置 / 更新 Atlas key","tags":["anycast"],"description":"令牌 scope 至少 admin","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/telemetry/links/overview":{"get":{"summary":"链路总览:每条骨干隧道的角色/cost/实测 RTT/丢包/速率/握手/OSPF 邻接/健康度","tags":["telemetry"],"description":"令牌 scope 至少 read","parameters":[{"name":"role","in":"query","required":false,"schema":{"type":"string"},"description":"primary|backup — 只看某类链路"},{"name":"health","in":"query","required":false,"schema":{"type":"string"},"description":"up|degraded|down — 只看某种健康度"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/telemetry/fabric-resilience":{"get":{"summary":"骨干健壮性:桥(断了会分区的链路)、割点、被孤立的节点","tags":["telemetry"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/telemetry/ospf-cost/preview":{"get":{"summary":"OSPF cost 校准建议(当前 cost vs 按实测 RTT 应有的 cost)","tags":["telemetry"],"description":"令牌 scope 至少 read","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/telemetry/ospf-cost/apply":{"post":{"summary":"应用 cost 校准(写平台记录并标记待推送,不自动下发)","tags":["telemetry"],"description":"令牌 scope 至少 write","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/telemetry/ospf-cost/settings":{"patch":{"summary":"校准设置(auto_apply / 阻尼阈值 / 备份链路 cost / 中转保护偏移)","tags":["telemetry"],"description":"令牌 scope 至少 write","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/tunnels/mesh/plan":{"get":{"summary":"备份 mesh 规划(缺口节点对 + 端点候选);probe=1 实测端点可达性","tags":["tunnels"],"description":"令牌 scope 至少 read","parameters":[{"name":"probe","in":"query","required":false,"schema":{"type":"string"},"description":"1 = 逐对实测端点(慢)"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/tunnels/mesh/create":{"post":{"summary":"按规划生成备份 mesh 隧道(link_role=backup)","tags":["tunnels"],"description":"令牌 scope 至少 write","parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/telemetry/probe-targets/{id}":{"get":{"summary":"某节点的探测目标","tags":["telemetry"],"description":"令牌 scope 至少 read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"节点 id"}],"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}},"/api/agent/telemetry":{"post":{"summary":"agent 遥测上报(heartbeat token 鉴权)","tags":["agent"],"description":"令牌 scope 至少 write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ts":{"type":"string"},"uptime_s":{"type":"integer"},"load1":{"type":"number"},"cpu_pct":{"type":"number"},"mem_used_mb":{"type":"number"},"mem_total_mb":{"type":"number"},"sessions":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"state":{"type":"string"},"since":{"type":"string"},"imported":{"type":"integer"},"exported":{"type":"integer"}}}},"tunnels":{"type":"array","items":{"type":"object","properties":{"iface":{"type":"string"},"handshake_age_s":{"type":"integer"},"rx_bytes":{"type":"integer"},"tx_bytes":{"type":"integer"}}}},"probes":{"type":"array","items":{"type":"object","properties":{"peer_node_id":{"type":"integer"},"tunnel_id":{"type":"integer"},"family":{"type":"string"},"kind":{"type":"string"},"target":{"type":"string"},"sent":{"type":"integer"},"recv":{"type":"integer"},"rtt_min":{"type":"number"},"rtt_avg":{"type":"number"},"rtt_max":{"type":"number"}}}}}}}}},"responses":{"200":{"description":"OK"},"401":{"description":"未认证"},"403":{"description":"无权限 / scope 不足"},"422":{"description":"参数错误","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearer":[]},{"cookie":[]}]}}}}