## 公开暴露排障

- NC01 共享 public-edge 的排障入口：
  - 先用一次 `bun scripts/cli.ts platform-infra public-edge status --target NC01 --site <site-id>`；
  - 再按 `installed/desired sourceCommit`、managed Caddy 指纹和 `matchesDesired` 判断运行面是否已经收敛；
  - 不要从单个 Sub2API Pod 的 `/health` 推断公网流式链路正常。
- 共享 public-edge 的超时配置：
  - 默认 `response_header_timeout` 只由 `config/platform-infra/public-edge.yaml#targets.NC01.runtime.responseHeaderTimeoutSeconds` 控制；
  - 产品 YAML 中的 Sub2API 本地 HTTPS timeout 不会自动覆盖共享 Caddy；
  - 长耗时流式 API 应由共享 edge 的 owning YAML 统一声明，避免只修一个站点。
- Caddy `context canceled` 的判定：
  - `aborting with incomplete response` 且错误为 `context canceled`，表示下游客户端或前置代理已经取消连接；
  - 该日志不能单独证明 Caddy 主动超时；
  - 只有固定耗时接近实际 `response_header_timeout`，且存在 Caddy timeout 和对应请求状态证据，才归类为 edge response-header timeout；
  - 同时对齐 Sub2API 是否记录 `status_code=200`、`latency_ms` 和同一请求的 `context canceled`。
- 多账号、多分组同时断流的主机检查：
  - Sub2API 的 `/models` 或调度缓存同时出现 `context canceled` 时，先检查 NC01 主机负载、内存压力和非核心遗留测试进程；
  - 只停止能明确证明为遗留测试或一次性任务的进程；
  - 不停止 k3s、containerd、Sub2API、Redis、数据库、egress proxy 或其他运行面基础设施。
- public-edge 自动交付判定：
  - host-only reconcile 成功但通用 CI closeout 报 `pac-gitops-missing` 时，以唯一 PipelineRun 的 TaskRun 状态和 `public-edge status` provenance 为准；
  - 不人工执行 reconcile、Argo sync 或 Caddy patch；
  - 失败只显示空的 `trans sh -- 失败` 时，登记 CLI 可见性问题，并下钻该 PipelineRun 的 bounded TaskRun 日志。

- FRP 不通：先看 `codex-pool expose --confirm` 输出的 `masterFrps`、`masterCaddy`、`sub2api-frpc` 和 public 401 probe；需要低层证据时只用 `trans G14:k3s` 做 bounded 查询。
- k3s external-active target 的 public URL 不通：先区分 DNS/TLS/Caddy/FRP/Sub2API。DNS 未解析到 YAML 声明的 PK01 地址时，Caddy ACME 会失败，HTTPS 不能算完成；可用 PK01 loopback FRP 端口和 PK01 公网 remotePort 证明 FRP 数据路径，但最终仍要等 DNS 生效后重跑 HTTPS health、`/v1/models` 和 `/v1/responses`。PK01 host-Docker local target 不走 FRP，不能用 FRP 端口探针替代本机 loopback/Caddy/app 验证。
- D601 external-active apply 后其他 PK01 HTTPS 服务消失：优先怀疑共享 Caddy managed block 合并失败或旧整文件写入路径复现。用受控 Sub2API apply 输出和 PK01 Caddy managed block markers 取证，再通过各服务自己的 YAML apply/public-exposure 入口恢复；不要手工复制某一份 Caddyfile 作为长期修复。
- Caddy 下载慢或失败：先确认 `config/platform-infra/sub2api.yaml` 已为对应 target 设置 `publicExposure.pk01.caddyDownloadProxyUrl`，并重跑 `sub2api apply --target <id> --confirm` 看 PK01 apply summary 中的 `downloadProxy.mode=curl-proxy`。不要反复裸连 GitHub release。
- `/responses/compact` 在接近 master Caddy `response_header_timeout` 的固定时长后返回 504，或 Sub2API 日志稍后记录 `codex.remote_compact.succeeded` 时，优先检查 master Caddy `response_header_timeout` 是否由 YAML `publicExposure.masterCaddy.responseHeaderTimeoutSeconds` 渲染，修正后跑 `codex-pool expose --confirm`；这类边缘代理超时不会触发 Sub2API 账号级临时下线。reload 前已经在途的 compact 请求仍可能按旧 timeout 结束，判断修复是否生效时只看 reload 之后新发起的请求。
- `/responses/compact` 或普通 public URL 在几秒窗口内出现 502，Caddy 日志显示 `dial tcp 127.0.0.1:<remotePort>: connect: connection refused`、`EOF` 或 `connection reset by peer`，同时 frps 日志出现 `platform-infra-sub2api proxy closing` / `listener is closed` / `new proxy ... success`，说明失败在 master Caddy 与 FRP remotePort 边缘层，Sub2API 和 sentinel 可能完全看不到。先确认 `publicExposure.masterCaddy.edgeRetry` 已按 YAML 渲染并 `codex-pool expose --confirm` 生效；若仍频繁发生，再继续查 G14 `sub2api-frpc` 到 master `frps` 的控制连接稳定性。不要把这类边缘 502 误判成账号池上游错误，也不要通过禁用账号恢复。
