feat(config): gate channel config writes

This commit is contained in:
Peter Steinberger
2026-01-15 01:41:11 +00:00
parent f65668cb5f
commit ad8799522c
28 changed files with 576 additions and 2 deletions

View File

@@ -269,6 +269,20 @@ const FIELD_HELP: Record<string, string> = {
"commands.debug": "Allow /debug chat command for runtime-only overrides (default: false).",
"commands.restart": "Allow /restart and gateway restart tool actions (default: false).",
"commands.useAccessGroups": "Enforce access-group allowlists/policies for commands.",
"channels.telegram.configWrites":
"Allow Telegram to write config in response to channel events/commands (default: true).",
"channels.slack.configWrites":
"Allow Slack to write config in response to channel events/commands (default: true).",
"channels.discord.configWrites":
"Allow Discord to write config in response to channel events/commands (default: true).",
"channels.whatsapp.configWrites":
"Allow WhatsApp to write config in response to channel events/commands (default: true).",
"channels.signal.configWrites":
"Allow Signal to write config in response to channel events/commands (default: true).",
"channels.imessage.configWrites":
"Allow iMessage to write config in response to channel events/commands (default: true).",
"channels.msteams.configWrites":
"Allow Microsoft Teams to write config in response to channel events/commands (default: true).",
"channels.discord.commands.native": 'Override native commands for Discord (bool or "auto").',
"channels.telegram.commands.native": 'Override native commands for Telegram (bool or "auto").',
"channels.slack.commands.native": 'Override native commands for Slack (bool or "auto").',

View File

@@ -72,6 +72,8 @@ export type DiscordAccountConfig = {
capabilities?: string[];
/** Override native command registration for Discord (bool or "auto"). */
commands?: ProviderCommandsConfig;
/** Allow channel-initiated config writes (default: true). */
configWrites?: boolean;
/** If false, do not start this Discord account. Default: true. */
enabled?: boolean;
token?: string;

View File

@@ -6,6 +6,8 @@ export type IMessageAccountConfig = {
name?: string;
/** Optional provider capability tags used for agent/runtime guidance. */
capabilities?: string[];
/** Allow channel-initiated config writes (default: true). */
configWrites?: boolean;
/** If false, do not start this iMessage account. Default: true. */
enabled?: boolean;
/** imsg CLI binary path (default: imsg). */

View File

@@ -34,6 +34,8 @@ export type MSTeamsConfig = {
enabled?: boolean;
/** Optional provider capability tags used for agent/runtime guidance. */
capabilities?: string[];
/** Allow channel-initiated config writes (default: true). */
configWrites?: boolean;
/** Azure Bot App ID (from Azure Bot registration). */
appId?: string;
/** Azure Bot App Password / Client Secret. */

View File

@@ -8,6 +8,8 @@ export type SignalAccountConfig = {
name?: string;
/** Optional provider capability tags used for agent/runtime guidance. */
capabilities?: string[];
/** Allow channel-initiated config writes (default: true). */
configWrites?: boolean;
/** If false, do not start this Signal account. Default: true. */
enabled?: boolean;
/** Optional explicit E.164 account for signal-cli. */

View File

@@ -67,6 +67,8 @@ export type SlackAccountConfig = {
capabilities?: string[];
/** Override native command registration for Slack (bool or "auto"). */
commands?: ProviderCommandsConfig;
/** Allow channel-initiated config writes (default: true). */
configWrites?: boolean;
/** If false, do not start this Slack account. Default: true. */
enabled?: boolean;
botToken?: string;

View File

@@ -21,6 +21,8 @@ export type TelegramAccountConfig = {
capabilities?: string[];
/** Override native command registration for Telegram (bool or "auto"). */
commands?: ProviderCommandsConfig;
/** Allow channel-initiated config writes (default: true). */
configWrites?: boolean;
/**
* Controls how Telegram direct chats (DMs) are handled:
* - "pairing" (default): unknown senders get a pairing code; owner must approve

View File

@@ -12,6 +12,8 @@ export type WhatsAppConfig = {
accounts?: Record<string, WhatsAppAccountConfig>;
/** Optional provider capability tags used for agent/runtime guidance. */
capabilities?: string[];
/** Allow channel-initiated config writes (default: true). */
configWrites?: boolean;
/**
* Inbound message prefix (WhatsApp only).
* Default: `[{agents.list[].identity.name}]` (or `[clawdbot]`) when allowFrom is empty, else `""`.
@@ -78,6 +80,8 @@ export type WhatsAppAccountConfig = {
name?: string;
/** Optional provider capability tags used for agent/runtime guidance. */
capabilities?: string[];
/** Allow channel-initiated config writes (default: true). */
configWrites?: boolean;
/** If false, do not start this WhatsApp account provider. Default: true. */
enabled?: boolean;
/** Inbound message prefix override for this account (WhatsApp only). */

View File

@@ -36,6 +36,7 @@ export const TelegramAccountSchemaBase = z.object({
capabilities: z.array(z.string()).optional(),
enabled: z.boolean().optional(),
commands: ProviderCommandsSchema,
configWrites: z.boolean().optional(),
dmPolicy: DmPolicySchema.optional().default("pairing"),
botToken: z.string().optional(),
tokenFile: z.string().optional(),
@@ -132,6 +133,7 @@ export const DiscordAccountSchema = z.object({
capabilities: z.array(z.string()).optional(),
enabled: z.boolean().optional(),
commands: ProviderCommandsSchema,
configWrites: z.boolean().optional(),
token: z.string().optional(),
allowBots: z.boolean().optional(),
groupPolicy: GroupPolicySchema.optional().default("allowlist"),
@@ -206,6 +208,7 @@ export const SlackAccountSchema = z.object({
capabilities: z.array(z.string()).optional(),
enabled: z.boolean().optional(),
commands: ProviderCommandsSchema,
configWrites: z.boolean().optional(),
botToken: z.string().optional(),
appToken: z.string().optional(),
allowBots: z.boolean().optional(),
@@ -252,6 +255,7 @@ export const SignalAccountSchemaBase = z.object({
name: z.string().optional(),
capabilities: z.array(z.string()).optional(),
enabled: z.boolean().optional(),
configWrites: z.boolean().optional(),
account: z.string().optional(),
httpUrl: z.string().optional(),
httpHost: z.string().optional(),
@@ -303,6 +307,7 @@ export const IMessageAccountSchemaBase = z.object({
name: z.string().optional(),
capabilities: z.array(z.string()).optional(),
enabled: z.boolean().optional(),
configWrites: z.boolean().optional(),
cliPath: ExecutableTokenSchema.optional(),
dbPath: z.string().optional(),
service: z.union([z.literal("imessage"), z.literal("sms"), z.literal("auto")]).optional(),
@@ -370,6 +375,7 @@ export const MSTeamsConfigSchema = z
.object({
enabled: z.boolean().optional(),
capabilities: z.array(z.string()).optional(),
configWrites: z.boolean().optional(),
appId: z.string().optional(),
appPassword: z.string().optional(),
tenantId: z.string().optional(),

View File

@@ -11,6 +11,7 @@ export const WhatsAppAccountSchema = z
.object({
name: z.string().optional(),
capabilities: z.array(z.string()).optional(),
configWrites: z.boolean().optional(),
enabled: z.boolean().optional(),
messagePrefix: z.string().optional(),
/** Override auth directory for this WhatsApp account (Baileys multi-file auth state). */
@@ -60,6 +61,7 @@ export const WhatsAppConfigSchema = z
.object({
accounts: z.record(z.string(), WhatsAppAccountSchema.optional()).optional(),
capabilities: z.array(z.string()).optional(),
configWrites: z.boolean().optional(),
dmPolicy: DmPolicySchema.optional().default("pairing"),
messagePrefix: z.string().optional(),
selfChatMode: z.boolean().optional(),