Skip to content

Give the owner's keys to every turn of the owner's own Bots - #656

Merged
Birfy merged 2 commits into
ThinkFlowLab:mainfrom
Birfy:fix-601-secrets-every-turn
Oct 22, 2026
Merged

Birfy merged 2 commits into
ThinkFlowLab:mainfrom
Birfy:fix-601-secrets-every-turn

Conversation

@Birfy

@Birfy Birfy commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #601

Rebased onto main after #654 merged (ee1739e). Two commits: 480c22d (secrets) and fb70b22 (connectors + GitHub guidance).

Owner decisions (recorded on #601):

  • 2026-10-22 08:32 Asia/Shanghai: 「放开这个权限管理,我的bot都应该能看到」. Every one of the owner's own Bots gets the owner's saved keys on every turn, wherever the turn came from.
  • 2026-10-22 08:42 Asia/Shanghai: 「放开,主要应该用连接器工具」. Connector tools follow the same rule, and Bots should use them first for GitHub work.

The boundary that stays: a friend's Bot or a remote home never gets the keys or the connector tools. A per-key Chosen Bots scope and a per-Bot connector switch are still respected.

What changed

Secrets (core/src/host/secrets.js)

  • withheldReason and ownersTurn are removed, and secrets no longer import turn-origin.js. resolveEnv hands out every key in the Bot's scope on any turn: group rounds of any origin, relays, scheduled turns, shared Bots' turns, and turns with no recorded origin.
  • A sub-agent's shell follows its parent chain to its Bot through rt.whoseAgent, the same chain the connector guard uses.
  • DSH_SECRETS_WITHHELD now names only the real boundaries: remote-bot, not-in-scope and unknown-bot.
  • list_secrets and request_secret no longer say a key is "withheld this turn".
  • canUseSecret (capabilities) follows the same rule.

Connectors (core/src/host/connector-access.js, turns.js, client)

  • The guard no longer reads the turn's origin. Every turn of the owner's own Bots may use the connector tools (mcp__github__*, mcp__composio__*), including sub-agents, which resolve to their parent. A friend's Bot gets none, and a Bot whose connector the owner turned off gets none.
  • The "also when others use it" switch is removed, along with connectorsShared, the sharing-follow machinery, connectorTurnChanged and its calls in turns.js. This removes the most dead code.
    • setBotConnector ignores a scope sent by an older client.
    • A legacy connectorsShared flag is dropped.
  • The UI (connector-bots.js) shows one switch per Bot, and the related i18n strings are removed or reworded.

GitHub guidance (core/src/host/prompt.js)

  • One new line: use the GitHub connector tools first, and $DSH_SECRET_GITHUB_TOKEN with gh/git only as the fallback (for example git push).

Docs

  • AGENTS.md (hard rules 2 and 4)
  • docs/subsystems/core-host.md, team.md, core-client.md
  • README.md and README.zh.md
  • changelog.d/601-secrets-every-turn.changed.md

Tests

  • secrets.test.js and capabilities.test.js cover:
    • a group round with origin other
    • a turn someone else started
    • a shared Bot's scheduled turn
    • a shared Bot outside a known turn
    • sub-agent bash, plus unknown-bot when the parent chain is lost
    • Chosen Bots scope
    • a friend's Bot getting remote-bot
  • connector-access.test.js covers:
    • every turn origin, including a friend in the room
    • turning a connector off and on for one Bot
    • a sub-agent following its parent
    • legacy connectorsShared and scope being dropped
    • disconnecting a connector
    • a new Bot or a copy starting on
    • a friend's Bot getting nothing
  • connector-bots.test.js: the single-switch UI.

Left open

  • The trade-off the owner accepted: a friend talking to a shared Bot, or anyone in a group round, can now steer a turn that holds the owner's key and the GitHub connector.
  • turnOrigin is still used by standing approvals and resumed turns. The optional cleanup was skipped.

Verification (head fb70b22e26565be67f2498caeb43b09d3b648767, rebased on main ee1739e)

  • ARCH_DOCS_BASE=origin/main TZ=UTC npm run verify → pass: core 1201/1201, plugin suites 317/89/104/132/37/16, arch-docs OK on 29 files, patches check ok, and 85 lint warnings (unchanged).
  • Smoke: dev/bench.sh … reset && node dev/smoke.mjs with deepseek-harness 0.2.0-rc.2 → all 42 steps passed on the rebased head.
  • Red at base:
  • Not run: the CI package job, the desktop app, and a real-model or real DSH sub-agent run.

@Birfy Birfy added bug Something isn't working agent-pr Pull request opened by an agent area:security Auth, grants, approvals, secrets labels Oct 22, 2026
@Birfy Birfy self-assigned this Oct 22, 2026
@Birfy

Birfy commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator Author

Review — self-review (review-pr), owner's reviewer agent as Birfy

Rules loaded from origin/main a5a887b: review-pr, code-standards, AGENTS.md, LESSONS.md. This review is in the same session as the implementation, not a fresh-context session; self-PASS is allowed by selfReview.

Tip SHA: 85f7b07048f439b1b0dd02d6a6be1a5ad3e77c37
Ran:
  - ARCH_DOCS_BASE=origin/main TZ=UTC npm run verify (core/dev/harness) → pass (core 1204/1204; plugins 317/89/104/118/37/16; arch-docs OK, 10 files; patches check ok)
  - CONTEXT_WINDOW=100000 CHECK_RATIO=0.45 dev/bench.sh smoke601 3196 8896 reset && node dev/smoke.mjs smoke601 3196 (DSH_HARNESS=deepseek-harness 0.2.0-rc.2 checkout) → pass (42/42)
  - red at base: tip's core/test/secrets.test.js + capabilities.test.js on #654 head ad0c471 → fail (12 fail / 25 pass; all 7 #601 cases red; friend's-Bot boundary green on both)
  - node scripts/ds-bot-patches.mjs generate && check → pass
  - node .github/scripts/changelog.mjs check → pass
  - lint warning count vs #654 tip → 85 / 85, no new warnings
Not run:
  - CI package job (pack, typecheck, actionlint) — left to CI
  - Desktop app, real-model run, a real DSH sub-agent — the sub-agent path is tested through the Agent shape (session.header.parentSession) that connector-access already relies on
Verdict: PASS

Findings. Nothing blocks this PR.

Non-blocking notes:

  1. turnOrigin in turn-origin.js no longer has a caller, and its comment still names Secrets: an absent $DSH_SECRET_* says nothing — distinguish not-configured, withheld-this-turn and empty, and honour an explicit per-Bot scope on the owner s scheduled turns #651's use. It can be removed in a follow-up.
  2. Connector tools keep the per-turn rule, so the shell has the token where mcp__github__* is refused. This is follow-up question 1 in the PR body, and the owner decides it.
  3. canUseSecret widening for capabilities: follow-up question 2 in the PR body.

Security. This is a deliberate widening on the secrets surface, authorised by the owner on 2026-10-22 08:32 (Asia/Shanghai) and recorded on #601. No fence or display-name code is touched.

Stacked on #654, so merge #654 first. This review is not merge authority, and nothing was enqueued.

Birfy added 2 commits October 22, 2026 08:51
…wLab#601)

Owner decision 2026-10-22 08:32 (Asia/Shanghai): the owner's Bots should
all see the owner's secrets. resolveEnv no longer reads the turn's origin
(withheldReason/ownersTurn are gone): a group round, a relay, a scheduled
turn, a shared Bot's turn, a turn with no recorded origin all get the keys
the scope allows. A sub-agent's shell follows its parent chain to the Bot
through connector-access's whoseAgent. A friend's Bot still gets nothing
and a Chosen Bots scope still limits which Bots get a key; those are the
only DSH_SECRETS_WITHHELD reasons left, plus unknown-bot for a chain that
cannot be followed. canUseSecret (capabilities) follows the same rule.

Fixes ThinkFlowLab#601
…Lab#601)

Owner decision 2026-10-22 08:42 (Asia/Shanghai) on ThinkFlowLab#601: the connector
tools follow the same rule as secrets. connector-access.js no longer
reads the turn's origin or who a Bot is shared with: every turn of the
owner's own Bots (group rounds of any origin, relays, schedules, shared
Bots, turns with no origin, sub-agents via their parent) may use them.
A friend's Bot and an unresolvable Agent still get none; the per-Bot
off switch stays. The "also when others use it" switch is removed from
host, client and i18n; a stored connectorsShared offer is dropped on the
next switch or disconnect, and a scope from an older client is ignored.
connectorTurnChanged, followSharing and the unused turnOrigin are gone.

The Bot rules now say to use the GitHub connector tools first and
$DSH_SECRET_GITHUB_TOKEN with gh/git only as the fallback (git push).

Fixes ThinkFlowLab#601
@Birfy
Birfy force-pushed the fix-601-secrets-every-turn branch from 85f7b07 to fb70b22 Compare October 22, 2026 00:51
@Birfy

Birfy commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator Author

Self-review (head fb70b22e2656, rebased on main ee1739e after #654 merged)

Verdict: ready for the owner to queue (T2/T3). No blocking findings.

Checked

  • Secrets path: no turn-origin import is left, and resolveEnv resolves sub-agents through rt.whoseAgent. DSH_SECRETS_WITHHELD is still declared to shell-env, so Declare DSH_SECRETS_WITHHELD so a withheld turn keeps its shell #654's fix holds after the rebase. Its reasons are limited to remote-bot, not-in-scope and unknown-bot. No value is ever printed.
  • Connector guard:
    • allowed = bot.remote === undefined && !turnedOff(bot, id).
    • A friend's Bot, and a Session whose Bot can't be resolved, still fail closed.
    • DSH-only sessions are unchanged.
    • No connectorsShared or connectorTurnChanged readers are left. A legacy flag is deleted on the next switch or disconnect, and a scope from an older client is ignored.
  • settled/turnOrigin: still used by standing approvals, relays (tools.js), resume.js and parts.js. The cleanup was skipped on purpose.
  • Prompt: one line saying GitHub connector tools come first and $DSH_SECRET_GITHUB_TOKEN with gh/git is the fallback (e.g. git push).
  • Docs: AGENTS.md hard rules 2 and 4, core-host, team, core-client, both READMEs and the changelog fragment agree with the code. arch-docs is OK.

Verification

  • ARCH_DOCS_BASE=origin/main TZ=UTC npm run verify on the rebased head → pass (core 1201/1201, every plugin suite passes, patches check ok).
  • Smoke on the rebased head (deepseek-harness 0.2.0-rc.2) → all 42 steps passed.
  • Red at base: the new secrets/capabilities tests fail 12 at Declare DSH_SECRETS_WITHHELD so a withheld turn keeps its shell #654's head, and the new connector tests fail 8/21 against the secrets-only commit.

Non-blocking notes

  • The owner has accepted this trade-off: anyone who can steer a shared Bot's turn or a group round now reaches the owner's key and the GitHub connector.
  • Not run: the CI package job, the desktop app, and a real DSH sub-agent.

@Birfy
Birfy added this pull request to the merge queue Oct 22, 2026
Merged via the queue into ThinkFlowLab:main with commit 4f6e3e5 Oct 22, 2026
9 checks passed
@Birfy
Birfy deleted the fix-601-secrets-every-turn branch October 22, 2026 00:58
@Birfy Birfy removed the agent-pr Pull request opened by an agent label Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:security Auth, grants, approvals, secrets bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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)

1 participant