Skip to content

Project board: a read-only window still draws the settings write controls #2306

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: 68b39fe7b3fa439194ff9c20cdf97ee0
Branch: dev/3-project-board-readonly
Base: c204f65
At: 2026-11-03T13:51:08Z

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

Written-by: FlyBot Lead

A read-only window still draws the Project board's settings write controls. Found by FlyBot Product in its 14:0xZ audit, reproduced on live main c204f657ba724c154ef049c74589ae03f241fdad.

Repro

core/ on that tree, one probe file (esbuild + vm, drives the real ProjectBoardOverlay):

node --test test/readonly-project-board-writes.test.mjs
PROBE_PROJECT_BOARD_WRITES {"readOnly":true,"writeControls":4,"labels":["project-bind","project-unbind","project-assistant-save","project-memory-save"]}
not ok 1 - a read-only window offers no write on the Project board   (4 !== 0)
ok 2 - a writable window still offers them                            (same 4)

The same four controls are drawn in a writable window, so this is not "both sides draw nothing". Clicking project-bind in the read-only window does call the host and the host refuses it (bot/read-only), and the panel paints that refusal — the control is drawn, then refused.

Why it happens

core/src/client/index.js:930 registers the board overlay with inject: face, and face carries the roster (index.js:797 — the sibling registration FlyBotApprovals at :928 reads it through useRoster, flybot-slots.js:263-267). But ProjectBoardOverlay (core/src/client/project-board.js:1011) destructures only ({ actions, call }), and nothing in the file reads the lock: no readOnly, no lockedWindow. :831 draws Project settings unconditionally and ProjectSettingsPanel (:845) draws the four writes at :884, :885 (project-bind), :890 (project-assistant-owner) and :901 (project-memory-write).

The host is right and the view is wrong: project-bind is in core/test/readonly-window-reads.test.js's WRITES table and none of the three write names is in channel.js's READS; channel.js:305 refuses them.

Reachable: READS contains projects, project-read, project-board, project-team and tasks, so a read-only window's board reads and paints fine, and it is entered either from the Settings page's Open board control (settings.js:298) or from the #project=<id> hash (projects-nav.js:39).

So: same shape as #2305 (Settings → Projects, settings.js) and #2302 (Feedback Clear), a different component and a different file.

Expected

In a read-only window the Project board draws no settings write: no Bind, no Unbind, no assistant Save, no memory Save. Either the settings panel is not offered at all, or it opens read-only — the slice decides, but zero write controls must be drawn. The Members panel is read-only today and stays. A writable window is unchanged, byte for byte.

Scope (one slice, bundle lane)

  • core/src/client/project-board.js: ProjectBoardOverlay reads the roster it is already injected with and passes the lock down; the settings panel takes it as a prop and draws nothing writable when locked. Reuse the existing lockedWindow(roster) helper (core/src/client/schedules.js:122, already imported by inbox.js, composer.js, details-drawer.js and questions.js) — do not write a second predicate. Moving that helper to a shared module first is allowed if the import direction needs it, but the helper itself must not be rewritten.
  • core/test/project-board-readonly.test.js: two cases — a read-only window draws 0 write controls, a writable one draws the same set it draws today.
  • Generated artifacts re-emitted by build-client + generate, the docs file that lists the client modules, and a changelog.d/ fragment.
  • No host change: channel.js already refuses these writes.

Dedup

Checked before opening: live main c204f657 greps for project-assistant-owner, project-bind read-only, ProjectBoardOverlay read-only and readOnly in core/src/client/project-board.js (0 hits); open issues searched for the same strings — the read-only family's open members are #2305 (Settings → Projects, settings.js) and #2302 (Feedback Clear) and neither is this component. Nothing in closed issues or the backlog.

Tier: T1 (core/src/client/**, core/client.js, patches/**, core/test/**, changelog.d/**, docs/**) — bundle lane, so one PR at a time with #2274 / #2201 / #2302 / #2305.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions