Repository navigation
Description
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: e235ecb932d34d92bfb93b810f64c70a
Branch: dev/4-retired-inbound-grant
Base: 7b8f81e
At: 2026-10-30T05:29:25Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.
Written-by: FlyBot Lead
What a person sees
A Bot that was shared with a friend's Bot and later retired still accepts messages from that friend's Bot: the retired Bot runs a turn, reads the memory it kept, and spends the owner's model budget — with nothing on screen telling the owner it happened. From the friend's side it looks like the Bot is still there.
Where (main 7b8f81e15a803d54a13fe32d2c0bc2119e7f9333, and the same code at 92a4cf26)
core/src/host/roster.js:519-540archiveBotwritesretired/hidden, stops the timers and files a failure card — but leavesstate.grantsuntouched; only the delete path clears sharing (roster.js:584rt.forgetBotSecrets).core/src/host/hooks.js:733-736sendchecks that the target exists, not that it is retired.core/src/host/reach.js:323-353reach()never looks atretiredBot.
Reproduction
grantTo('b', '@bob.bot'); the friend's Bot sends one message →{"action":"allow"},delivered: 1.archive_bot Writer→retired: true; the grant survives:grants: ["b"],[{"id":"b:@bob.bot::0","grantee":"@bob.bot"}].- The same message again →
{"action":"allow"},delivered: 2, and it lands as[Message from Bob] <untrusted-message from="Bob"> hello after </…>.
Expected: after retirement the outside sender is refused, the same way message_bot refuses a retired Bot's name ("No Bot named …").
This is not the channel.js send case: that is the owner typing in their own chat, which docs/subsystems/core-host.md:217 explicitly keeps ("opens the chat again"). This one is triggered by an outside party and is invisible to the owner, and the docs do not keep it.
Expected
A retired Bot cannot be reached from outside: the shared grant either stops resolving (the clean fix — clear state.grants[id] in archiveBot and rt.reachChanged(id), symmetric with the delete path) or reach()/send refuses a retired target with the same No Bot named-shaped refusal.
Scope
5-10 lines plus one case in core/test/retired-bot-paths.test.js; regenerated patches/ds-bot/0001/0002. It is a generate face, so the PR queues behind the ones already in flight.
Dedupe (searched 2026-10-30, open + closed)
retired grant→ 4 hits: Sharing to a home member that was deleted reports success and can never deliver #1125 (a deleted home member's share stops working — different surface) and docs/self-test material.retired shared bot inbound→ 1 hit, A friend's Bot added to a local group shows the raw FLYBOT-ROOM-SHARE envelope on its approval cards #847 (a face-room card).archive_bot grant→ 0.
Activity