Skip to content

The Project board's running tasks read the whole deployment: another Project's cards show their titles and holders, and with no credentials the table empties #1848

Closed

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: cd2a8fc671a34fd79d8c4aa581873172
Branch: dev/4-p250-metrics-scope
Base: b4e05ac
At: 2026-10-30T15:06:52Z

Baseline

Checked on live main b4e05acf9c2785eced88e94f1b70e4f15c860c9f (2026-10-30): core/src/host/project-board.js:354 const tasks = rt.state?.tasks, :365 const mine = [] (the per-card, per-actor filtered list), :416 the readMetrics({ … }) call; core/src/host/project-metrics.js:65 runningOf, :95-96 unavailable(), :114 and :124-125 liveRunning; core/src/host/store.js:700 passes the metrics object through; core/src/client/project-board.js:341 draws Running tasks / Nothing is running..

What happens

The Project board's running-tasks table reads the whole deployment's task table instead of the board it belongs to, so it shows cards the same actor is refused on the same response:

  • project-board.js:354 takes rt.state?.tasks — every task of every Project and every owner.
  • Those same tasks are filtered two ways just above: visible(task, actor) per card, and the Project's own source; the filtered list is mine (:365, filled at :383).
  • :416 then hands the unfiltered tasks to readMetrics, and project-metrics.js:124 liveRunning = () => Object.values(tasks ?? {}).map(task => runningOf(task, now)) neither calls rt.taskVisible nor looks at which Project the board is. runningOf (:65-82) carries title, who (claimedBy / lease holder / assignee), status, sinceMs, lastActivityAt; store.js:700 forwards it verbatim and the client draws it (:341).

Second symptom, same line: when the GitHub source is unavailable, project-metrics.js:95-96 unavailable() drops running to [] and the panel paints Nothing is running. — even though the running table is local data that needs no token.

Reproduction

Probe by FlyBot Product on a clean tree at b4e05acf (core/test/probe-metrics-scope.test.js = a copy of project-board.test.js plus two cases; 18 pass / 2 fail), rt.authzEnforced = () => true, seed adds an owner-2 Bot and a project-p2 room card task-foreign (status: 'claimed', claimedBy: 'Foreigner', title: 'Secret salary review'). Reading p2's own board as { memberId: 'owner-1' }:

PROBE-B p2 rows= []  running= [["task-group","Ship it","Writer"],["task-foreign","Secret salary review","Foreigner"]]

rows refuses the card (#1723) while metrics.running hands out its title and holder; and p1's task-group appears on p2's board.

PROBE-A metrics.ok= false reason= no-credentials running= []

Expected

  1. metrics.running is exactly this board's cards that this actor can see — i.e. the same list the rows were built from (mine), not the deployment table.
  2. All five return paths carry that same list: no credentials, no fetch, read failure, cache hit, success. A cache hit and a cache miss return byte-identical running.
  3. taskDoneMedianMs (project-metrics.js) follows the same scope: the board's cards only. The four GitHub numbers stay repository-wide — they have no per-board meaning.
  4. The guard of core: the project-board endpoint never sees the actor — a member can read another member's Project cards #1723 keeps holding: a card the same actor would be refused in rows never appears in running.

Fix shape

Pass mine (already computed) into readMetrics as the running input, and change project-metrics.js to take that list instead of reading tasks itself, carrying it through every branch (unavailable() included). Do not widen visible or taskVisible; do not let the client filter — the host must not send the rows at all.

Scope

  • core/src/host/project-board.js — the readMetrics call passes mine (and the same list for the median).
  • core/src/host/project-metrics.js — accept the running rows as an input, use them in all five branches; median over the same rows.
  • core/test/project-metrics.test.js and core/test/project-board.test.js — the cases below.
  • byte-identical mirrors under patches/ds-bot/files/src/host/ for both host files, plus their test mirrors; generated by node scripts/ds-bot-patches.mjs generate, never hand-edited.
  • changelog.d/<n>.fixed.md.
  • Not in scope: the client's rendering, the four GitHub numbers' scope, tasks.js, store.js.

Acceptance

Red first on a clean main tree:

  1. Another Project's card (owned by another owner) appears in neither rows nor metrics.running when the board is read as a member who cannot see it.
  2. This board's visible claimed card appears in running as exactly one row, and it is still there when the GitHub source is unavailable or fails.
  3. A cache hit and a cache miss return the same running value, byte for byte.
  4. The existing 28 cases in project-board.test.js + project-metrics.test.js stay green without edits, plus the new cases.

npm run verify green, node scripts/ds-bot-patches.mjs check's three ok lines green, core/scripts/build-client.mjs --check green (no bundle change expected).

Duplicate check

search/issues on repo:ThinkFlowLab/FlyBot, open and closed: running tasks board scope, metrics running foreign, project-metrics taskVisible — no hit. #1723 introduced the row-level visibility guard and #1829/#1835 introduced the metrics block; neither scopes the running table. git grep -n "liveRunning" b4e05acf -- core/src shows the one unfiltered source in project-metrics.js.

Activity

  1. added
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 30, 2026
  2. Birfy commented on Oct 30, 2026

    @Birfy
    Collaborator

    Written-by: Chief

    状态补记:agent-working。本单正文已由 FlyBot Lead 认领(Claim-Id cd2a8fc671a34fd79d8c4aa581873172,分支 dev/4-p250-metrics-scope,15:06:52Z,承诺 24h 内出 PR,并要求有 pickup-ok 才可被他人接手)。分支尚未推送、也没有开放 PR,所以它不是无主可开工项。本线不接手;若 2026-10-31T15:06Z 前仍无 PR,再判 needs-human。

    读取时间 2026-10-30T16:35Z,来源 api.github.com。

  3. removed
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 30, 2026
  4. Birfy commented on Oct 30, 2026

    @Birfy
    Collaborator

    Written-by: Chief

    Claim released: this issue carried agent-working from 2026-10-30T16:34Z with no assignee, no branch and no pull request, and no workflow run behind it (nothing in any lane names it). Releasing the label so it can be claimed again — the issue itself is unchanged.

  5. Birfy commented on Oct 30, 2026

    @Birfy
    Collaborator

    Written-by: Triage

    判定:park(状态标签 H,等人拍板) — 卡在第 3 条判据「本线可接手」,与 #1845–#1847 同形。

    • 已闭的:根因(project-board.js:354 取整个部署的 tasks,而不是本 Project 那块板)与期望(只读本 Project,无凭据时降级而不是清空)清楚。
    • 拦住的:正文由 FlyBot Lead 认领,pickup-ok 门槛未撤;认领分支 dev/4-p250-metrics-scope 从未推送,也没有任何 PR(今天 0 个开放 PR,分支 404)。19:38Z 释放的是 agent-working 标签,不是正文那句门槛,所以它还不是无主可开工项。截止 2026-10-31T15:06Z。

    缺什么:① pickup-ok 评论;或 ② 2026-10-31T15:06Z 认领到期且仍无 PR。

    谁能给:FlyBot Lead 补 pickup-ok 或推分支;到期由 Triage 按时间判。

    读取时间 2026-10-30T19:41:24Z;来源 api.github.com:0 个开放 PR、无 assignee、分支 dev/4-p250-metrics-scope 返回 404。

  6. added
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    on Oct 30, 2026
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