Recipe: analytics listener
Events-only app process with no bridge actions: narrow secret, manifest, strict startup, and safe logging or export.
Analytics, audit logs, and metrics pipelines often need only events—no app.actions.* calls. That is the narrowest capability surface and the easiest scoped secret to reason about.
Manifest (events only)
import { defineShardwireApp, generateSecretScope } from 'shardwire';
export const analyticsManifest = defineShardwireApp({
name: 'analytics-listener',
events: ['messageCreate', 'messageDelete', 'guildMemberAdd', 'guildMemberRemove'],
actions: [],
filters: {
messageCreate: ['guildId', 'channelId'],
messageDelete: ['guildId', 'channelId'],
guildMemberAdd: ['guildId', 'userId'],
guildMemberRemove: ['guildId', 'userId'],
},
});
export const analyticsMinimumSecret = generateSecretScope(analyticsManifest);actions: [] keeps the generated minimum scope free of action permissions.
Bot bridge secret
secrets: [
{
id: 'analytics',
value: process.env.SHARDWIRE_SECRET_ANALYTICS!,
allow: analyticsMinimumSecret,
},
],Even if the bot process negotiates a broader secret for other apps, this connection only receives what allow grants.
App process
import { connectBotBridge } from 'shardwire';
import { analyticsManifest, analyticsMinimumSecret } from './analytics-manifest.js';
const app = connectBotBridge({
url: process.env.SHARDWIRE_URL!,
secret: process.env.SHARDWIRE_SECRET_ANALYTICS!,
appName: analyticsManifest.name,
});
app.on('messageCreate', ({ message }) => {
// append-only sink: your warehouse, file, or queue
recordMessageCreated(message);
});
app.on('messageDelete', ({ message }) => {
recordMessageDeleted(message); // BridgeDeletedMessage — partial content is normal
});
app.on('guildMemberAdd', ({ member }) => {
recordMemberJoined(member);
});
app.on('guildMemberRemove', ({ member }) => {
recordMemberLeft(member);
});
await app.ready({
strict: true,
manifest: analyticsManifest,
botIntents: ['Guilds', 'GuildMessages', 'MessageContent', 'GuildMembers'],
expectedScope: analyticsMinimumSecret,
});Operational advantages
- Least privilege: a leaked analytics secret cannot send messages or ban users.
- Predictable load: you can scale read-only consumers without touching moderation or dashboard secrets (Secret cookbook).
Related
Recipe: interactions worker
App process handles slash commands and components: interactionCreate manifest, defer/reply actions, strict startup, and scoped secrets.
Recipe: music bot + remote web controller
Use Shardwire for Discord voice and member actions while a separate channel carries player/queue state for a dashboard—no custom wire primitives.