Slack bot token SSOT — slack.json (MC #102830) — 2026-06-03 Summary MC #102830 makes ~/system/config/slack.json the single source of truth (SSOT) for the Slack bot's tokens, with environment-variable fallback, and removes the hardcoded tokens from the LaunchAgent plist. Previously the com.john.slack-bot.plist hardcoded both SLACK_BOT_TOKEN and SLACK_APP_TOKEN in EnvironmentVariables — so a token rotation that wasn't mirrored into the plist would strand the daemon with a stale token. Change slack.json ( ~/system/config/slack.json , mode 0600): now holds token (xoxb bot), app_token (xapp), workspace , bot_name . slack-bot.js loadSlackTokens() (line ~443): reads slack.json first (SSOT); returns {botToken, appToken} when both present; otherwise silently falls through to the existing Keychain → vault → env chain. Env-var fallback preserved. com.john.slack-bot.plist : SLACK_BOT_TOKEN and SLACK_APP_TOKEN removed from EnvironmentVariables (GROQ/HOME/PATH untouched). plutil -lint OK. run-slack-bot-reload.sh : reload wrapper added under ~/system/tools/ . Token rotation procedure (new) Edit ~/system/config/slack.json — update token (xoxb) and/or app_token (xapp). bash ~/system/tools/run-slack-bot-reload.sh No plist edit. No risk of stranding the daemon on rotation. Verification plist: grep -c SLACK_*_TOKEN = 0; plutil -lint OK. slack.json: mode 0600; keys token/app_token/workspace/bot_name. slack-bot.js: node --check SYNTAX_OK; SSOT branch at line 443. Daemon: launchctl PID 42749, LastExitStatus 0, stable; log Tokens loaded from slack.json (SSOT) + Slack bot started (Socket Mode) . Live: slack.js send #ops succeeded (token valid). Independent verifier (Company Mesh / eval-Proveo): PASS — mesh-thr-b04409c5-ab59-4ff1-bc24-b163433bd063 . til-done: DONE — /tmp/til-done/102830-20260603T142915Z.json . Security note This also improves posture: secrets moved out of a (potentially world-readable) LaunchAgent plist into the 0600 slack.json. Token values are never logged (masked).