From 12871128e1a03af932d73b30d10a89ec1115c2d3 Mon Sep 17 00:00:00 2001 From: Cameron Date: Tue, 3 Feb 2026 12:30:27 -0800 Subject: [PATCH] feat: default to allowlist for dedicated numbers in onboarding (#100) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When user selects "dedicated bot number" mode (selfChatMode=false), skip the dmPolicy question and default to allowlist. Prompt for allowed phone numbers immediately. This is simpler and safer than pairing mode, which sends codes to whoever messages the bot. Users who want pairing or open mode can edit lettabot.yaml manually. Also updates docs to reflect the new defaults. Written by Cameron ◯ Letta Code "Simplicity is the ultimate sophistication." - Leonardo da Vinci --- docs/configuration.md | 8 +++-- docs/signal-setup.md | 7 ++--- docs/whatsapp-setup.md | 9 ++---- src/onboard.ts | 67 +++++++++++++----------------------------- 4 files changed, 33 insertions(+), 58 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 781ba11..c422312 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -117,8 +117,12 @@ All channels share these common options: ### DM Policies -- **`pairing`** (recommended): New users get a code, approve with `lettabot pairing approve` -- **`allowlist`**: Only specified user IDs can message +**Note:** For WhatsApp/Signal with `selfChat: true` (personal number), dmPolicy is ignored - only you can message via "Message Yourself" / "Note to Self". + +For dedicated bot numbers (`selfChat: false`), onboarding defaults to **allowlist**: + +- **`allowlist`** (default for dedicated numbers): Only specified phone numbers can message +- **`pairing`**: New users get a code, approve with `lettabot pairing approve` - **`open`**: Anyone can message (not recommended) ### Channel-Specific Options diff --git a/docs/signal-setup.md b/docs/signal-setup.md index 48290f4..a8b0037 100644 --- a/docs/signal-setup.md +++ b/docs/signal-setup.md @@ -46,13 +46,12 @@ SIGNAL_PHONE_NUMBER=+17075204676 # SIGNAL_HTTP_HOST=127.0.0.1 # SIGNAL_HTTP_PORT=8090 -# Optional: DM access policy (default: pairing) -# SIGNAL_DM_POLICY=pairing - # Optional: Self-chat mode for "Note to Self" (default: true) # SIGNAL_SELF_CHAT_MODE=true ``` +**Note:** For personal numbers (`selfChatMode: true`), `dmPolicy` is ignored - only you can message via "Note to Self". For dedicated bot numbers, onboarding defaults to `allowlist`. + ## How It Works LettaBot automatically: @@ -66,7 +65,7 @@ The daemon runs on port 8090 by default to avoid conflicts with other services. - **Direct Messages** - Receive and respond to DMs - **Note to Self** - Use Signal's "Note to Self" feature to message yourself (selfChatMode) -- **Pairing System** - Unknown senders get a pairing code (same as Telegram) +- **Allowlist** - For dedicated numbers, only pre-approved phone numbers can message ## Troubleshooting diff --git a/docs/whatsapp-setup.md b/docs/whatsapp-setup.md index 5aaf61e..bdf3501 100644 --- a/docs/whatsapp-setup.md +++ b/docs/whatsapp-setup.md @@ -24,8 +24,7 @@ Add to your `lettabot.yaml` or set environment variables: channels: whatsapp: enabled: true - selfChatMode: true # IMPORTANT: See below - dmPolicy: pairing # or 'allowlist' or 'open' + selfChat: true # IMPORTANT: See below ``` Or via environment variables: @@ -34,12 +33,10 @@ Or via environment variables: # WhatsApp Configuration WHATSAPP_ENABLED=true WHATSAPP_SELF_CHAT_MODE=true # CRITICAL - see below -WHATSAPP_DM_POLICY=pairing - -# Optional: Restrict to specific phone numbers (if dmPolicy=allowlist) -# WHATSAPP_ALLOWED_USERS=+15551234567,+15559876543 ``` +**Note:** For personal numbers (`selfChat: true`), `dmPolicy` is ignored - only you can message via "Message Yourself". For dedicated bot numbers, onboarding defaults to `allowlist`. + ### Self-Chat Mode (Critical Safety Setting) **`selfChatMode: true`** (default, recommended for personal numbers): diff --git a/src/onboard.ts b/src/onboard.ts index c682971..c42e937 100644 --- a/src/onboard.ts +++ b/src/onboard.ts @@ -868,32 +868,19 @@ async function stepChannels(config: OnboardConfig, env: Record): } } - // Access control only matters for dedicated numbers + // Dedicated numbers use allowlist by default if (config.whatsapp.selfChat === false) { - const dmPolicy = await p.select({ - message: 'WhatsApp: Who can message the bot?', - options: [ - { value: 'pairing', label: 'Pairing (recommended)', hint: 'Requires CLI approval' }, - { value: 'allowlist', label: 'Allowlist only', hint: 'Specific phone numbers' }, - { value: 'open', label: 'Open', hint: '⚠️ Anyone (not recommended - full account access!)' }, - ], - initialValue: config.whatsapp.dmPolicy || 'pairing', + config.whatsapp.dmPolicy = 'allowlist'; + const users = await p.text({ + message: 'Allowed phone numbers (comma-separated, with +)', + placeholder: '+15551234567,+15559876543', + initialValue: config.whatsapp.allowedUsers?.join(',') || '', }); - if (!p.isCancel(dmPolicy)) { - config.whatsapp.dmPolicy = dmPolicy as 'pairing' | 'allowlist' | 'open'; - - if (dmPolicy === 'pairing') { - p.log.info('Users will get a code. Approve with: lettabot pairing approve whatsapp CODE'); - } else if (dmPolicy === 'allowlist') { - const users = await p.text({ - message: 'Allowed phone numbers (comma-separated, with +)', - placeholder: '+15551234567,+15559876543', - initialValue: config.whatsapp.allowedUsers?.join(',') || '', - }); - if (!p.isCancel(users) && users) { - config.whatsapp.allowedUsers = users.split(',').map(s => s.trim()).filter(Boolean); - } + if (!p.isCancel(users) && users) { + config.whatsapp.allowedUsers = users.split(',').map(s => s.trim()).filter(Boolean); } + if (!config.whatsapp.allowedUsers?.length) { + p.log.warn('No allowed numbers set. Bot will reject all messages until you add numbers to lettabot.yaml'); } } } @@ -931,31 +918,19 @@ async function stepChannels(config: OnboardConfig, env: Record): } // Access control only matters for dedicated numbers + // Dedicated numbers use allowlist by default if (config.signal.selfChat === false) { - const dmPolicy = await p.select({ - message: 'Signal: Who can message the bot?', - options: [ - { value: 'pairing', label: 'Pairing (recommended)', hint: 'Requires CLI approval' }, - { value: 'allowlist', label: 'Allowlist only', hint: 'Specific phone numbers' }, - { value: 'open', label: 'Open', hint: 'Anyone (not recommended)' }, - ], - initialValue: config.signal.dmPolicy || 'pairing', + config.signal.dmPolicy = 'allowlist'; + const users = await p.text({ + message: 'Allowed phone numbers (comma-separated, with +)', + placeholder: '+15551234567,+15559876543', + initialValue: config.signal.allowedUsers?.join(',') || '', }); - if (!p.isCancel(dmPolicy)) { - config.signal.dmPolicy = dmPolicy as 'pairing' | 'allowlist' | 'open'; - - if (dmPolicy === 'pairing') { - p.log.info('Users will get a code. Approve with: lettabot pairing approve signal CODE'); - } else if (dmPolicy === 'allowlist') { - const users = await p.text({ - message: 'Allowed phone numbers (comma-separated, with +)', - placeholder: '+15551234567,+15559876543', - initialValue: config.signal.allowedUsers?.join(',') || '', - }); - if (!p.isCancel(users) && users) { - config.signal.allowedUsers = users.split(',').map(s => s.trim()).filter(Boolean); - } - } + if (!p.isCancel(users) && users) { + config.signal.allowedUsers = users.split(',').map(s => s.trim()).filter(Boolean); + } + if (!config.signal.allowedUsers?.length) { + p.log.warn('No allowed numbers set. Bot will reject all messages until you add numbers to lettabot.yaml'); } } }