Skip to content

Always allow does not persist: the same permission card comes back after approval #608

Closed

Description

@Birfy

Summary

The user approves a tool-permission card with Always allow (per Bot or per group) and the same request still comes back later, so the Reviewer's review chain keeps stopping on the same card. The standing grant does not take effect.

Evidence

Where the code stands (main abaf938b, hypotheses only)

  • core/src/host/approvals.js: grantStanding writes to bot.standingApprovals / room.standingApprovals, and standingCovers only honors a grant when settled(rt, sessionId) === OWNER (turn origin, turn-origin.js). If the turn's origin verdict is missing / OTHER — which Secrets: $DSH_SECRET_* can be empty on an ordinary turn of a shared Bot's own chat — per-session/turn context, not only scheduled turns (extends #581) #601 shows happens on ordinary turns — the grant is skipped and the card returns.
  • OUTCOMES maps always-bot to allowed-once for the DSH side, so the persistence is entirely FlyBot-side; if standingApprovals is not written to the Bot/room record store, a reload / restart loses it.
  • The client has core/src/client/standing-approvals.js (view/revoke); if a grant exists there but the host skips it, the gap is in standingCovers.

Expected behavior

  1. Always allow (per Bot / per group) is persisted on the Bot/room record and honored on every later request of that kind from that Bot in that scope — including after a page reload, a new session and a restart.
  2. The grant is the owner's, recorded with the owner identity at grant time; a later turn whose origin verdict is missing must not silently skip it (fix the attribution, or honor the grant for the owner's own Bot in the owner's chat).
  3. The UI shows the active grants and lets the owner revoke them (standing-approvals).
  4. If a grant is deliberately skipped, say why (log + card), never silently re-ask.

Acceptance / evidence

  • A test that approves always-bot (and always-room), then issues the same kind of request again: no card, auto-approved. Remove the standingCovers check → the test turns red.
  • A reload/restart test: rebuild the runtime from the store and repeat the request — still auto-approved (proves persistence). This is the part that reproduces the user's report.
  • Scope: core/src/host/approvals.js, core/src/host/authz.js, core/src/client/standing-approvals.js, matching core/test/approvals*.test.js, the patches/ds-bot/files/... mirror, docs.

Why it matters

It blocks the Reviewer's review chain and shows the user a control that does not work; the user has already clicked it twice.

Activity

  1. added
    bugSomething isn't working
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    area:uiWeb/desktop UI and copy
    area:automationScheduled tasks and automation
    area:securityAuth, grants, approvals, secrets
    on Oct 21, 2026
  2. Birfy commented on Oct 21, 2026

    @Birfy
    CollaboratorAuthor

    Cross-reference (Triage, 2026-10-21, per the Chief's direction): this may share one root cause with #601 ($DSH_SECRET_* empty on ordinary turns) — a turn whose origin verdict is missing/OTHER. In core/src/host/approvals.js, grantStanding writes the grant to bot.standingApprovals / room.standingApprovals, and standingCovers honours it only when settled(rt, sessionId) === OWNER; when the verdict is missing the grant is skipped and the card returns.

    Dev: verify this first, rather than patching the card: in one owner turn record the turn-origin verdict (and whether the grant was skipped). If confirmed, fix the attribution once with #601 folded in; no second patch. Acceptance stays as written: approve always-bot → same request no card; reload/restart → still auto-approved. The user's three details (session, request, interval) are coming from the Chief.

  3. Birfy commented on Oct 21, 2026

    @Birfy
    CollaboratorAuthor

    Fixed and merged via #612 (external contributor PR, so its body has no Fixes #N and I do not edit a contributor body to add one).

    Evidence: #612 merged at 2026-10-21T11:31:44Z, squash merge commit 81c708d054f43c90fd201ae3a281fd2e8e8916e7 on main (was 7eae271c). Reviewer PASS was on tip 31342ec06c6cc85e3165047cad2843a3b3b88f9b; the PR was enqueued at that same SHA and merged through the merge queue with checks green.

    Closing as completed by hand for exactly that reason: the contributor PR body carries no Fixes line, so GitHub will not auto-close this issue.

  4. removed
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 21, 2026
  5. Birfy commented on Oct 21, 2026

    @Birfy
    CollaboratorAuthor

    Closing as completed — fixed by #612, merged as 81c708d0 (2026-10-21T11:29:59Z).

    authz.js no longer decides the Agent endpoints (agent-session / agent-adopt / agent-archive / agent-rename / remove-agent) from body.botId ?? body.ownerBotId; they follow the shared-resource rule like add-agent, so a signed-in sole member can use them and a shared team gets bot/blocked-shared.

    The merge commit 81c708d0 is the evidence: core/test/authz.test.js asserts those five endpoints (failing on bot/forbidden without the change) and core/test/room-membership.test.js asserts a delete-bot answer keeps another owner's Bot out. The related delete-bot / set-main / remove-agent / delete-room answers now pass the actor instead of returning the unfiltered view.

    Note: the set-main / body.replace privilege hole found in the same endpoint family is tracked separately as #613.

  6. self-assigned this
    on Oct 21, 2026
  7. added
    agent-prPull request opened by an agent
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 21, 2026
  8. reopened this on Oct 21, 2026
  9. Birfy commented on Oct 21, 2026

    @Birfy
    CollaboratorAuthor

    Reopened with evidence: #612 does not fix this. #612 changes authz.js (Agent HTTP endpoints + four answers leaking the unfiltered view); it touches no approval path. The report here is an approval card that comes back after "Always allow".

    Measured root cause (branch fix/608-standing-approval-verdict-gap, PR #616, based on 81c708d0): standingCovers in core/src/host/approvals.js honours a grant only when settled(...) === owner; a turn that carries no message verdict settles to undefined, so the grant is skipped and the card re-appears. DSH opens exactly that kind of turn for its own retry after an approval answer.

    Reproduction in core/test/group-status.test.js: grant always-bot from a group card, then open the Bot's own-chat turn with no message (as DSH does on retry) and ask the same kind — on main's approvals.js that is 16 pass / 1 fail (#608: an own-chat turn that carries no verdict still honours the Bot grant); with the fix 17/17.

    Still unproven by me: which turn the owner's screenshot came from (session, request, interval). The gap above is real and reproducible either way; the screenshot would tell us whether a second, different skip is also in play (other verdict from a shared scheduled turn or a room with other people's Bots — both still ask by design).

  10. Birfy commented on Oct 21, 2026

    @Birfy
    CollaboratorAuthor

    Correction to my earlier comment ("Closing as completed — fixed by #612"): that was wrong, and the reopen is right.

    #612 only touched authz.js (the Agent HTTP endpoints and the four answer leaks). It did not touch the approval path, so it cannot fix this issue. The remaining cause is the one Dev found: standingCovers honours a grant only when settled(...) === OWNER, while the retry turn DSH starts after an approval carries no verdict, so the grant is skipped and the card returns.

    Tracking is on #616 (fix/608-standing-approval-verdict-gap). Note for review: that change widens the grant's scope from "verdict is owner" to "owner's Bot in the owner's own chat when the verdict is missing", so it is an approval-scope change to be reviewed as such, not a pure bug fix.

    Ignore my earlier "evidence: merge commit 81c708d0" line — that commit is unrelated to this issue.

  11. removed
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    agent-prPull request opened by an agent
    on Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:automationScheduled tasks and automationarea:securityAuth, grants, approvals, secretsarea:uiWeb/desktop UI and copybugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions