diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index e29ba7f0..00f03b0b 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -2299,8 +2299,24 @@ - 触发条件:legacy `/api/admin/users` Route Handler 通过 `export { ..., runtime } from "../customers/route"` 同时重导出 handlers 和 route segment config。 - 根因:Next.js 要求 `runtime` 等 route segment config 在当前 route 文件中可被静态解析,不允许从另一 Route Handler 重导出;既有精确合同测试反而固化了非法 re-export,且并发功能本地 production build 未闭环。 - 修复:在 users route 本文件静态声明 `export const runtime = "nodejs"`,只重导出 DELETE/GET/PATCH/POST/PUT handlers;不复制 handler、不修改权限或客户数据逻辑。合同测试改为强制本地 runtime 常量并拒绝 runtime re-export。 -- 验证:待 admin users 目标合同、Next production build、完整 Gitea PR gate 和 staging gate;完成前不得标记 resolved。 +- 验证:admin users 目标合同、`tsc --noEmit`、默认 Turbopack `next build`、`next build --webpack`、全 route segment config re-export 扫描与 `git diff --check` 已通过;Gitea PR gate `1499` 在 SHA `015f1e501e2132d2abc6bbbcb8e6af074c326b47` 上通过并完成 production build。待最新并发主线 staging gate 与部署验收,完成前不得标记 resolved。 - 防复发:Route Handler 的 `runtime`、`dynamic`、`revalidate` 等 segment config 必须本地静态声明;handler 可复用,但 segment config 不得 re-export。新增 alias route 必须经过 production build,而不只运行文本合同测试。 - 相关记录:BUG-131、BUG-132 - 复发自:无 - 修复版本:待 Route Handler 静态 config 修复与 staging 验收 + +## BUG-134 | staging admin origin selector 未配置导致 exact-SHA 自动部署失败 + +- 状态:investigating +- 首次发现:2026-08-06 +- 最近更新:2026-08-06 +- 影响面:staging `.env.staging` 的公开 identity selector、自动 deploy run `1502`;应用容器、业务数据库和 production 未被修改。 +- 用户现象:staging gate `1500` 已成功验证并发布 SHA `9a3d0d440f43deab66c1f8a4a08cdbfc6f9d73eb` 的 immutable artifact,但自动 deploy `1502` 在远端 env 校验时报 `invalid staging selector: ADMIN_USER_ORIGIN` 并 fail closed;公网继续健康运行旧 SHA `e59f15d352787f3d05425ba8c459d092e9801a20`。 +- 触发条件:包含双 host self-hosted identity validator 的 controller 部署到现有 staging host,而 `.env.staging` 尚未包含精确且唯一的 `ADMIN_USER_ORIGIN=https://admin.staging.jyotisha.chat`。 +- 根因:并发 admin rollout 将 admin host origin 加入应用和 validator 合同,但 staging host-managed env 未在发布前同步新增的非密钥 selector;quality gate 验证仓库合同,不读取主机 secret/env,因此直到 mutation 前远端校验才暴露漂移。 +- 修复:待在共享 staging mutation lock 下,仅向原文件原子补入公开 `ADMIN_USER_ORIGIN` selector,保留全部既有内容、`deploy:deploy` owner 和 `0600` mode;不得输出、复制或重写其他 secret 值。随后用 exact-SHA gate artifact 重新部署。 +- 验证:脱敏只读检查已确认 `.env.staging` 为 `deploy:deploy 0600`、`AUTH_USER_ORIGIN` 精确且唯一、`ADMIN_USER_ORIGIN` 计数为 0;待 selector validator、最新 staging gate、exact-SHA deploy、公网/host SHA、容器 restart、日志和未登录边界验收。 +- 防复发:任何新增 staging host-managed selector 必须在同一 rollout runbook 中包含 deploy 前 presence/exact-value 检查;quality gate 成功不能替代 host env validation。env 修复必须共享 mutation lock、原子替换并保持 owner/mode,严禁打印 raw env。 +- 相关记录:BUG-128、BUG-133、ERR-093、ERR-097 +- 复发自:无 +- 修复版本:待 staging env selector 对齐与 exact-SHA 部署验收 diff --git a/docs/research/pre_work_error_ledger.md b/docs/research/pre_work_error_ledger.md index 3c6c7415..f35d6c69 100644 --- a/docs/research/pre_work_error_ledger.md +++ b/docs/research/pre_work_error_ledger.md @@ -157,6 +157,12 @@ Staging gate `1485` failed before validation when its single exact-SHA shallow f Prevention: both validate and publish exact-SHA checkouts use three bounded 300-second attempts, a 15-second connect timeout, and a 60-second/1-B/s stalled-transfer threshold. Preserve `--depth=1 --no-tags origin "$GITEA_SHA"`, exact HEAD equality, clean-tree checks, artifact non-reuse, and fail-closed exhaustion. Never report a skipped publish job as successful artifact publication. +## ERR-097 | Staging host env missed the reviewed admin-origin selector | investigating 2026-08-06 + +Staging gate `1500` successfully validated and published the exact SHA, but automatic deploy `1502` stopped before app mutation with `invalid staging selector: ADMIN_USER_ORIGIN`. A redacted read-only check confirmed `.env.staging` remained `deploy:deploy 0600`, had one exact user origin, and had zero admin-origin definitions. Public staging therefore remained on the prior healthy SHA; this was not a migration failure and production was not involved. + +Prevention: when a reviewed identity rollout adds a host-managed non-secret selector, update the staging env under the shared mutation lock before deploying the dependent controller. Modify only the named public selector through a mode-`0600` atomic replacement that preserves deployment-tree UID/GID; never print or copy the raw env. Re-run the exact validator and require the same gate-attested SHA in `main`, `staging`, host state, and public health before closure. + ## Fragment Sweep Command Set ## ERR-086 | Steve Jobs jyotishganit artifacts used non-San-Francisco coordinates | mitigated 2026-07-21 diff --git a/frontend/tests/admin-users-contract.test.ts b/frontend/tests/admin-users-contract.test.ts index bedbe96d..a637710f 100644 --- a/frontend/tests/admin-users-contract.test.ts +++ b/frontend/tests/admin-users-contract.test.ts @@ -41,5 +41,5 @@ test("admin_users migration is service-role-only and auditable", () => { test("legacy admin users route aliases handlers but declares runtime statically", () => { assert.match(usersSource, /export const runtime = "nodejs"/); assert.match(usersSource, /export \{ DELETE, GET, PATCH, POST, PUT \} from "\.\.\/customers\/route"/); - assert.doesNotMatch(usersSource, /export \{[^}]*runtime[^}]*\} from/); + assert.doesNotMatch(usersSource, /export \{[^}]*\bruntime\b[^}]*\} from/); });