Operations Guide
Last updated: March 2026 Audience: Claude Code agents operating the system day-to-day
System Architecture
ChurchWiseAI operates three web properties on Vercel sharing a single production Supabase database, plus a voice agent on LiveKit Cloud.
Web Properties (Vercel) Voice Agent (LiveKit Cloud)
----------------------------- -------------------------
churchwiseai.com (port 3002) LiveKit Agents v1.5 (Python)
pewsearch.com (port 3001) Multi-tenant, routes by phone
illustratetheword.com (port 3000) Deploy: lk agent deploy
Code: voice-agent-livekit/
Shared Database: Supabase (wrwkszmobuhvcfjipasi)
ONE instance for dev AND prod. No staging DB.
| Property | What It Sells | Code Location | Deploy Branch |
|---|---|---|---|
| churchwiseai.com | Voice Agent + Chatbot (all AI products) | churchwiseai-web/ | main |
| pewsearch.com | Premium Pages ($4.95/mo directory listing) | pewsearch/web/ | master |
| illustratetheword.com | ITW Premium ($9.95/mo illustration library) | sermon-illustrations/ | master |
Legacy services (do not modify):
churchwiseai-web/voice-agent/-- old Node.js/Railway voice agent (replaced by voice-agent-livekit/)churchwiseai-web/voice-agent-line/-- old Cartesia LINE SDK agent (replaced by voice-agent-livekit/)ai-sermon-assistant/-- old Nx monorepo (reference only, never build here)
Signup Flow (End to End)
Pricing Page (/pricing) -> "Get Started"
-> Onboard (/onboard): church name, email, denomination, plan
-> Stripe Checkout (hosted)
-> Webhook: checkout.session.completed
1. Upsert premium_churches (status='active')
2. Store stripe_customer_id + stripe_subscription_id
3. Normalize plan key via normalizePlanKey()
4. provisionChatbot() -> creates organization_settings
5. Send welcome email with magic link
6. If voice plan -> send voice setup alert to admin
-> Admin Dashboard (/admin/[token]) -- church is live
Key detail: checkout.session.completed is the single activation event. customer.subscription.created is intentionally NOT handled (prevents duplicate welcome emails).
Voice Provisioning
Voice plans require a phone number. New customers use Telnyx (direct SIP to LiveKit, cheaper than Twilio). Twilio is legacy only for existing numbers.
- Webhook detects a voice plan purchase
- Alert email sent to support with church name, city, plan tier
- Admin provisions a Telnyx number with local area code + creates LiveKit SIP trunk/dispatch rule
- Database update:
church_voice_agentsrow with phone number andstatus = 'active' - Phone ready email sent to the church
Current state: Semi-automated. See knowledge/runbooks/voice-provisioning.md for full runbook.
Auth & Security
- HMAC sessions: Admin tokens hashed with HMAC-SHA256 using
APP_SECRET. Database stores hashes only. - Magic links: Welcome email contains
/auth/magic?t=TOKEN. Sets HttpOnly cookie (cw_session) on first visit. - RBAC (9 roles): admin, office_admin, prayer_team, care_team, treasurer, volunteer_coordinator, worship_leader, spiritual_leader, care_leader. Enforced at both API and UI levels.
- Sensitive data gating: Callback reasons visible only to PASTORAL_ROLES. Confidential prayer text redacted for non-pastoral. Financial data restricted to FINANCIAL_ROLES (admin, treasurer).
Key Database Tables
| Table | Purpose |
|---|---|
churches (218K+ visible) | Church directory listings |
premium_churches (13 total: 3 Stripe, 10 demo/test) | Paid subscriptions + admin access |
church_voice_agents | Voice agent config per church |
organization_settings | Chatbot config per church |
voice_call_logs | Call transcripts + recordings |
voice_prayer_requests | Prayer requests (voice + chat) |
voice_visitor_contacts | Visitor contact captures |
voice_callback_requests | Callback/appointment requests |
church_team_members | RBAC team roles |
unified_rag_content (327K) | All content (illustrations, sermons) -- NEVER bulk delete |
product_knowledge | Runtime knowledge for chatbot + voice agent |
Deployment
| Service | How to Deploy | Timing |
|---|---|---|
| churchwiseai.com | Push to main -> Vercel auto-deploys | 2-5 min |
| pewsearch.com | Push to master -> Vercel auto-deploys | 2-5 min |
| illustratetheword.com | Push to master -> Vercel auto-deploys | 2-5 min |
| Voice agent | C:\dev\lk.exe agent deploy --project cwa-voice --silent | ~1 min |
Rollback (Vercel): Dashboard -> Deployments -> find last good deploy -> Promote to Production. Takes seconds.
Rollback (Voice): Re-deploy the previous commit from voice-agent-livekit/.
Email System
All transactional email via Resend (from hello@churchwiseai.com):
| Trigger | |
|---|---|
| Welcome | checkout.session.completed |
| Payment Failed | invoice.payment_failed |
| Voice Setup Alert | Voice plan purchased |
| Phone Ready | Twilio number assigned |
| Upgrade Notification | Plan change |
Lifecycle Emails — 11 sequences, 25+ templates, daily cron at 8am ET (13:00 UTC) via Vercel. Handles onboarding drips (Starter/Pro/Suite), win-back, cross-property promotions (PS→CWA, ITW→SermonWise, CWA→ShareWise), newsletter welcome, and 7-day AI ministry course. Engine: churchwiseai-web/src/lib/lifecycle-emails.ts. Sent via Resend. Deduplication via lifecycle_emails_sent table (unique constraint on church_id + email_key is the state machine — cron is fully idempotent). MailerLite is retained for newsletter subscriber management and Care broadcasts only.
Stripe Integration
Webhook endpoint: /api/stripe/webhook. Three events handled:
| Event | Action |
|---|---|
checkout.session.completed | Activate subscription, provision chatbot, send welcome email |
customer.subscription.updated | Update plan tier, adjust feature access |
customer.subscription.deleted | Set status='cancelled', remove premium flag |
Plan normalization: normalizePlanKey() in tier-config.ts maps Stripe price IDs to canonical plan keys.
Stripe account: churchwiseai@gmail.com. Test mode is default (sk_test_). Use --live flag for live operations. Restricted live key cannot create products via CLI.
Chatbot System
- Auto-provisioned during checkout via
provisionChatbot()-- creates organization_settings with default agent config, maps denomination to theological lens, loads denomination content packs. - 39 agentic tools across 3 tiers: Starter (12 tools, 2 agents), Pro (35 tools, 4 agents), Suite (39 tools, 4 agents).
- Moderation escalation: 1st violation = warning, 2nd = 2-min cooldown, 3rd = 1-hr block, repeated = permanent block.
- 4 agents in chat: Coordinator, Care, Stewardship, Discipleship.
Voice Agent System
- 2 agents in voice: Coordinator Agent (Gemini 2.5 Flash, handles info + logistics + giving) + Care Agent (Claude Haiku 4.5, handles prayer/grief/crisis with different voice and pacing).
- Technology: LiveKit Agents v1.5 (Python), deployed on LiveKit Cloud.
- Multi-tenant: ONE deployed agent serves ALL churches.
session.py:resolve_route()routes by phone number (PHONE_REGISTRY dict + DB fallback). - STT/TTS: Deepgram Nova-3 (speech-to-text), Cartesia Sonic (text-to-speech).
- LLMs: Gemini 2.5 Flash (primary), Claude Haiku 4.5 (fallback; Care Agent uses Haiku as primary for better empathy).
- Threat detection: Explicit threats -> immediate hangup + emergency notifications. Abuse -> graduated response (warning -> hangup after 3 offenses).
Demo Church
| Property | Value |
|---|---|
| Church ID | 00000000-0000-4000-a000-000000000001 |
| Admin token | demo-admin-token-2026 |
| Dashboard | /admin/demo-admin-token-2026 |
| Chatbot | /care/churchwiseai-demo |
| Plan | bundle (Voice + Chat) |
Setup script: scripts/setup-demo-church.sql (idempotent).
Operational Guardrails
- ONE production database. Every query hits prod. Be paranoid about writes.
- 327K irreplaceable records in
unified_rag_content. NEVER bulk delete. - ai-sermon-assistant is LEGACY. Read for reference, never build there.
- Deploy branches differ.
mainfor churchwiseai-web,masterfor pewsearch and ITW. - Multiple agents work concurrently. Always create your own branch. Never reuse another agent's. Never force push.
- Voice agent deploys via
lk agent deploy, NOT git push. - Use
claude -pfor batch content generation, not API calls.
Blocking Issues (April 2026)
- FA-004 (P1): Add trial_will_end webhook event -- trial reminder emails won't send
- ShareWiseAI: Code complete but OAuth + Stripe products not configured
- 10DLC SMS: Campaign pending vetting, outbound SMS blocked