From bfd206424d7ca7f72e5b917b0aac5022393d06b4 Mon Sep 17 00:00:00 2001 From: selftest Date: Fri, 21 Aug 2026 23:58:41 +0800 Subject: [PATCH] =?UTF-8?q?fix(conductor):=20sender=5Frole=20=E4=B8=A4?= =?UTF-8?q?=E7=BA=A7=E8=A7=A3=E6=9E=90=E2=80=94=E2=80=94GOV=5FTOKEN=20?= =?UTF-8?q?=E6=88=90=E5=91=98=E8=B5=84=E6=A0=BC=E5=A4=B1=E8=B4=A5=E6=97=B6?= =?UTF-8?q?=E7=BB=8F=20APP=5FTOKEN=20=E4=BB=93=E7=BA=A7=E5=8D=8F=E4=BD=9C?= =?UTF-8?q?=E8=80=85=20admin=20=E5=85=9C=E5=BA=95=EF=BC=88W1-C3=20e2e=20.g?= =?UTF-8?q?ithub#206=20=E5=AE=9E=E6=B5=8B=EF=BC=9AGOVERNANCE=5FTOKEN=20?= =?UTF-8?q?=E8=AF=BB=20memberships=20=E9=9D=9E=20200=EF=BC=8Cowner=20?= =?UTF-8?q?=E8=A2=AB=E5=88=A4=20none=20=E9=81=AD=20arbiter=20=E6=8B=92?= =?UTF-8?q?=EF=BC=8Crun=2032500211932=EF=BC=9B=E6=97=A7=20T3=20=E7=9A=84?= =?UTF-8?q?=20assoc=20=E5=85=9C=E5=BA=95=E6=8E=A9=E7=9B=96=E8=AF=A5?= =?UTF-8?q?=E5=8D=95=E7=82=B9=E5=A4=9A=E5=B9=B4=EF=BC=89=EF=BC=88W1-C3=20#?= =?UTF-8?q?166=EF=BC=8CADR-0055=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/conductor.yml | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/.github/workflows/conductor.yml b/.github/workflows/conductor.yml index 90aefc3..5f6ee94 100644 --- a/.github/workflows/conductor.yml +++ b/.github/workflows/conductor.yml @@ -128,14 +128,30 @@ jobs: audit("event=unrecognized verdict=noop"); raise SystemExit(0) # ---- sender_role(INV-02:API 判定,不硬编码用户名)---- + # 两级解析(W1-C3 e2e .github#206 实测教训:GOVERNANCE_TOKEN 读 + # /orgs/{org}/memberships 拿不到 200,role 曾静默落 none——旧 T3 guard + # 靠 author_association 兜底掩盖了该单点,arbiter 转介按 role 判权后 + # 把 owner 也拒了【run 32500211932 role-not-allowed】): + # ① GOV_TOKEN org 成员资格 role==admin → owner(首选,组织级语义) + # ② 失败时 APP_TOKEN 读仓级协作者权限 ==admin → owner(兜底; + # 与 drift-check §9 vcs-admin 唯一性同源——受管仓 admin 唯 owner) + # 两路全败=none(arbiter 默认拒绝)。均 API 判定,无硬编码用户名。 actor = E.get("ACTOR") or "" role = "none" + role_src = "none" if actor == "cloudbrid-agent[bot]": role = "agent" + role_src = "app-slug" else: st, m = api(E["GOV_TOKEN"], f"/orgs/{ORG}/memberships/{actor}") if st == 200 and m.get("role") == "admin": role = "owner" + role_src = "org-membership" + else: + st, p = api(E["APP_TOKEN"], f"/repos/{REPO}/collaborators/{actor}/permission") + if st == 200 and p.get("permission") == "admin": + role = "owner" + role_src = "repo-collab-admin(gov-membership HTTP %s)" % st assoc = E.get("COMMENT_ASSOC") or "NONE" # label 事件无此字段→NONE(guard 用 role) # ---- 当前状态与标签集 ---- @@ -175,11 +191,11 @@ jobs: if ev == "comment:/release": rc = adjudicate("/release") if rc == 0: - audit(f"event={ev} from={current} sender_role={role} arbiter=allow " + audit(f"event={ev} from={current} sender_role={role}({role_src}) arbiter=allow " f"verdict=ALLOWED release(租约已释放——无标签转移定义,纯租约面)") raise SystemExit(0) if rc == 1: - audit(f"event={ev} sender_role={role} verdict=DENIED-by-arbiter " + audit(f"event={ev} sender_role={role}({role_src}) verdict=DENIED-by-arbiter " f"(非 holder/无租约/过期——无租约变更、无标签变更)") raise SystemExit(0) audit(f"event={ev} arbiter=infra rc={rc} verdict=ABORT " @@ -226,7 +242,7 @@ jobs: audit(f"event={ev} transition={t['id']} arbiter=infra rc={rc} verdict=ABORT " f"(fail-closed——不许绕过仲裁;delivery 幂等可安全重投)") raise SystemExit(1) - audit(f"event={ev} transition={t['id']} sender_role={role} arbiter=allow " + audit(f"event={ev} transition={t['id']} sender_role={role}({role_src}) arbiter=allow " f"(租约已建——T3 落地;TTL 到期由下一 /claim 原子接管,ADR-0054)") # ---- 执行转移(状态标签写=App 身份,INV-02;写失败=fail-closed,