Configuration & secrets.
Every environment variable, secret, binding, OAuth redirect, webhook URL, and cron trigger Concierge expects. All sensitive values are stored as Cloudflare Workers secrets via wrangler secret put; non‑sensitive values live in the [vars] block of wrangler.toml.
Use the Wrangler CLI: wrangler secret put SECRET_NAME. You’ll be prompted to enter the value securely. Secrets are encrypted at rest by Cloudflare and exposed to your Worker as environment variables.
Environment variables
Plain‑text vars in the [vars] block of wrangler.toml. Safe to commit.
| Variable | Description |
|---|---|
ENVIRONMENT | production or development. Dev mode bypasses some auth checks. |
CF_ACCESS_TEAM | Cloudflare Access team name (the subdomain in myteam.cloudflareaccess.com). |
CF_ACCESS_AUD | Cloudflare Access Application Audience (AUD) tag for /manage/*. |
WHATSAPP_WABA_ID | Your WhatsApp Business Account ID. |
WHATSAPP_SIGNUP_CONFIG_ID | Meta Embedded Signup configuration ID. |
EMAIL_DOMAIN | Single platform email domain. Set to a domain you control; configure MX records manually on its apex and wire it into Cloudflare Email Routing. |
AI_MODEL | Optional override for the Workers AI model used for replies. Default @cf/meta/llama-4-scout-17b-16e-instruct. |
AI_FAST_MODEL | Optional override for the fast classifier model (prompt‑injection scan + persona safety check). Default @cf/meta/llama-3.1-8b-instruct-fast. |
Secrets
Sensitive values, set with wrangler secret put. Grouped by integration.
Core
| Secret | Description |
|---|---|
ENCRYPTION_KEY |
32‑byte hex key for AES‑256‑GCM encryption of stored tokens. Generate with openssl rand -hex 32. |
Google OAuth
| Secret | Description |
|---|---|
GOOGLE_OAUTH_CLIENT_ID | Google OAuth client ID (for sign-in). |
GOOGLE_OAUTH_CLIENT_SECRET | Google OAuth client secret. |
Meta: Facebook / Instagram / WhatsApp
| Secret | Description |
|---|---|
META_APP_ID | Meta app ID: shared for Facebook Login, Instagram, WhatsApp signup. |
META_APP_SECRET | Meta app secret: used for webhook signature verification and token exchange. |
WHATSAPP_ACCESS_TOKEN | System user token for your shared WABA. |
WHATSAPP_VERIFY_TOKEN | Webhook verification token. Generate with openssl rand -hex 16. |
INSTAGRAM_VERIFY_TOKEN | Instagram webhook verification token. Generate with openssl rand -hex 16. |
Discord
| Secret | Description |
|---|---|
DISCORD_PUBLIC_KEY | Discord application public key (Ed25519 signature verification for interactions). |
DISCORD_APPLICATION_ID | Discord application ID (for registering slash commands). |
DISCORD_BOT_TOKEN | Discord bot token (for sending messages and managing interactions). |
Razorpay optional
| Secret | Description |
|---|---|
RAZORPAY_KEY_ID | Razorpay API key ID. |
RAZORPAY_KEY_SECRET | Razorpay API key secret. |
RAZORPAY_WEBHOOK_SECRET | Razorpay webhook secret (for verifying payment notifications at POST /webhook/razorpay). |
Bindings
Cloudflare resource bindings declared in wrangler.toml. The IDs come from the deployment guide.
| Binding | Type | Description |
|---|---|---|
DB | D1 | SQLite database for message logs, payments, audit, credit packs. |
KV | KV | Config store for tenants, accounts, sessions, routing rules, billing state, persona. |
AI | AI | Cloudflare Workers AI for reply generation, prompt‑injection scanning, persona safety classification, and BGE embeddings. |
EMAIL | send_email | Outbound email for forwarding and reverse‑alias replies. |
REPLY_BUFFER | DO | Per‑conversation reply buffer that batches multi‑message bursts within wait_seconds. |
SAFETY_QUEUE | Queue | Persona safety classifier jobs. Producer + consumer bound on the same Worker. |
Cloudflare Queues
Two queues must exist before deploy:
concierge-safety: producer + consumer for the persona safety classifier. The Worker enqueues aSafetyJobon each persona save and consumes the same queue via#[event(queue)].concierge-safety-dlq: dead‑letter queue for safety jobs after 3 retries. Inspect failures here when persona checks stop completing.
wrangler queues create concierge-safety
wrangler queues create concierge-safety-dlq
Local wrangler dev works without queues configured: safety_queue::enqueue logs and falls through, leaving personas in Pending until you deploy against a properly bound environment.
Locale & supported languages
Every tenant has a BCP‑47 locale tag (Tenant.locale) plus an independent currency override. Currently shipped: en-IN (default; Indian‑style number grouping, INR currency) and en-US (Western grouping, USD). Locale is set at signup from the request’s Accept-Language header, falling back to cf-ipcountry, then to en-IN. Admins can change both locale and currency independently from /admin/settings.
Adding a new locale is a drop‑in change: place a translated messages.ftl at assets/locales/{tag}/, register the tag in src/i18n.rs::Translator::new and src/locale.rs::Locale::from_request, then rebuild. CLDR data for number / currency formatting ships automatically via icu4x’s compiled_data feature. AI‑generated reply content stays English regardless of the UI locale.
OAuth redirect URIs
Register these in the respective developer consoles:
- Google:
https://your-domain/auth/callback - Facebook:
https://your-domain/auth/facebook/callbackandhttps://your-domain/instagram/callback
Webhook URLs
Configure these in the respective platforms:
| Platform | URL | Method |
|---|---|---|
https://your-domain/webhook/whatsapp | GET / POST | |
https://your-domain/webhook/instagram | GET / POST | |
| Discord | https://your-domain/discord/interactions | POST |
| Razorpay | https://your-domain/webhook/razorpay | POST |
Cron triggers
A daily cron runs at 0 6 * * * (06:00 UTC) for Instagram token refresh. Configured in the [triggers] section of wrangler.toml.
# Identity
name = "concierge"
main = "worker-shim.mjs"
compatibility_date = "2024-01-01"
# Plain-text variables
[vars]
ENVIRONMENT = "production"
CF_ACCESS_TEAM = "calculon"
CF_ACCESS_AUD = "abcd1234…"
WHATSAPP_WABA_ID = "123456789012345"
EMAIL_DOMAIN = "cncg.email"
# Bindings
[[d1_databases]]
binding = "DB"
database_name = "concierge"
database_id = "…"
[[kv_namespaces]]
binding = "KV"
id = "…"
[ai] binding = "AI"
[[send_email]] name = "EMAIL"
[[durable_objects.bindings]]
name = "REPLY_BUFFER"
class_name = "ReplyBufferDO"
# Persona safety classifier
[[queues.producers]]
queue = "concierge-safety"
binding = "SAFETY_QUEUE"
[[queues.consumers]]
queue = "concierge-safety"
max_batch_size = 10
max_batch_timeout = 5
max_retries = 3
dead_letter_queue = "concierge-safety-dlq"
# Daily Instagram token refresh, 06:00 UTC
[triggers]
crons = ["0 6 * * *"]
Rotating ENCRYPTION_KEY invalidates every encrypted Instagram page token in KV: customers will need to reconnect. Webhook verify tokens (WHATSAPP_VERIFY_TOKEN, INSTAGRAM_VERIFY_TOKEN) can be rotated independently; just update them in the Meta Developer Console at the same time.