feat(teams): the slash-command seam, and the first command through it
Phase 7 of TEAMS.md. `api.registerSlashCommands` stops throwing: a module registers a command's DEFINITION and its HANDLER together, the bot pulls the definitions over the internal listener and runs none of our code, and the handler executes here — forced by the bot container having no `modules` volume, and the right boundary anyway. Registration validates what Discord would reject as a batch (names, description lengths, the four option types, required-before-optional), because the bot registers the whole set in one PUT and a single bad entry costs every command including the bot's own. Commands are not namespaced under their owner — there is no dot in Discord's name grammar — so collisions are first-come with the holder named. The dispatcher is the access boundary: `linked` has no Discord equivalent, so the platform-side permission default can only ever be advertising. It resolves the actor by `auth_providers.kind` rather than the id slug, treats a banned account as unlinked, bounds a handler under the bot's own timeout, and keeps `ok` outside the envelope so a handler cannot forge it. Liveness is asked at both the pull and the dispatch. The registries have no removal path, so a module an operator disables at runtime would otherwise keep a live handler behind a command Discord still advertises. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -282,13 +282,16 @@ function buildApi(record) {
|
||||
once('registerTeamProvider')
|
||||
record.staged.registerTeamProvider(provider)
|
||||
},
|
||||
// Declared in 1.6.0 with the rest of the Team surface; the bot half that
|
||||
// executes a command lands in phase 7 (§7.1). Present and throwing rather
|
||||
// than absent, so a module written against the published version fails at
|
||||
// registration with a sentence naming the phase, instead of at whatever
|
||||
// moment someone first types the command.
|
||||
registerSlashCommands() {
|
||||
throw new Error('api.registerSlashCommands is not available until Discord slash commands land (TEAMS.md §7.1)')
|
||||
// Chat-platform slash commands (API 1.6.0, §7.1), live since phase 7. Like
|
||||
// registerTeamProvider above, the handler this stages is core CALLING THE
|
||||
// MODULE and waiting for an answer — but from further away than any other
|
||||
// member: the caller is a bot in another container, holding a Discord
|
||||
// interaction open on a deadline. `once` for the same reason the two
|
||||
// registries above take it — a second call is a module changing its mind
|
||||
// halfway through register(), not adding to what it already said.
|
||||
registerSlashCommands(commands) {
|
||||
once('registerSlashCommands')
|
||||
record.staged.registerSlashCommands(commands)
|
||||
},
|
||||
// The two lifecycle hooks (§2.5). Registered here, dispatched from
|
||||
// lifecycle.js — this file runs with no database and the hooks run with one.
|
||||
|
||||
Reference in New Issue
Block a user