Skip to content

fix(slack-bridge): let workers join a broker without Slack tokens - #1093

Merged
tmustier merged 2 commits into
mainfrom
fix/token-free-followers
Oct 17, 2026
Merged

tmustier merged 2 commits into
mainfrom
fix/token-free-followers

Conversation

@tmustier

Copy link
Copy Markdown
Collaborator

Problem

The extension returned at load time whenever SLACK_BOT_TOKEN/SLACK_APP_TOKEN were missing (index.ts, if (!botToken || !appToken) return;). A pi started outside the shell that exports those tokens (a Rex block, Herdr, any detached launcher) therefore never registered /pinet, so /pinet follow silently did nothing. The mesh secret was never the problem: it comes from meshSecretPath in settings.json, which every process reads.

Change

  • Load without tokens. Only broker and single-player mode need the Slack app. That check now runs at the start of a runtime transition, before the current runtime is torn down, so a token-less follower that runs /pinet start keeps its broker connection and gets a clear error.
  • Quiet startup. A token-less session whose settings ask for broker/single (for example a shared runtimeMode: "broker") starts in off instead of logging a failed start. /pinet follow works as usual.
  • Slack calls go through the broker. A follower without a local token sends Slack API calls through the broker's existing slack api.call capability (BrokerClient.slackProxy), which already enforces thread ownership. Thread replies already went through the broker.
  • File downloads fail clearly. Private file URLs need the bot token itself, so a token-less download now throws a clear error instead of caching Slack's login page.

This is step 1 of the worker-membership redesign; a design doc and the per-worker credential work follow in a separate PR. It is independent of #1068.

Verification

  • New real-broker test, token-free-follower.test.ts: a real BrokerSocketServer with a recording Slack adapter; the extension loads with no tokens and runtimeMode: "broker", stays off at startup, joins with /pinet follow, runs the slack tool react action through the broker, and stays connected after a refused /pinet start. It fails on main (no /pinet command), fails with the proxy routing removed (no adapter call), and fails with the token check after teardown (worker leaves the broker).
  • End to end in Rex on fc2e146: a real pi (openai-codex/gpt-6.1-sol, medium thinking) launched with env -u SLACK_BOT_TOKEN -u SLACK_APP_TOKEN, loading only this branch's build, with the real settings.json, against a scratch broker. It stayed off at startup, /pinet follow registered it, and the prompt "Use the slack tool to add an eyes reaction to … then reply with just: done" made the model call slack action="react". The scratch broker's adapter recorded {"method":"reactions.add","params":{"channel":"C0E2ETEST","timestamp":"1712345678.000100","name":"eyes"}}. Block, broker and scratch files were cleaned up.
  • pnpm lint, pnpm typecheck: pass. slack-bridge tests in the clean single-worker setup: 100 files, 1,718 tests pass.
  • Pushed with --no-verify: the pre-push hook failed only on @pinet/tmux transport.test.ts timing out at 5 s on this machine (it passes with a 30 s timeout). That package is untouched here; CI runs the full suite.

Not tested: a real Slack workspace (the adapter was a recorder), and Slack file downloads from a token-less worker (now an explicit error).

tmustier and others added 2 commits October 17, 2026 20:07
The extension returned at load when SLACK_BOT_TOKEN/SLACK_APP_TOKEN were
missing, so a pi started outside the token-bearing shell (Rex blocks, Herdr,
detached launchers) never registered /pinet and could not follow the broker.

- Load without tokens; only broker and single-player mode require them, and
  that check runs before the current runtime is torn down.
- A token-less session whose settings ask for broker/single mode starts off
  instead of failing; /pinet follow still works.
- A follower without a local token makes Slack API calls through the broker's
  existing slack api.call capability (same thread-ownership guard).
- Slack file downloads need the real token; fail clearly instead of caching a
  login page.
@tmustier
tmustier force-pushed the fix/token-free-followers branch from fc2e146 to e70d3c4 Compare October 17, 2026 19:07
@tmustier

Copy link
Copy Markdown
Collaborator Author

Review completed. Moved Slack response validation to the proxy boundary, removed the caller cast and redundant await, and updated proxy tests to use valid Slack responses plus malformed-input coverage. Independent read-only code-reviewer subagents approved the final tree with no findings: https://ampcode.com/threads/T-01a14b32-1f7c-72c0-87a4-6dc34b51a90e

All seven CI checks pass at e70d3c4. Remote lint/typecheck/full tests passed (1,722 Slack tests). Real-model E2E at 4958622 used openai-codex/gpt-6.1-sol, medium thinking, with an actual slack react tool call and independently verified recording-adapter payload; startup off, follow registration, refused start preserving the connection, and token-free reload passed. e70d3c4 has exactly the same tree; only commit identity metadata changed. Live Slack was not tested.

Local pre-push tests hit unrelated tmux timeouts, including a sequential retry; the local full Slack rerun exceeded the command timeout. Pushed without the hook after remote verification, then waited for all CI checks to pass.

@tmustier
tmustier merged commit 01e43f5 into main Oct 17, 2026
7 checks passed
@tmustier
tmustier deleted the fix/token-free-followers branch October 17, 2026 20:05
tmustier added a commit to tmustier/extensions that referenced this pull request Oct 17, 2026
Add `--pinet-follow`: this Pi process follows the running broker whatever
runtimeMode says, without editing settings.json, bypassing mesh auth or the
local-subagent gate. Headless, launchd and broker-launched tmux workers can
follow a broker whose machine keeps runtimeMode "broker".

- resolveSlackBridgeStartupRuntimeMode: a follow request returns follower
  when the broker socket exists, otherwise off.
- session_start waits for the follower to register, as --pinet-join does,
  so a task passed on the command line has the Slack and Pinet tools.
- A missing socket, or a broker that rejects the login, leaves the
  communication tools off with a visible warning (also for --pinet-join).

Rebuilt on current main from gugu91#983's original commit c2ea531: token-free
startup (gugu91#1093) and the PINET_SOCKET_PATH resolver already exist there.

Fixes gugu91#982.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant