From 21aed20f624bb2cf0c627664954e6ff8cfc63999 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 13 Jul 2026 12:37:46 +0200 Subject: [PATCH] fix: bound missing webhook credentials status --- .../R1.1_Task_Report.md | 3 +- .../src/platform-infra-gitea-config.test.ts | 36 +++++++++++++++++++ scripts/src/platform-infra-gitea.ts | 17 +++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/docs/MDTODO/details/selfmedia-production-delivery/R1.1_Task_Report.md b/docs/MDTODO/details/selfmedia-production-delivery/R1.1_Task_Report.md index 570bf680..469924ae 100644 --- a/docs/MDTODO/details/selfmedia-production-delivery/R1.1_Task_Report.md +++ b/docs/MDTODO/details/selfmedia-production-delivery/R1.1_Task_Report.md @@ -29,10 +29,11 @@ ## Target 原入口证据 - 已通过 `trans NC01:/root/.worktrees/unidesk/selfmedia-repo-github-authority` 执行全部源码、Git 和验证操作。 -- `bun test scripts/src/platform-infra-gitea-config.test.ts scripts/src/platform-infra-gitea-disclosure.test.ts`:8 项通过,0 项失败。 +- `bun test scripts/src/platform-infra-gitea-config.test.ts scripts/src/platform-infra-gitea-disclosure.test.ts`:9 项通过,0 项失败。 - `bun scripts/cli.ts platform-infra gitea plan --target NC01`:policy 为 `ok`。 - `git diff --check`、Node 语法、Python `py_compile`、Shell `sh -n`:通过。 - `mirror bootstrap --target NC01 --repo selfmedia-nc01 --dry-run`:`OK=false`,blocker 为 `github-upstream:selfmedia-nc01`,符合 fail-closed。 +- `mirror webhook status --target NC01 --repo selfmedia-nc01 --full`:在本地 credential blocker 处早返回,包含 `sourceRef`、`present=false`、`fingerprint=null`、`permissionResult=blocked-missing-credential` 与有界错误码;未访问运行面,JSON/stderr 均无 stack 或绝对 worktree 路径。 - `mirror bootstrap --target JD01 --dry-run`:`OK=true`,证明 JD01 不依赖 NC01 override。 - 专用凭据只读状态:`sourceRef=pikainc-selfmedia-gh-token.txt`、`presence=false`、`fingerprint=null`、`permissionResult=blocked-missing-credential`。 - 因 credential material 缺失,未执行权限 API 探测;不得声称 Contents、Metadata 或 Webhooks 权限已实际授予。 diff --git a/scripts/src/platform-infra-gitea-config.test.ts b/scripts/src/platform-infra-gitea-config.test.ts index c528960f..df7b4dd3 100644 --- a/scripts/src/platform-infra-gitea-config.test.ts +++ b/scripts/src/platform-infra-gitea-config.test.ts @@ -47,4 +47,40 @@ describe("platform-infra Gitea repository GitHub credentials", () => { expect(jd01Manifest).not.toContain(tokenEnv); expect(nc01Manifest).toContain(tokenEnv); }); + + test("keeps missing selfmedia webhook status bounded and stack-free", () => { + const result = Bun.spawnSync({ + cmd: [ + "bun", + "scripts/cli.ts", + "platform-infra", + "gitea", + "mirror", + "webhook", + "status", + "--target", + "NC01", + "--repo", + "selfmedia-nc01", + "--full", + ], + stdout: "pipe", + stderr: "pipe", + }); + const stdout = result.stdout.toString(); + const payload = JSON.parse(stdout); + const credentials = payload.data.credentials as Array>; + const selfmedia = credentials.find((item) => item.id === "github-upstream:selfmedia-nc01"); + + expect(payload.data.error.code).toBe("github-credential-unavailable"); + expect(selfmedia).toMatchObject({ + sourceRef: "pikainc-selfmedia-gh-token.txt", + present: false, + fingerprint: null, + valuesPrinted: false, + }); + expect(selfmedia).not.toHaveProperty("sourcePath"); + expect(stdout).not.toContain('"stack"'); + expect(result.stderr.toString()).not.toContain("platform-infra-gitea.ts:"); + }); }); diff --git a/scripts/src/platform-infra-gitea.ts b/scripts/src/platform-infra-gitea.ts index a86dff9c..b6cab6fa 100644 --- a/scripts/src/platform-infra-gitea.ts +++ b/scripts/src/platform-infra-gitea.ts @@ -298,6 +298,7 @@ async function mirrorWebhookCommand(config: UniDeskConfig, args: string[]): Prom if (action === "status") { const options = parseMirrorWebhookStatusOptions(args.slice(1)); const result = await mirrorWebhookStatus(config, options); + if (result.credentialBlocked === true) return result; if (options.raw) return rawMirrorWebhookStatus(result); const disclosure = buildMirrorWebhookStatusDisclosure(result, options); return options.full ? disclosure : renderMirrorWebhookStatus(result, disclosure); @@ -471,6 +472,22 @@ async function mirrorWebhookStatus(config: UniDeskConfig, options: MirrorWebhook const gitea = readGiteaConfig(); const target = resolveCommandTarget(gitea, options.targetId); const repos = selectedRepositories(gitea, target, options.repoKey); + const credentials = credentialSummaries(gitea, repos); + const blockers = credentialBlockers(credentials); + if (blockers.length > 0) { + return { + ok: false, + action: "platform-infra-gitea-mirror-webhook-status", + mutation: false, + credentialBlocked: true, + target: targetSummary(target), + webhook: webhookSyncSummary(gitea, target), + repositories: repos.map((repo) => repositorySummary(gitea, repo)), + credentials, + error: { code: "github-credential-unavailable", blockers, valuesPrinted: false }, + next: mirrorReadOnlyNextCommands(target.id), + }; + } const secrets = ensureMirrorSecrets(gitea, target, repos, false, false, false); const result = await capture(config, target.route, ["sh"], remoteScript("mirror-webhook-status", gitea, target, "", { ...options, confirm: false, dryRun: true, wait: false }, { repos, secrets }).script); const parsed = parseJsonOutput(result.stdout);