# Bot Owner Permissions Some `/sudo` features (hub server-wide lockdown, future feature flags + force-clear-caches, etc.) require **bot owner** authority — a stricter level than sudo. Sudo can edit settings; bot owners can pull kill switches. ## Resolution `src/services/botOwner.ts` resolves bot-owner status dynamically: 1. Reads `client.application.owner`. When the bot belongs to a **Team** on the Discord dev portal, this is a `Team` (not a `User`), and `Team.members` enumerates everyone with access. 2. **Team Admins and Developers** count as bot owners. **Read-only** members do not. 3. The team's own `ownerId` is always included regardless of their TeamMember role. 4. `BOT_OWNER_ID` env is always added as a fallback so the bot keeps working before a Team is set up. The resolved ID set is cached for 60 s, pre-warmed on `READY`, and logged so misconfiguration is obvious: ``` 🟢 Bot owners (3): 117501528641634310, 484484232199012352, 539266131651854336 ``` If no owners resolve, the bot logs a warning: ``` 🟡 Bot owners: none resolved. Set BOT_OWNER_ID env or assign Admins/Developers on the Discord dev portal Team. ``` ## Setting up a Team To use the team-based path: 1. Open the [Discord dev portal](https://discord.com/developers/applications) and the SquishyBot application. 2. Under **Teams**, create or attach a team for the bot. 3. Add team members and assign **Admin** or **Developer** roles to anyone you want to grant bot-owner authority. 4. Restart the bot (or wait up to 60 s for the cache to refresh). 5. Verify in the startup log that the resolved IDs match what you expect. ## API ```typescript import { isBotOwner, getBotOwnerIds, invalidateBotOwnerCache } from '../services/botOwner' // Gate a bot-owner-only action if (!await isBotOwner(client, userId)) { await interaction.reply({ content: '❌ Bot-owner-only.', ephemeral: true }) return } // Get the full set (e.g. for fan-out DMs) const ids = await getBotOwnerIds(client) ``` `invalidateBotOwnerCache()` forces the next call to re-fetch from Discord — useful right after editing team membership. ## Current bot-owner-only surfaces | Surface | Function | |---|---| | `/report` Approve / Reject buttons | Only bot owners can approve or reject reports | | `/sudo → Hub Channels → 🚨 Lockdown → Lock all` (15 m / 1 h / 4 h) | Server-wide hub kill switch | | `/sudo → Hub Channels → 🚨 Lockdown → Unlock all` | Lift server-wide lockdown | | `/sudo → Settings → Debug → Feature flags` | Per-feature runtime kill switches | | `/sudo → Settings → Debug → Force-clear caches` | Reload settings / games / social feeds / bot-owner cache | | `/sudo → Settings → Debug → Orphan resource scan → Clean up orphan rows` | Delete fully-orphaned DB rows | ## Debug sub-panel `/sudo → Settings → Debug` is visible to any sudo but the action buttons gate on `isBotOwner()`. Three things live here: 1. **Feature flags** — Each toggle gates a feature path at runtime: | Flag | Gates | |---|---| | `feature.auto_voice` | `handleHubJoin` (existing auto-channels keep working when off) | | `feature.auto_threads` | `messageCreate maybeAutoThread` | | `feature.social_poller` | `social/poller runPoll` | | `feature.presence_renames` | `presenceUpdate` | | `feature.birthday_pings` | `birthdayScheduler runForDate` | | `feature.auto_role_on_join` | `guildMemberAdd` auto-role apply; default OFF (#36) | | `feature.color_roles` | `/color` picker; default OFF (#38) | 2. **Force-clear caches** — One button calls `loadSettings`, `loadGames`, `loadSocialFeeds`, and `invalidateBotOwnerCache`. Equivalent to a hot reload of the cache layer without a process restart. 3. **Orphan resource scan** — Walks `auto_channels`, `hub_channels`, `auto_thread_channels`, `games`, `archived_channels` and reports rows whose Discord channels/roles are no longer in `guild.channels.cache` / `guild.roles.cache`. Cleanup deletes rows where *every* reference is gone; partial-orphan rows (e.g. a game whose `ping_role_id` is missing but channel still exists) are left intact so they can be edited via the Games panel. Planned additions (see [Feature Roadmap](Feature-Roadmap.md) / GH project board): - Unlimited social-feed throttle (issue #29; non-owners capped at 3) - Sudo `/report` triage view (issue #24; bot-owner gated)