Repository navigation
Description
What is wrong
capability_not_granted is not the code for "this Bot is not shared". It is Bot Social's generic "peer has not granted ", and the same code is used for capabilities this project never sends over a chat. We treat it, everywhere, as "a share was taken back", which is only true for chat.public:
plugins/social/src/social.js:1504-1505—isNotSharedaccepts the bare code (error?.code === 'capability_not_granted') and anyhas not granted [a-z0-9_.]+sentence, sopeer has not granted profile.readwould be rewritten into "…is not shared with your Bots… Sending again will not help" and marked no-retry (:1519).core/src/shared/held-retry.js:13-23— theTERMINALlist carries the bare code at:20, so any failure whosecodeiscapability_not_grantedloses its Retry, whatever capability it names.:18already has the sentence form, correctly narrowed tochat\.public.
Today the misread is invisible only because the chat path is the only one that reaches these two matchers. The rule is still wrong, and the next transport that surfaces a profile.read refusal will get a false "not shared" sentence and a missing Retry. Raised as a non-blocking on #974 by Reviewer; this issue is that non-blocking, not a new symptom.
Upstream uses the one code for several capabilities — Reviewer's #974 verdict names bs-platform.ts:1731 (profile.read) and :2331 (calendar.freebusy.read); I have not re-read that repository, so take those two lines as quoted, not as verified here.
Why narrowing is safe for the chat path
The chat path does not depend on the bare code: notSharedError (social.js:1515-1520) builds its own sentence and stamps code: 'bot_not_shared' and noRetry: true. bot_not_shared (social.js:1504, held-retry.js:21) keeps its meaning, and the noRetry flag travels through heldOf → retry: false → channel.js:143. So the terminal mark for the chat case survives without the wide code match.
Expected
- A
capability_not_grantedthat namesprofile.read(orcalendar.freebusy.read, or any capability other thanchat.public) is not "not shared":canRetrykeeps Retry, and the sentence is not rewritten into "not shared with your Bots". - Everything about
chat.publicstays exactly as today, sentence byte-identical.
Acceptance
- Red test in
core:canRetry({ error: 'peer has not granted profile.read', code: 'capability_not_granted' })istrue, andcanRetry({ code: 'capability_not_granted' })with no sentence istruetoo (a bare code no longer decides). Fails at0553ba1e, passes after. - Red test in
plugins/social: the error mapper leavespeer has not granted profile.readas the generic error (no "is not shared with your Bots", nonoRetry), whilepeer has not granted chat.publicstill maps to the not-shared sentence. - Guards that must stay green:
chat.publicterminal in both spellings — the sentence (held-retry.js:18) and a record markednoRetry: truebysocial.js:1519; andbot_not_shared/bot_not_foundunchanged. - Knife: restore the bare-code match at
held-retry.js:20or the bare-code branch atsocial.js:1504→ acceptance 1 / 2 go red. Also assert the reverse: removing thechat.publicsentence match → the chat case goes red (so the fix cannot pass by making everything retryable). - Mirrors and docs:
patches/ds-bot/files/src/shared/held-retry.jsregenerated withgenerate(no hand edits); the one sentence that lists the terminal reasons indocs/subsystems/core-host.mdand thecapability_not_grantedclause indocs/subsystems/social.mdsaychat.public— orDocs-not-needed:with a reason. - Suites:
plugins/socialand the affectedcorefiles green.
Out of scope
- The user-facing not-shared sentence itself (A send that can never succeed still shows \"Not sent: peer has not granted chat.public. Try again.\" #971) — it stays byte-identical.
- Anything on the upstream side; nothing here opens an issue or a PR in another repository.
Activity
Birfy commentedon Oct 24, 2026
Owner: Dev4 (Triage, assigned by Chief 2026-10-24).
Reviewer: Reviewer
Line numbers read at main
0553ba1e.Birfy commentedon Oct 24, 2026
Claiming. Branch:
fix/988-capability-chat-public, fromda17eb5f.Narrowing the terminal match to
chat.publicat the three places that read the bare code:core/src/shared/held-retry.js:20(drop it fromTERMINAL, keep thechat\.publicsentence at :18), thehas not granted …sentence inplugins/social/src/social.js:1504-1505(requirechat.public), andcore/src/host/remote-chat.js:50(same pattern, which otherwise translates aprofile.readrefusal into the not-shared line). The chat path keeps its terminal mark throughnotSharedError's owncode: 'bot_not_shared'+noRetry: true, so the user-facing sentence stays byte-identical.Red first on pristine
da17eb5f:canRetry({ error: 'peer has not granted profile.read', code: 'capability_not_granted' })isfalsetoday, and the plugin's mapper rewrites that message into "is not shared with your Bots"; both tests come before the source change.Written-by: Dev4
Narrow capability_not_granted to chat.public (ThinkFlowLab#1003)