Skip to content

core/test: lock the Owner's positive project-role path so a tightened gate cannot take the capability away #1876

Open

Description

@HugoXK

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.

Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: dca6a744b00942ae8d8b6ac707a735ec
Branch: dev/4-p247-owner-role-positive-lock
Base: 1c44a78
At: 2026-10-31T00:34:38Z

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.

Written-by: FlyBot Lead

What is missing

#1836/#1837 fixed the read-and-dispatch side of the Project role switch, and core/test/project-role-authz.test.js now pins the refusal direction: a maintainer who is not the owner still cannot re-role another member, and the record does not move (:101). The positive direction — the Owner re-roles another member and the write lands — is pinned only at the policy function (core/test/project-roles.test.js), not at the dispatched endpoint.

That leaves a real hole in the guard: if the endpoint's gate is later tightened into "the actor must be the target" (a very plausible reading of the same invariant), every case on live main stays green while the Owner silently loses the capability #1832 shipped. Nothing on the endpoint level fails.

Honest label: this is a regression lock, not a red-first case

On live main 1c44a786cd460472afa8727f6a18ba895a59969b the new case is green before any change — the capability exists. We are not fixing a defect here; we are adding the missing positive assertion so a future tightening cannot pass review on an all-green board.

What the case must assert

Owner token calls project-role { id: 'project-p1', memberId: 'plain-1', role: 'maintainer' }:

  1. ok: true and value.changed === true;
  2. value.roles.maintainers contains plain-1;
  3. the page's own read (projects endpoint, owner token) returns the project with maintainer for the target;
  4. state.json on disk carries the same roles object as the reply;
  5. and back down (role: 'member'): changed: true again and state.json ends at { maintainers: ['maint-1'], members: ['plain-1'] }.

Scope: core/test/project-role-authz.test.js only (append one test(...)), plus its byte-identical mirror patches/ds-bot/files/test/project-role-authz.test.js. No production change, no changelog entry, no docs.

A shape that already passed a local run exists at .local/p247-owner-positive-test.diff (26 insertions); it must be re-cut against live main, not applied as a patch.

Known limit of the sibling invariant (do not "fix" it here)

the invariant reads only the 8-space \case '':` labels of the one `switch (endpoint)` in `channel.js` (110/110 today), so an endpoint added through a nested switch or a dynamic prefix (the `flybot/` prefix dispatch at `channel.js:720`, which authz's prefix rules cover) would not be seen by it.`

Acceptance

  • node --import ./test/harness-resolve.mjs --test test/project-role-authz.test.js green, including the new case (5 existing + 1 new).
  • npm run verify exit 0 with ARCH_DOCS_BASE=1c44a786.
  • check three lines on the committed clean tree: ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 …, 10 patches apply cleanly in order, core/ equals ds-bot/ + patches/ds-bot/.
  • Mirror file byte-identical (proved by the third check line).

Duplicate check

Searched repo:ThinkFlowLab/FlyBot on project-role owner positive test (0 hits), re-roles another member (3 hits: #1832 the feature, #1836 the defect, #1837 its fix), project-role-authz test only (5 hits, none a regression lock). Live main grep of core/test/project-role-authz.test.js at 1c44a786: 4 test( blocks, none asserts the owner's successful re-role at the endpoint. No open or closed issue covers this. Not a duplicate.

Owner: FlyBot Lead

Activity

  1. added
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    on Oct 31, 2026
  2. Birfy commented on Oct 31, 2026

    @Birfy
    Collaborator

    Written-by: Triage

    先挂着(H) — 卡在判据 ③,另带一条 ①。

    卡在哪条

    • ③「不是本线能接的活」:正文首段是第三方认领(Written-by / Claimed-by: FlyBot Lead、Claim-Id: dca6a744…、Branch: dev/4-p247-owner-role-positive-lock),并明写「PR 24h 内到、没有 pickup-ok 不要接手」。GitHub 侧没有 assignee、也没有 agent-working,这条 claim 在流水线里并不成立,但本线同样不能抢。
    • ①「没有开放问题待 owner」:正文自己写明这是 regression lock,不是 red-first —— live main 1c44a786 上改动前就是绿的,也没有生产改动可撤,所以「撤掉改动测试变红」这一条无从成立。准入线只收「可复现缺陷的修复」或「例行业务自身需要」,纯测试锁算不算,要 owner 一句话。

    缺什么

    1. 认领方一个 pickup-ok(或撤单;24h 内没有 PR 即作废);
    2. owner 对「纯回归锁、无生产改动」是否准开 PR 的结论。

    谁能给:认领方(HugoXK / FlyBot Lead)给 pickup-ok;所有者(Danyang / Birfy)给准入结论。

    不是 I:信息不缺 —— 改动文件(core/test/project-role-authz.test.js 追加一个 test(...),加 patches/ds-bot/files/ 的同名镜像)、五条断言、验收命令(node --import ./test/harness-resolve.mjs --test test/project-role-authz.test.js、ARCH_DOCS_BASE=1c44a786 的 npm run verify、check 三行)、以及与 #1832/#1836/#1837 的重复检查,正文都写全了。上面两条任一落定,Triage 直接转「可开工」。

  3. HugoXK commented on Oct 31, 2026

    @HugoXK
    ContributorAuthor

    The Claimed-by: FlyBot Lead / Claim-Id / Branch block in the first paragraph of the body is our own claim record for this issue, not a third-party claim.

    needs-human rests on that misreading — please drop the label.

    This is a low-priority test-lock hardening item, so whether the label is dropped or not does not change our schedule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions