Repository navigation
Save the owner's keys for all of the owner's Bots by default - #547
Conversation
A connector saved GITHUB_TOKEN and COMPOSIO_API_KEY for no Bot, so the owner's Bots could not use the key the owner connected (owner decision 2026-10-20, ThinkFlowLab#359). A key is now for all of the owner's Bots unless the owner narrows it; a chosen scope carries scopeSet, and an empty list without it (the old connector default) moves to all Bots once. The Secrets page offers All my Bots, Chosen Bots or No Bot. Fixes ThinkFlowLab#545
Self-review of ThinkFlowLab#545: with connector keys now for all Bots, a friend's turn on a shared Bot could read GITHUB_TOKEN in the shell or have a Bot save a capability that sends it elsewhere. A shell gets keys only on the owner's own turn (or, outside a known turn, on a Bot shared with nobody), and a capability on a shared Bot gets only a key whose list names it, the same fail-closed rule as the connector tools (ThinkFlowLab#359).
Self-review (review-pr) — PASSChecked line by line (
Not merge authority: T3 needs the maintainer's approval through GitHub. |
|
Self-review (review-pr, Birfy reviewer agent, 2026-10-20 21:20 Asia/Shanghai): PASS (merge-main conflict fix; no feature change) Tip SHA: 37c9688
Findings: none to act on. This review does not authorize a merge: it still needs the maintainer's approval (the owner queues it). |
Generated patches regenerated from the merged core/; topics.json keeps main's src/host/approvals.js and this branch's src/client/secret-card.js.
|
Self-review (review-pr, Birfy reviewer agent, 2026-10-20 Asia/Shanghai): PASS (merge-main conflict fix; no feature change) Tip SHA: 1974ed7
Findings: none to act on. This review is not merge authority by itself; the maintainer's approval is recorded separately. |
|
Owner approval in chat 2026-10-20 21:46 Asia/Shanghai: merge. |
…kFlowLab#551) A Bot that works on something handed out in a group (a member there sends it the work with `message_bot`) runs it in a hidden turn of its own chat. Its `ask_user` card therefore landed in the Bot's private chat, and an answer there never went back to the group. Now the card sits in that group's composer dock, named for the Bot that asks. The answer reaches the Bot as a hidden request from the member that handed the work over, so the Bot's reply goes back to the group the same way the work does. The group shows a quiet notice of the answer, and the Bot's private chat gets no card and no visible turn. Fixes ThinkFlowLab#550 - `tools.js`: `ask_user` in a turn that answers a group member's request (`senderRoomId`, not `audience: 'user'`, not a friend's) writes `state.questions[<room>]` (`header`, `botId`, `replyTo`, the turn's `origin`, `allowCustom`). Only one card per group: while one is open, a second Bot is told to ask in its reply. `rt.answerGroupQuestion` delivers the answer and posts the notice. - `channel.js` `answer-question`: routes a room card to it. `delivery.js`: a header for it (`answeredIn`). `turns.js`: a typed group line no longer clears the group's card. - `authz.js`: only the asking Bot's owner or the room's owner sees or answers such a card. A non-owner's answer carries `origin: other`. - `roster.js`: deleting the room or the Bot drops the card. Face-to-face rooms use the same path on the local home. - Docs: `core-host.md`. Changelog fragment `550-group-questions.fixed.md`. Not changed: `ask_user` inside a group Session is still refused (the Bot asks in its reply, which already shows in the group). Secret cards stay private. `reply_to: "user"` hand-offs are still answered in the Bot's own chat by design. ## Verification (tip 6dfe7ba) - The second commit, 6dfe7ba, runs the answerer's display name through `cleanName` before it goes into the group notice. - Red at base: 11f80dd with only `test/group-work.test.js` and `test/authz.test.js` copied in gives 4 fail / 27 pass. The 4 new ThinkFlowLab#550 tests fail and the own-chat guard test passes. At the tip they all pass. - `ARCH_DOCS_BASE=origin/main TZ=UTC npm run verify` passes: core 1121/1121, social 313, tree 83, timeline 93, scripts 93, interop 37, live-e2e 16; arch-docs OK; patches check ok. oxlint warnings are 53 at both base and tip. - On the first verify run (at 368b4fb), `tasks.test.js` "an untagged hold stamps the latest working task…" failed once under full-suite load. It passed 3 of 3 alone and the rerun was fully green. That test uses millisecond timestamps, and this PR does not touch that code. - DSH smoke (`dev/bench.sh` + `dev/smoke.mjs`, DSH 0.2.0-rc.2, mock model) passes all 42 steps at 6dfe7ba. Not run: Desktop app, a real model, a live two-home face-to-face run, and a browser check of the group dock rendering. The client is unchanged: `QuestionDock` already reads `questions[sessionId]` for the open conversation and shows `header`. File overlap with open PRs: ThinkFlowLab#544 touches `authz.js`, `channel.js`, `topics.json`, `core-host.md` and the 0001/0005 patches; ThinkFlowLab#547 touches `0001-core-fixes.patch`, `topics.json` and `core-host.md`. The source hunks are in different places. `topics.json` adds `test/group-work.test.js` to topic 0001. --------- Co-authored-by: Birfy <15378933+Birfy@users.noreply.github.com>
Fixes #545
Owner decision 2026-10-20 20:21 (Asia/Shanghai), per #359 / AGENTS.md hard rule 4: the owner's connectors and secrets are on by default for all of the owner's own Bots.
Root cause.
connector-connect(core/src/host/connectors.js) savedGITHUB_TOKEN/COMPOSIO_API_KEYwithscope: []on a first connect, so the Secrets page andlist_secretsshowed "No Bot" and no Bot's shell got the token. An empty scope list could not be told apart from an owner's choice.Change.
connectors.js: noscope: []; a connector key gets the normal default (all Bots), a reconnect keeps the existing scope.secrets.js: a scope the owner chose is stored withscopeSet: true(Secrets pagesecret-update/secret-setwith a scope, a card's "Only ", a deleted Bot leaving a picked list). On load, an empty list withoutscopeSet(the old connector default) becomes'all'once and is written back by the holding host. Pre-Owner's connector keys and secrets default to 'No Bot'; make them available to all of the owner's Bots (#359) #545 empty lists the owner picked by hand carry no marker and are widened too (not distinguishable).secret-card.js): explicit three-way control All my Bots / Chosen Bots / No Bot; the row tag says "All my Bots". zh strings added.settledinturn-origin.js), and outside a known turn only while the Bot is shared with nobody; a friend's Bot never. A capability (canUseSecret) on a Bot shared with anyone gets only a key whose list names that Bot, never an'all'key — otherwise a friend's turn could have a shared Bot save an HTTP capability that sends$DSH_SECRET_GITHUB_TOKENelsewhere.connector-access.jsis unchanged.changelog.d/545-secrets-all-my-bots.fixed.md.Risk tier: touches
core/src/host/secrets.js(secret exposure) → expect T2/T3; see the controller's label.Verification (tip
2f484fe)b6e89d2(tests only):connectors.test.js2 fail (scope[]≠'all'),secrets.test.js2 new fail (migration, explicit No Bot),tool-cells.test.jsfails (no three-wayScopeEditor). Red atc0d189f(first commit): the shared-Bot shell test and the shared-Bot capability test.DSH_HARNESS=core/dev/harness ARCH_DOCS_BASE=origin/main TZ=UTC npm run verify: exit 0 — core 1117/1117, social 312/312, tree 83/83, timeline 93/93, .github scripts 93/93, interop 37/37, live-e2e 16/16; lint + arch-docs +build-client --check+ds-bot-patches checkok.dev/bench.sh smoke545 3196 8896 reset && node dev/smoke.mjs smoke545 3196against deepseek-harnessdsh-v0.2.0-rc.2: all 42 steps passed. (Bench trap: pnpm 11 did not linkds-botinto the bench profile; linkedprofiles/web/node_modules/ds-botby hand.)2f484fe:tests-okgreen.Not run: Desktop app; real-model run; the owner's running instance.