Skip to main content

Database Schema — ChurchWiseAI Web

Knowledge > Architecture > Database Schema > ChurchWiseAI Tables


Database Schema — ChurchWiseAI Web

All tables owned or primarily used by churchwiseai-web/. Shared Supabase instance: wrwkszmobuhvcfjipasi. Row counts are pg_class estimates (actual may vary). Tables with ~0 or -1 est are empty or unanalyzed.

Core ChurchWiseAI Table Relationships


Church Subscriptions & Auth

premium_churches (~6 rows)

The central subscription record for every church using ChurchWiseAI products. One row per church. All auth, plan, and Pro Website content lives here.

ColumnTypeNotes
iduuidPK
church_iduuidFK → churches.id (PewSearch directory record)
stripe_customer_idtextStripe customer
stripe_subscription_idtextActive Stripe subscription
plantextstarter, pro, suite; default starter
statustextpreview, active, trialing, canceled; default preview
preview_created_attimestamptzWhen preview/trial started
preview_expires_attimestamptz14-day preview window
activated_attimestamptzWhen paid subscription started
admin_tokentextMagic-link token for /admin/[token]; auto-generated hex
admin_emailtextPrimary contact email
admin_nametextPrimary contact name
admin_phonetextSMS notification number
admin_roletextRole label (e.g. "Pastor")
channeltextchat, voice, both; default chat
custom_nametextChurch display name override
custom_descriptiontextChurch tagline
hero_photo_urltextPro Website hero image
logo_urltextChurch logo
hero_slideshow_keysjsonbArray of Storage keys for slideshow images
hero_video_keytextStorage key for hero video
transition_video_keytextStorage key for transition video
featured_video_urltextEmbedded YouTube/Vimeo URL
what_to_expectjsonbFirst-visit section content
custom_staffjsonbStaff members array
custom_ministriesjsonbMinistries array
custom_hoursjsonbService times
custom_social_mediajsonbSocial media links
eventsjsonbUpcoming events array
sermonsjsonbRecent sermons array
beliefsjsonbBeliefs/doctrine section
giving_urltextOnline giving link
contact_cc_emailtextCC email for contact form submissions
website_templatetextPro Website theme selection
vanity_slugtextCustom URL slug
chatbot_agent_iduuidFK → chatbot_agents.id
chatbot_enabledbooleanWhether chatbot widget is active
care_enabledbooleanWhether congregation care module is enabled
custom_domaintextWhite-label domain (Suite plan)
cap_infojsonbCapacity/plan override info
email_opt_outbooleanMarketing email opt-out
last_email_sent_attimestamptzDrip campaign tracking
email_sequence_stepintegerCurrent drip step
sms_sent_attimestamptzLast SMS notification sent
ministries_updated_attimestamptzLast ministries edit
founder_notestextInternal notes (not customer-visible)
email_send_domaintextCustom sending domain registered with Resend (e.g., gracecommunity.church). NULL until set. Added FA-107 v2 2026-05-12.
email_send_from_addresstextFull resolved From address (e.g., pastor@gracecommunity.church). Populated after verification. NULL until verified.
email_send_resend_idtextResend domain object ID — required for verify + delete API calls. NULL until domain registered.
email_send_statustextVerification state machine: unverified (default) | pending | verified | failed. CHECK constraint enforces enum.
email_send_dns_recordsjsonbCached DNS records from Resend (SPF + DKIM CNAMEs) for Settings panel rendering. NULL until domain registered.
created_attimestamptz
updated_attimestamptz

Safety: Only 4–6 rows exist (all founder test accounts). NEVER bulk delete. All mutations must be intentional.

Email domain columns (email_send_*) added in migrations/2026-05-12-per-church-email-domain.sql (FA-107 v2). All five are additive with safe defaults — existing churches start in unverified state automatically. Full state-machine and code-path docs: knowledge/architecture/inbox-email-sender-domain.md.


church_team_members (~0 rows)

Additional admin users for a church's account (multi-user access).

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
premium_iduuidFK → premium_churches.id
access_tokentextAuto-generated hex token
nametext
emailtext
roletexte.g. admin, editor
is_activebooleanDefault true
last_accessed_attimestamptz
created_attimestamptz

church_admin_identities (~1 row)

Supabase Auth identity records linked to a church admin account.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
emailtext
nametext
phonetext
auth_user_iduuidFK → Supabase Auth users.id
is_primary_ownerboolean
is_backup_ownerboolean
is_activebooleanDefault true
created_attimestamptz
updated_attimestamptz

church_admin_sessions (~14 rows)

Hashed session tokens for magic-link admin authentication.

ColumnTypeNotes
iduuidPK
identity_iduuidFK → church_admin_identities.id
church_iduuidFK → premium_churches.church_id
token_hashtextBcrypt/SHA hash of session token
created_attimestamptz
last_used_attimestamptz
expires_attimestamptzDefault now() + 30 days
revoked_attimestamptzNull if active
created_byuuid
iptext
user_agenttext

church_identity_roles (~1 row)

Role assignments for church admin identities.

ColumnTypeNotes
iduuidPK
identity_iduuidFK → church_admin_identities.id
church_iduuidFK → premium_churches.church_id
roletextRole name
created_attimestamptz

church_access_audit (~4 rows)

Immutable audit log of admin access events (logins, token use, etc.).

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
identity_iduuidFK → church_admin_identities.id (nullable)
event_typetexte.g. login, token_used, logout
detailsjsonbEvent-specific payload
iptext
user_agenttext
created_attimestamptz

Safety: Audit log — never delete rows.


Voice Agent

church_voice_agents (~2 rows)

Per-church configuration for the voice agent. One row per church with a voice subscription.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
premium_iduuidFK → premium_churches.id
twilio_phone_numbertextInbound phone number
twilio_phone_sidtextTwilio Phone Number SID
voice_idtextCartesia voice ID; default dIeHOwebB4fO6l6gNfUK
welcome_greetingtextCustom greeting script
custom_faqsjsonbChurch-specific FAQs array
pastor_nametext
notification_emailtextWhere to send leads/alerts
notification_phonetextSMS notification number
prayer_requests_enabledbooleanDefault true
visitor_intake_enabledbooleanDefault true
callback_scheduling_enabledbooleanDefault true
giving_enabledbooleanDefault false
giving_urltext
etransfer_emailtexte-Transfer giving email
giving_messagetext
statustexttrial, active, suspended; default trial
trial_ends_attimestamptzDefault now() + 14 days
calls_this_monthintegerCurrent month call counter
calls_limitintegerDefault 50
recording_enabledbooleanDefault false
pastor_availabilityjsonbStructured availability slots
pastor_availability_texttextHuman-readable availability
church_timezonetextDefault America/New_York
cal_event_type_idtextCal.com event type for booking
cal_api_keytextCal.com API key
pco_app_idtextPlanning Center app ID
pco_secrettextPlanning Center secret
pco_enabledbooleanDefault false
sermon_topictextCurrent sermon topic (Pastor Pulse)
sermon_seriestextCurrent sermon series
theme_versetextWeekly theme verse
weekly_announcementtextAnnouncement for this week
human_request_messagetextMessage when human requested
pastor_pulse_updated_attimestamptzLast Pastor Pulse update
crisis_messagetextCustom crisis/grief response
crisis_blessingtextCrisis closing blessing
created_attimestamptz
updated_attimestamptz

voice_agents (~18 rows)

Cartesia voice option catalog — available voice IDs with labels and routing weights.

ColumnTypeNotes
iduuidPK
voice_idtextCartesia voice ID
labeltextDisplay name
regiontextDefault default
weightintegerRouting weight for load balancing
enabledbooleanWhether available for selection
created_attimestamptz
updated_attimestamptz

voice_call_logs (~118 rows)

Full log of every inbound call handled by the voice agent.

ColumnTypeNotes
iduuidPK
call_sidtextTwilio Call SID (unique)
from_numbertextCaller phone number
to_numbertextChurch Twilio number
church_iduuidFK → premium_churches.church_id
voice_idtextCartesia voice used
duration_secondsinteger
transcriptjsonbArray of turn objects {role, content}
summarytextAI-generated call summary
statustextin_progress, completed, failed; default in_progress
recording_sidtextTwilio Recording SID
recording_urltext
caller_sentimentnumericSentiment score
call_topicstext[]Topics detected in call
categorytextCall category
urgencytextlow, medium, high; default low
follow_up_neededbooleanDefault false
suggested_assigneetextWho should follow up
created_attimestamptz

voice_prayer_requests (~34 rows)

Prayer requests captured during voice calls or chatbot sessions. Despite the voice_ prefix, also used by chatbot.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
caller_nametext
caller_phonetext
prayer_texttextThe prayer request content
is_confidentialbooleanDefault false
statustextnew, acknowledged, prayed; default new
created_attimestamptz

voice_callback_requests (~49 rows)

Callback requests from callers wanting a pastor to call them back. Also used by chatbot.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
caller_nametext
caller_phonetext
reasontextReason for callback
preferred_timetext
urgencytextnormal, urgent; default normal
statustextpending, scheduled, completed; default pending
agreed_daytextAgreed callback day
agreed_time_windowtextAgreed time window
created_attimestamptz

voice_visitor_contacts (~0 rows)

Visitor intake records — people who identified themselves as visiting or new to the church. Also used by chatbot.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
caller_nametext
caller_phonetext
caller_emailtext
reasontextWhy they're contacting
follow_up_requestedbooleanDefault false
statustextnew, contacted; default new
created_attimestamptz

voice_event_registrations (~0 rows)

Event RSVPs captured by the voice agent during a call.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
event_titletext
event_datetext
caller_nametext
caller_phonetext
caller_emailtext
party_sizeintegerDefault 1
notestext
statustextregistered; default registered
created_attimestamptz

voice_demo_requests (~0 rows)

Sales demo requests captured by the ChurchWiseAI sales voice agent.

ColumnTypeNotes
iduuidPK
caller_nametext
caller_phonetext
church_nametext
interesttextProduct interest
church_sizetext
caller_roletexte.g. "Pastor", "Administrator"
audience_typetext
preferred_daytext
preferred_time_windowtext
notestext
statustextnew, contacted; default new
sms_sentbooleanDefault false
created_attimestamptz

voice_support_requests (~0 rows)

Support tickets captured by the voice agent.

ColumnTypeNotes
iduuidPK
caller_nametext
caller_phonetext
church_nametext
issuetextIssue description
statustextnew, resolved; default new
created_attimestamptz

Chatbot

chatbot_agents (~1 row)

Chatbot agent configuration — personality, capabilities, widget appearance. One per organization.

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
nametextAgent display name
slugtextUnique identifier
descriptiontext
avatar_urltext
personalityjsonbTone, formality, emoji usage, response length
system_prompttextCustom system prompt override
theological_lens_idintegerTheological stance
lens_weightsjsonbPer-lens weighting
capabilitiesjsonbAllowed/blocked topics, scripture search, escalation
widget_configjsonbPosition, color, branding, welcome message
statustextdraft, active; default draft
is_publicbooleanDefault false
is_templatebooleanDefault false
use_shared_ragbooleanWhether to use unified_rag_content
cloned_from_iduuidSource agent if cloned
price_typetext
price_centsintegerDefault 0
created_byuuid
created_attimestamptz
updated_attimestamptz

chatbot_conversations (~658 rows)

Session-level conversation records for the chatbot widget.

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
user_iduuidSupabase Auth user (nullable for anonymous)
visitor_nametext
visitor_emailtext
session_idtextBrowser session identifier
titletextDefault New Conversation
summarytextAI-generated summary
started_attimestamptz
ended_attimestamptz
last_message_attimestamptz
message_countintegerDefault 0
visitor_message_countinteger
bot_message_countinteger
satisfaction_ratinginteger1–5
categorytextConversation category
primary_topictext
sentimenttext
avg_response_time_msinteger
agent_iduuidFK → chatbot_agents.id
agent_typetext
persona_typetext
user_agenttext
referrertext
is_activeboolean
is_archivedboolean
metadatajsonb
created_attimestamptz
updated_attimestamptz

chatbot_messages (~15 rows)

Individual messages within a chatbot conversation.

ColumnTypeNotes
iduuidPK
conversation_iduuidFK → chatbot_conversations.id
organization_iduuidFK → organizations.id
roletextuser, assistant, system
contenttextMessage text
intenttextDetected user intent
faq_categorytextMatched FAQ category
matched_faq_iduuidFK → canned_responses.id
rag_content_idsuuid[]RAG chunks used in response
confidence_scorenumericRAG confidence
tokens_usedintegerLLM tokens consumed
response_time_msinteger
was_helpfulbooleanFeedback flag
was_savedbooleanDefault false
metadatajsonb
created_attimestamptz

chatbot_api_keys (~0 rows)

API keys for programmatic chatbot access.

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
nametextKey label
key_prefixtextFirst 8 chars (for display)
key_hashtextHashed full key
permissionstext[]Default {read}
is_activebooleanDefault true
last_used_attimestamptz
created_attimestamptz

organization_settings (~18 rows)

Per-organization chatbot and account configuration. One row per organization.

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id (unique)
brandingjsonbLogo, colors, custom CSS
security_settingsjsonbIP whitelist, 2FA, session timeout
notification_preferencesjsonbEmail/webhook notification config
feature_flagsjsonbPer-org feature toggles
integration_settingsjsonbThird-party integration config
compliance_settingsjsonbGDPR, HIPAA, data retention
account_settingsjsonbBilling email, tax ID, invoicing
chatbot_configjsonbBehavior (tone, language), appearance, availability, knowledge base, welcome message
widget_primary_colortextDefault #1B365D
widget_positiontextDefault bottom-right
agent_configjsonbAgent routing config
agent_tool_configjsonbTool enablement per agent
business_agent_configjsonbBusiness/general agent config
business_tool_configjsonbBusiness agent tool config
doctrinal_overridesjsonbChurch-specific theological overrides
created_attimestamptz
updated_attimestamptz

canned_responses (~26 rows)

Per-church FAQ responses for the chatbot. Scoped to one organization.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
organization_iduuidFK → organizations.id
questiontext
answertext
categorytext
priorityintegerDefault 0
exact_responsebooleanIf true, serve verbatim
sourcetextmanual, ai_suggested; default manual
source_conversation_idtext
question_embeddingvectorSemantic search embedding
match_countintegerTimes matched
last_matched_attimestamptz
is_activebooleanDefault true
denomination_packtext
created_attimestamptz
updated_attimestamptz

canned_response_templates (~21 rows)

System-level FAQ templates that can be adopted by churches. Managed by founder/AI pipeline.

ColumnTypeNotes
iduuidPK
questiontext
answertext
denomination_packtextDenomination filter
categorytext
agent_typetextWhich agent uses this
agent_confidence_scorenumericQuality score
agent_quality_notestext
agent_denomination_matchtext
exact_responsebooleanDefault false
question_embeddingvectorSemantic search embedding
source_conversation_idtext
source_church_iduuidOriginating church
statustextagent_suggested, approved; default agent_suggested
founder_notestext
adoption_countintegerHow many churches adopted this
total_match_countintegerTotal times matched across churches
ai_improve_countintegerTimes AI improved this
approved_attimestamptz
created_attimestamptz
updated_attimestamptz

moderation_violations (~2 rows)

Source of truth for all safety and crisis events. Both the chatbot (logViolation() in chatbot-tools.ts) and the voice agent write here on any safety trigger. The admin Safety tab (ModerationDashboard.tsx) reads from here. The pendingSafetyFlags badge count in the dashboard Overview also counts from this table — do NOT count from voice_callback_requests SAFETY FLAG patterns (that was the old, incorrect approach).

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
church_iduuidFK → premium_churches.church_id
session_idtext
user_identifiertextIP or session fingerprint
violation_typetextcrisis, abuse_mild, abuse_severe, spam, predatory
severity_scorenumeric
detected_categoriesjsonbOpenAI moderation categories
original_messagetextThe offending message
action_takentextWhat the system did
country_codetext
created_attimestamptz

user_restrictions (~0 rows)

Active user bans or restrictions from the chatbot.

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
church_iduuidFK → premium_churches.church_id
user_identifiertextIP or session fingerprint
restriction_typetextban, rate_limit, etc.
reasontext
violation_iduuidFK → moderation_violations.id
expires_attimestamptzNull = permanent
created_byuuid
created_attimestamptz

Congregation Care

congregation_care_members (~6 rows)

Congregation members who have opted into the care/outreach communication system.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
nametext
phonetext
emailtext
topicstext[]Care topics of interest; default {}
sms_opted_inbooleanDefault false
email_opted_inbooleanDefault false
sms_opted_outbooleanDefault false
delivery_preferencetextsms, email, any; default any
created_attimestamptz

congregation_care_messages (~0 rows)

Outgoing care messages sent to congregation members.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
sent_bytextWho triggered the send
topictextMessage topic
subjecttextEmail subject
bodytextMessage content
sms_countintegerNumber sent via SMS
email_countintegerNumber sent via email
created_attimestamptz

Pastoral Care Response Library

pastoral_care_responses (~597 rows)

Pre-researched, CPE-quality pastoral care response patterns. Used by both chatbot (pastoral-care-library.ts) and voice agent (Care Agent) to serve seminary-quality empathetic responses instead of LLM improvisation. Organized by category → subcategory → response_type.

ColumnTypeNotes
iduuidPK
categorytextgrief_loss, illness_health, addiction_recovery, anxiety_mental_health, relationship_crisis, spiritual_crisis, additional_crisis
subcategorytext~80 subcategories (e.g. death_of_spouse, suicidal_ideation, domestic_violence)
response_typetextCHECK: opener, followup, feeling_articulation, bridge_to_human, avoid, context_note, framework, fallback_bridge
traditiontextDefault universal; can be tradition-specific
contenttextThe actual response text or instruction
avoid_reasontextFor avoid type: WHY this phrase is harmful
safety_leveltextCHECK: standard, elevated, life_safety
safety_resourcestext[]Crisis hotlines (US + Canadian)
professional_referralbooleanDefault false; true if bridge suggests counselor
theological_sensitivitytextCHECK: low, medium, high, critical
first_disclosurebooleanDefault false; true for "I've never told anyone"
source_principletextNamed CPE framework (Ghost Sentence Rule, OARS, etc.)
tagstext[]Search tags
sort_orderintegerOrdering within (category, subcategory, response_type)
is_activebooleanDefault true
created_attimestamptz
updated_attimestamptz

Consumed by: Chatbot src/lib/pastoral-care-library.tsloadCareLibraryContext(). Voice agent session.py (future per-turn RAG).


tradition_care_context (~22 rows)

Per-tradition context blocks that calibrate pastoral care responses. Includes clergy titles, care structures, sacramental rules, theological notes, bridge language, sensitive topic handling, and tradition-specific avoids. 22 traditions: universal + 21 specific.

ColumnTypeNotes
iduuidPK
tradition_keytextuniversal, southern_baptist, catholic, orthodox, methodist, anglican, mennonite, seventh_day_adventist, churches_of_christ, unitarian_universalist, etc.
tradition_nametextDisplay name (e.g. "Roman Catholic", "Southern Baptist Convention")
clergy_titlestext[]All valid titles (e.g. {Father, Monsignor, Deacon})
clergy_default_titletextMost common title (e.g. "Father" for Catholic)
care_structuresjsonbPrimary/secondary/lay care providers
sacramental_rulestext[]What AI must NEVER attempt (confession, anointing, etc.)
theological_notestext[]Key theology that shapes care (suffering, saints, etc.)
bridge_language_overridesjsonbTradition-specific bridge phrasing
sensitive_topic_notesjsonbPer-topic notes (divorce, LGBTQ+, suicide, etc.)
tradition_avoidstext[]Phrases NEVER to say for this tradition
context_prompttext200-400 word instruction block for the Care Agent
is_activebooleanDefault true
created_attimestamptz
updated_attimestamptz

Consumed by: Voice agent session.pyload_tradition_care_context(). Chatbot pastoral-care-library.tsloadCareLibraryContext().

Mapping: denominations.tradition_key (64 rows) maps each denomination to a tradition context. Python: tradition_care_contexts.pyDENOMINATION_TO_TRADITION_KEY. TypeScript: pastoral-care-library.tsDENOMINATION_TO_TRADITION_KEY.


Knowledge & Product Config

product_knowledge (~75 rows)

Runtime Q&A knowledge base consumed by both the chatbot and voice agent at session initialization. Edit via SQL — changes take effect immediately.

ColumnTypeNotes
iduuidPK
categorytextpewsearch, churchwiseai, billing, account, troubleshooting, getting_started, integrations, policies
questiontext
answertext
keywordstext[]Semantic search keywords
is_activebooleanDefault true
priorityinteger0–10; higher = more important
created_attimestamptz
updated_attimestamptz

Critical: This is the live product knowledge used by AI agents at runtime. Updates take effect immediately — no redeploy needed.


agentic_tools (~39 rows)

Registry of all available agent tools across chat and voice channels.

ColumnTypeNotes
idtextPK (slug, e.g. prayer_request)
nametextDisplay name
descriptiontext
categorytextTool category
tiertextMinimum plan required
chatbot_defaultbooleanEnabled for chatbot by default
voice_defaultbooleanEnabled for voice by default
chatbot_onlybooleanChat-only tool
voice_onlybooleanVoice-only tool
agent_grouptextWhich agent group uses this
is_llm_poweredbooleanWhether requires LLM call
sort_orderintegerDisplay order
created_attimestamptz
updated_attimestamptz

pricing_tiers (~38 rows)

Plan definitions for all products (ChurchWiseAI, SermonWise, ShareWiseAI). Source for organization_subscriptions tier lookups.

ColumnTypeNotes
iduuidPK
namevarcharPlan name
descriptiontext
price_centsintegerMonthly price in cents
billing_periodvarcharmonthly, annual; default monthly
stripe_price_idvarcharStripe Price ID
stripe_product_idvarcharStripe Product ID
app_access_jsonjsonbWhich apps are included
features_jsonjsonbFeature list
sermon_generation_limitintegerSermonWise monthly limit
chatbot_conversation_limitintegerChatbot monthly limit
max_usersintegerTeam seats
is_organizationalbooleanOrg-level plan
is_featuredbooleanHighlighted on pricing page
trial_daysintegerDefault 14
is_founder_pricingbooleanFounder discount plan
standard_price_centsintegerRegular price (for founders)
founder_discount_centsintegerDiscount amount
founder_enrollment_cutoffintegerMax founder members
gamification_multipliernumericDefault 1.00
sort_orderinteger
is_activeboolean
created_attimestamptz
updated_attimestamptz

Note: C:\dev\PRICING.md and knowledge/data/pricing.yaml are the canonical source of truth for pricing. Treat this table as operational, not authoritative.


church_document_uploads (~0 rows)

Documents uploaded to a church's knowledge base for RAG retrieval.

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
file_nametext
file_typetextMIME type
file_sizeintegerBytes
file_urltextSupabase Storage URL
processing_statusvarcharpending, processing, complete, failed
processing_errortext
moderation_statustextpending, approved, rejected
moderation_categoriesjsonb
uploaded_byuuid
processed_attimestamptz
metadatajsonb
created_attimestamptz

church_document_chunks (~0 rows)

Text chunks extracted from uploaded documents, with embeddings for semantic search.

ColumnTypeNotes
iduuidPK
document_iduuidFK → church_document_uploads.id
organization_iduuidFK → organizations.id
chunk_indexintegerPosition within document
contenttextChunk text
content_embeddingvectorpgvector embedding
metadatajsonb
created_attimestamptz

church_local_resources (~19 rows)

Local community resources (food banks, shelters, etc.) associated with a church for the voice/chatbot to reference.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
categoryUSER-DEFINEDEnum of resource categories
nametext
descriptiontext
phonetext
addresstext
websitetext
hourstext
notestext
is_criticalbooleanPriority resource
is_activeboolean
sort_orderintegerDefault 0
created_attimestamptz
updated_attimestamptz

church_rag_content (~53 rows)

Structured knowledge-base content for a church, used in RAG retrieval. Distinct from document chunks — these are manually authored/curated entries.

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
category_iduuidOptional category grouping
titletext
contenttext
content_embeddingvectorpgvector embedding
search_texttextDenormalized search text
metadatajsonb
tagstext[]Default {}
versionintegerDefault 1
is_activebooleanDefault true
created_byuuid
approved_byuuid
approved_attimestamptz
created_attimestamptz
updated_attimestamptz

organization_knowledge_base (~3 rows)

Per-organization FAQ entries for the chatbot (legacy path — prefer canned_responses).

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
questiontext
answertext
categorytext
priorityintegerDefault 0
exact_responsebooleanDefault false
activebooleanDefault true
created_attimestamptz
updated_attimestamptz

agent_knowledge_bases (~2 rows)

Knowledge base configuration for a specific chatbot agent instance.

ColumnTypeNotes
iduuidPK
agent_iduuidFK → chatbot_agents.id
nametext
descriptiontext
content_typestext[]faq, document, url; default all
chunk_sizeintegerDefault 512
chunk_overlapintegerDefault 50
similarity_thresholdnumericDefault 0.75
document_countintegerDefault 0
training_statustextidle, training, ready
last_trained_attimestamptz
created_attimestamptz
updated_attimestamptz

Organizations (ShareWiseAI Multi-Org)

organizations (~16 rows)

Top-level organization records for ShareWiseAI and the B2C app system. Each church that signs up gets an organization.

ColumnTypeNotes
iduuidPK
nametext
slugtextUnique URL slug
owner_iduuidFK → Supabase Auth users.id
organization_typetextchurch, ministry; default church
subscription_tiertextDefault free
verification_statustextpending, verified; default pending
verification_methodtext
verification_tokenuuidAuto-generated
verified_attimestamptz
verified_byuuid
contact_emailtext
contact_phonetext
street_addresstext
websitetext
descriptiontext
logo_urltext
theological_lens_preferencestext[]
primary_theological_lens_idinteger
theological_lens_weightsjsonb
doctrinal_positionsjsonb
doctrinal_overridesjsonbDefault {}
custom_exceptionsjsonb
church_faqsjsonb
church_setup_datajsonbOnboarding form data
church_setup_completedbooleanDefault false
church_setup_completed_attimestamptz
trial_starts_attimestamptz
trial_ends_attimestamptz
trial_statustextDefault active
trial_converted_attimestamptz
setup_completedbooleanDefault false
setup_steps_completedjsonbDefault []
is_internal_demobooleanDefault false
max_seatsintegerDefault 5
settingsjsonbDefault {}
metadatajsonbDefault {}
created_attimestamptz
updated_attimestamptz

organization_members (~0 rows)

Users who belong to an organization (team members).

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
user_iduuidFK → Supabase Auth users.id
rolevarcharowner, admin, member; default member
invited_byuuid
invited_attimestamptz
joined_attimestamptz
is_activebooleanDefault true
created_attimestamptz

organization_permissions (~0 rows)

Flat permission grants per organization member role.

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
roletext
can_invite_membersboolean
can_remove_membersboolean
can_change_rolesboolean
can_enable_appsboolean
can_configure_appsboolean
can_edit_profileboolean
can_manage_billingboolean
can_delete_organizationboolean
can_create_contentbooleanDefault true
can_edit_own_contentbooleanDefault true
can_edit_all_contentboolean
can_delete_contentboolean
created_attimestamptz
updated_attimestamptz

organization_roles (~0 rows)

Custom role definitions for an organization.

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
role_nametext
role_descriptiontext
permissionsjsonbDefault {}
is_custombooleanDefault true
created_byuuid
created_attimestamptz
updated_attimestamptz

organization_subscriptions (~0 rows)

Stripe subscription records for organization-level plans (ShareWiseAI, SermonWise via organizations).

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
pricing_tier_iduuidFK → pricing_tiers.id
stripe_subscription_idvarchar
stripe_customer_idvarchar
statusvarcharactive, trialing, canceled; default active
seats_includedintegerDefault 1
seats_usedintegerDefault 0
billing_emailvarchar
admin_user_iduuid
current_period_starttimestamptz
current_period_endtimestamptz
trial_starttimestamptz
trial_endtimestamptz
cancel_at_period_endbooleanDefault false
canceled_attimestamptz
ended_attimestamptz
metadata_jsonjsonb
created_attimestamptz
updated_attimestamptz

organization_app_access (~0 rows)

Which apps (chatbot, voice, social, sermons) an organization has access to.

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
app_idUSER-DEFINEDEnum of app identifiers
has_accessbooleanDefault true
enabled_attimestamptz
enabled_byuuid
created_attimestamptz
updated_attimestamptz

organization_tool_access (~0 rows)

Per-tool access grants for an organization, with usage tracking.

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
tool_slugtextFK → agentic_tools.id
pricing_tier_iduuidFK → pricing_tiers.id
subscription_item_iduuid
access_leveltextfull, limited; default full
usage_countintegerDefault 0
usage_limitintegerNull = unlimited
trial_expires_attimestamptz
enabled_attimestamptz
disabled_attimestamptz
created_attimestamptz
updated_attimestamptz

organization_tool_configs (~0 rows)

Per-tool configuration for an organization (custom settings per tool).

ColumnTypeNotes
iduuidPK
organization_iduuidFK → organizations.id
tool_slugtext
configjsonbDefault {}
enabledbooleanDefault true
created_attimestamptz
updated_attimestamptz

Social (ShareWiseAI)

ShareWiseAI is code-complete but not yet deployed (OAuth pending as of 2026-03-25). All social tables are empty.

social_platforms (~0 rows)

Platform catalog (Facebook, Instagram, etc.) with OAuth and media capability configs.

ColumnTypeNotes
idtextPK (e.g. facebook, instagram)
display_nametext
icon_nametext
base_api_urltext
max_text_lengthinteger
max_imagesintegerDefault 1
max_video_length_secinteger
supported_media_typestext[]
supports_storiesboolean
supports_reelsboolean
supports_schedulingboolean
supports_analyticsboolean
oauth_providertext
oauth_authorize_urltext
oauth_token_urltext
required_scopestext[]
is_activebooleanDefault true
configjsonb
created_attimestamptz
updated_attimestamptz

oauth_connections (~0 rows)

Generic OAuth token store for any provider (used by ShareWiseAI and potentially others).

ColumnTypeNotes
iduuidPK
user_iduuidFK → Supabase Auth users.id
providertext
access_tokentextEncrypted
refresh_tokentextEncrypted
token_expires_attimestamptz
scopestext[]
emailtext
created_attimestamptz
updated_attimestamptz

social_accounts (~0 rows)

Connected social media accounts (pages, profiles) for a church.

ColumnTypeNotes
iduuidPK
user_iduuidFK → Supabase Auth users.id
church_iduuidFK → premium_churches.church_id
property_idtextShareWiseAI workspace
platform_idtextFK → social_platforms.id
platform_account_idtextPlatform's account ID
account_nametext
account_handletext
account_avatar_urltext
account_typetextpage, profile; default page
access_tokentextEncrypted
refresh_tokentextEncrypted
token_expires_attimestamptz
token_scopestext[]
statustextactive, expired; default active
last_errortext
last_synced_attimestamptz
follower_countintegerDefault 0
following_countintegerDefault 0
post_countintegerDefault 0
configjsonb
created_attimestamptz
updated_attimestamptz

social_posts (~0 rows)

AI-generated social posts (content queue items tied to blog articles).

ColumnTypeNotes
iduuidPK
article_iduuidFK → articles.id
article_titletext
article_slugtext
article_urltext
platformtextTarget platform
contenttextPost text
hashtagstext[]Default {}
image_prompttext
suggested_image_urltext
statustextpending, approved, rejected, posted; default pending
rejection_reasontext
scheduled_fortimestamptz
posted_attimestamptz
post_urltext
reviewed_attimestamptz
reviewed_byuuid
generation_prompttext
model_usedtextDefault claude-sonnet-4-20250514
regeneration_countintegerDefault 0
engagement_datajsonb
created_attimestamptz
updated_attimestamptz

social_post_platform_results (~0 rows)

Actual publishing results and engagement metrics for a post on a specific platform account.

ColumnTypeNotes
iduuidPK
post_iduuidFK → social_posts.id
account_iduuidFK → social_accounts.id
platform_idtextFK → social_platforms.id
platform_post_idtextPlatform's ID for the post
platform_post_urltext
statustextpending, published, failed; default pending
error_messagetext
retry_countintegerDefault 0
published_attimestamptz
impressionsintegerDefault 0
reachintegerDefault 0
engagementsintegerDefault 0
likesintegerDefault 0
commentsintegerDefault 0
sharesintegerDefault 0
savesintegerDefault 0
clicksintegerDefault 0
video_viewsintegerDefault 0
raw_metricsjsonb
metrics_updated_attimestamptz
created_attimestamptz
updated_attimestamptz

social_analytics (~0 rows)

Daily analytics snapshots per connected social account.

ColumnTypeNotes
iduuidPK
account_iduuidFK → social_accounts.id
platform_idtext
snapshot_datedate
follower_countinteger
follower_changeinteger
posts_countinteger
impressionsinteger
reachinteger
engagementsinteger
clicksinteger
profile_visitsinteger
raw_datajsonb
created_attimestamptz

social_audit_log (~0 rows)

Immutable audit trail for ShareWiseAI actions.

ColumnTypeNotes
iduuidPK
user_iduuid
church_iduuid
property_idtext
actiontext
detailsjsonb
ip_addresstext
user_agenttext
created_attimestamptz

Safety: Audit log — never delete rows.


social_campaigns (~0 rows)

Named campaigns grouping related social posts.

ColumnTypeNotes
iduuidPK
user_iduuid
church_iduuid
property_idtext
nametext
descriptiontext
start_datedate
end_datedate
statustextdraft, active, completed; default draft
goal_typetext
goal_targetjsonb
tagstext[]
colortextDefault #D4AF37
created_attimestamptz
updated_attimestamptz

social_content_queue (~0 rows)

Community feed posts (internal — not the same as social_posts).

ColumnTypeNotes
iduuidPK
user_iduuid
group_iduuid
post_typetext
contenttext
media_urlstext[]
sermon_iduuidFK → sermons.id
bible_passagetext
reaction_countintegerDefault 0
comment_countintegerDefault 0
share_countintegerDefault 0
visibilitytextpublic, members; default public
is_pinnedbooleanDefault false
created_attimestamptz
updated_attimestamptz

social_schedules (~0 rows)

Recurring post schedule definitions for auto-publishing.

ColumnTypeNotes
iduuidPK
user_iduuid
church_iduuid
property_idtext
nametext
descriptiontext
schedule_typetextrecurring, one_time, etc.
timezonetextDefault America/Chicago
recurrence_configjsonbCron or interval config
auto_fill_enabledbooleanDefault false
auto_fill_sourcetext
is_activebooleanDefault true
last_triggered_attimestamptz
created_attimestamptz
updated_attimestamptz

social_subscriptions (~0 rows)

ShareWiseAI billing subscriptions per user/church.

ColumnTypeNotes
iduuidPK
user_iduuid
church_iduuid
property_idtext
tiertextfree, pro, business, agency; default free
stripe_customer_idtext
stripe_subscription_idtext
statustextDefault active
posts_used_this_monthintegerDefault 0
ai_generations_used_this_monthintegerDefault 0
usage_reset_attimestamptzResets at month boundary
workspace_countintegerDefault 1
current_period_starttimestamptz
current_period_endtimestamptz
trial_ends_attimestamptz
configjsonb
created_attimestamptz
updated_attimestamptz

social_oauth_nonces (~0 rows)

Short-lived OAuth state tokens for the social media connect flow (CSRF protection).

ColumnTypeNotes
iduuidPK
noncetextRandom state value
platformtext
owner_typetextuser, church
owner_idtext
expires_attimestamptz
created_attimestamptz

Sermons (SermonWise)

sermons (~36 rows)

AI-generated sermon drafts created by SermonWise subscribers.

ColumnTypeNotes
iduuidPK
user_iduuidFK → Supabase Auth users.id
organization_iduuidFK → organizations.id
titletext
scripture_referencetext
sermon_styletext
contentjsonbStructured sermon content
statustextdraft, published; default draft
is_publicbooleanDefault false
date_preacheddate
notestext
series_iduuidFK → sermon series
theological_lens_idinteger
target_audiencetext
parent_sermon_iduuidFor variations
voice_stylejsonb
created_attimestamptz
updated_attimestamptz

shared_sermons (~35 rows)

Publicly shared sermons for the community discovery feed.

ColumnTypeNotes
iduuidPK
sermon_iduuidFK → sermons.id
user_iduuidFK → Supabase Auth users.id
author_nametextDefault Anonymous Pastor
share_typetextpublic, lens_only; default public
titletext
scripture_referencetext
descriptiontext
traditiontext
sermon_styletext
tagstext[]Default {}
primary_lens_idinteger
method_idinteger
introduction_previewtext
key_pointsjsonb
word_countinteger
view_countintegerDefault 0
copy_countintegerDefault 0
like_countintegerDefault 0
quality_scorenumeric
ai_feedbacktext
user_ratingnumeric
moderation_statustextpending, approved, rejected; default pending
last_viewed_attimestamptz
created_attimestamptz
updated_attimestamptz

sermon_generation_usage (~1 row)

Monthly generation counter per user for SermonWise rate limiting.

ColumnTypeNotes
iduuidPK
user_iduuidFK → Supabase Auth users.id
month_yeartextFormat YYYY-MM
generation_countintegerDefault 0
last_generation_attimestamptz
created_attimestamptz
updated_attimestamptz

app_trials (~5 rows)

Trial records for any app (chatbot, sermons, voice).

ColumnTypeNotes
iduuidPK
user_iduuidFK → Supabase Auth users.id
organization_iduuidFK → organizations.id
app_idtextWhich app is being trialed
bundle_typetext
trial_started_attimestamptzDefault now()
trial_ends_attimestamptzDefault now() + 14 days
is_convertedbooleanDefault false
converted_attimestamptz
created_attimestamptz

user_subscriptions (~1 row)

User-level Stripe subscriptions (SermonWise individual users, not org-level).

ColumnTypeNotes
iduuidPK
user_iduuidFK → Supabase Auth users.id
pricing_tier_iduuidFK → pricing_tiers.id
stripe_subscription_idvarchar
stripe_customer_idvarchar
statusvarcharactive, trialing, canceled; default active
current_period_starttimestamptz
current_period_endtimestamptz
trial_starttimestamptz
trial_endtimestamptz
cancel_at_period_endbooleanDefault false
canceled_attimestamptz
ended_attimestamptz
is_founder_memberbooleanDefault false
founder_enrolled_attimestamptz
locked_price_centsintegerFounder locked price
founder_member_numberintegerSequential founder number
created_attimestamptz
updated_attimestamptz

Operational

articles (~54 rows)

Blog articles for churchwiseai.com. Rendered at /blog/[slug].

ColumnTypeNotes
iduuidPK
titletext
slugtextUnique URL slug
contenttextHTML content
excerpttext
statustextdraft, published; default draft
categoryjsonbCategory object
primary_category_idinteger
content_type_idinteger
category_migration_statustextDefault legacy
tagsjsonbDefault []
authorjsonbAuthor object
featured_image_urltext
featured_image_alttext
read_timeintegerMinutes; default 0
ctajsonbCall-to-action block
seojsonbSEO title/description/OG
table_of_contentsjsonbDefault []
sync_metadatajsonbExternal sync info
published_attimestamptz
created_attimestamptz
updated_attimestamptz

email_subscribers (~6 rows)

Email list subscribers (lead capture, blog signups, etc.).

ColumnTypeNotes
iduuidPK
emailtextUnique
nametext
sourcetextSignup source (e.g. blog, landing_page)
statustextactive, unsubscribed; default active
tagstext[]Default {}
church_sizetext
citytext
state_codetext
intereststext[]Default {}
subscribed_attimestamptz
last_email_sent_attimestamptz
email_open_countintegerDefault 0
email_click_countintegerDefault 0
converted_to_customerbooleanDefault false
conversion_datetimestamptz
metadatajsonb
created_attimestamptz
updated_attimestamptz

chat_usage_tracking (~93 rows)

Per-response LLM usage tracking for cost monitoring.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
session_idtext
agent_typetext
response_sourcetextllm, canned, rag
input_tokensintegerDefault 0
output_tokensintegerDefault 0
estimated_cost_usdnumericDefault 0
modeltext
canned_response_iduuidFK → canned_responses.id if canned
created_attimestamptz

tool_invocations (~256 rows)

Log of every agent tool call across chat and voice channels.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
tool_idtextFK → agentic_tools.id
agent_typetext
persona_typetext
channeltextchat, voice
session_idtext
created_attimestamptz

ops_errors (~0 rows)

System error log — deduped by fingerprint, with occurrence counting.

ColumnTypeNotes
iduuidPK
sourcetextError source system
severitytextp0p3; default p1
propertytextWhich site/app
fingerprinttextDeduplication key (unique)
messagetext
stacktext
routetextURL route
repotextGit repo
http_statusinteger
servicetext
raw_payloadjsonb
statustextnew, acknowledged, resolved; default new
occurrencesintegerDefault 1
first_seen_attimestamptz
last_seen_attimestamptz
alert_sent_attimestamptz
dispatched_attimestamptz
resolved_attimestamptz
fix_committext
fix_pr_urltext
fix_summarytext
created_attimestamptz

ops_quota_snapshots (~1,452 rows)

Time-series quota/metric snapshots for operational monitoring.

ColumnTypeNotes
iduuidPK
servicetextService name
metrictextMetric name
valuenumeric
recorded_attimestamptzDefault now()

founder_action_items (~0 rows)

Action items requiring manual founder intervention. Surfaced in the admin FounderDashboard.

ColumnTypeNotes
iduuidPK
action_idtextUnique stable identifier
titletext
prioritytextP0, P1, P2
descriptiontext
locationtextWhere to act (URL or system)
reasontextWhy this needs attention
statustextpending, completed; default pending
created_bytextDefault agent
remind_countintegerDefault 0
last_reminded_attimestamptz
created_attimestamptz
completed_attimestamptz

founder_google_tokens (~0 rows)

Google OAuth tokens for the founder's Gmail/Calendar integrations used by agents.

ColumnTypeNotes
iduuidPK
emailtextGoogle account email
access_tokentext
refresh_tokentext
expires_attimestamptz
scopestextGranted scopes
created_attimestamptz
updated_attimestamptz

Safety: Contains live OAuth credentials. Never expose or bulk-read.


golive_checklist_progress (~8 rows)

Launch checklist progress state saved per user session.

ColumnTypeNotes
iduuidPK
user_identifiertextSession/user ID
checklist_versiontextDefault 285
progress_datajsonbCheck states per item
notes_datajsonbPer-item notes
custom_testsjsonbUser-added test items; default []
issue_mappingjsonbTest-to-issue links
last_saved_attimestamptz
created_attimestamptz
updated_attimestamptz

known_issues (~217 rows)

Issue tracker for known bugs and feature gaps.

ColumnTypeNotes
iduuidPK
titletext
descriptiontext
categoryvarchar
statusvarcharreported, in_progress, resolved; default reported
priorityvarcharlow, medium, high, critical; default medium
affected_appvarchar
upvote_countintegerDefault 1
reporter_emailtext
reporter_nametext
admin_notestext
fix_detailstext
feedback_countintegerDefault 0
screenshot_pathsjsonbDefault []
devicetext
resolved_attimestamptz
created_attimestamptz
updated_attimestamptz

known_issue_history (~196 rows)

Status change history for known_issues.

ColumnTypeNotes
iduuidPK
issue_iduuidFK → known_issues.id
old_statustext
new_statustext
changed_bytextDefault system
change_reasontext
metadatajsonb
created_attimestamptz

response_reviews (~283 rows)

Chatbot responses flagged for human review and potential promotion to canned responses.

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
conversation_idtext
user_messagetext
ai_responsetext
agent_typetext
modeltext
review_statustextpending, approved, rejected; default pending
edited_answertextImproved version of response
reviewer_notestext
promoted_to_canned_iduuidFK → canned_responses.id if promoted
detected_languagevarcharDefault en
created_attimestamptz
reviewed_attimestamptz

rate_limit_entries (~24 rows)

Sliding-window rate limit counters keyed by identifier.

ColumnTypeNotes
keytextPK — rate limit identifier (IP, user, etc.)
window_starttimestamptzWindow start time
countintegerRequest count in window

telemetry_breadcrumbs (~26,032 rows)

Frontend breadcrumb events for session replay and debugging. High volume — prune periodically.

ColumnTypeNotes
iduuidPK
event_idtextGroups breadcrumbs to a telemetry event
typetextBreadcrumb type
categorytext
leveltextinfo, warning, error; default info
messagetext
datajsonbEvent data
timestamptimestamptz
sequence_numberintegerOrder within event

telemetry_events (~1,846 rows)

Frontend telemetry events (errors, performance, user actions).

ColumnTypeNotes
iduuidPK
event_idtextUnique event identifier
project_idtextWhich project
environmenttextdevelopment, production; default development
releasetextApp version/release
platformtextDefault javascript
leveltext
event_typetext
messagetext
titletext
culprittextFile/function that caused the event
timestamptimestamptz
time_spentinteger
tagsjsonb
extrajsonb
contextsjsonbBrowser, OS, runtime context
user_idtext
user_emailtext
user_nametext
request_urltext
request_methodtext
request_headersjsonb
exception_typetext
exception_valuetext
stack_tracejsonb
performance_metricsjsonb
statustextunresolved, resolved; default unresolved
assigned_totext
fingerprinttext[]
checksumtext
created_attimestamptz
updated_attimestamptz

telemetry_performance (~476 rows)

Core Web Vitals and page load metrics.

ColumnTypeNotes
iduuidPK
event_idtextFK → telemetry_events.event_id
first_contentful_paintnumericms
largest_contentful_paintnumericms
first_input_delaynumericms
cumulative_layout_shiftnumericScore
navigation_startnumeric
dom_content_loadednumericms
load_completenumericms
custom_metricsjsonb
page_urltext
user_agenttext
viewport_widthinteger
viewport_heightinteger
connection_typetext
created_attimestamptz

Inbox (Compose + Safety)

inbox_outbox_messages (~0 rows)

One row per compose-message send (email, SMS, or internal note) across every inbox card type (prayer, visitor, callback, call). Multi-vertical design — tenant_id is premium_churches.id in v1; future verticals write their own tenant ID. Added 2026-05-12 (migrations/2026-05-12-inbox-outbox-messages.sql, FA-082/Inbox compose feature).

ColumnTypeNotes
iduuidPK
tenant_iduuidOwning tenant (premium_churches.id in v1). Not declared FK — multi-vertical design.
verticaltextVertical discriminator: church | funeral | vet | dental | restaurant | law | real_estate. Default church.
item_typetextSource inbox card type: prayer | visitor | callback | call (CHECK constraint)
item_iduuidUUID of the source inbox row (soft/discriminated ref, not FK)
channeltextDelivery channel: email | sms | internal_note (CHECK constraint)
to_addresstexte164 for SMS; email address for email; NULL for internal_note
subjecttextEmail subject line (email only; NULL for SMS/internal_note)
bodytextMessage content (1–4000 chars enforced by API layer)
composed_by_member_iduuidchurch_team_members.id if a member token was used; NULL for admin-token callers
composed_by_nametextDisplay name of the composer
composed_attimestamptzDefault NOW()
statustextState machine: queued | sending | sent | failed | suppressed (CHECK constraint). Default queued.
status_detailtextHuman-readable failure reason or suppression note
sent_attimestamptzWhen the provider accepted the message
providertextresend | twilio | null for internal_note
provider_message_idtextResend message-ID or Twilio SID

Indexes:

  • inbox_outbox_messages_tenant_item_idx(tenant_id, item_type, item_id, composed_at DESC) — primary retrieval for "all messages for this tenant+item in reverse chron order"
  • inbox_outbox_messages_status_idx — partial index on (status, composed_at) WHERE status IN ('queued','failed') — for future outbox cron retry processor

Access: Server-only writes via Next.js API routes (src/app/api/inbox/compose/route.ts). No direct client access. service_role has SELECT/INSERT/UPDATE.


inbox_item_state (rows vary)

Per-item per-viewer state for inbox cards: read receipts, assignments, Safety resolution. The resolved_by_members column was added 2026-05-12 for per-viewer Safety resolution (PR #419, migrations/2026-05-12-inbox-item-state-resolved-by-members.sql).

Selected columns of note (full schema from migration file):

ColumnTypeNotes
iduuidPK
church_iduuidFK → premium_churches.church_id
item_typetexte.g. safety, prayer, visitor, callback
item_iduuidUUID of the source inbox row
resolved_attimestamptzScalar: timestamp of first/last resolve (backward-compat)
resolved_byuuidScalar: UUID of first/last resolver (backward-compat)
resolved_by_membersjsonbPer-viewer array: [{member_id, resolved_at}, ...]. NULL until a viewer resolves. Each member can resolve independently. Admin-token callers write member_id: null. Populated by resolve_inbox_safety_item() RPC.
updated_attimestamptz

Per-viewer Safety: resolved_by_members replaces the scalar-only scheme for multi-member churches. One team member resolving no longer hides the safety card from all others. The scalar resolved_at + resolved_by columns are preserved for one-release backward-compat.


Safety Rules

The following tables require special care:

TableRule
premium_churchesOnly ~6 rows exist (founder test accounts). Every mutation is consequential. NEVER bulk delete. Confirm before any UPDATE/DELETE.
product_knowledgeConsumed by AI agents at runtime. Changes take effect immediately — write carefully.
unified_rag_content327K rows of irreplaceable church content (owned by PewSearch codebase, listed in pewsearch schema doc). NEVER bulk delete from any codebase.
church_access_auditImmutable security audit log. Never delete rows.
social_audit_logImmutable audit log. Never delete rows.
known_issue_historyHistorical record. Never delete rows.
voice_call_logsProduction call transcripts and summaries. Never bulk delete.
telemetry_breadcrumbsHigh volume (~26K rows). Safe to prune old rows, but use date-bounded DELETEs only.
founder_google_tokensContains live OAuth credentials. Never expose in logs or API responses.
ops_errorsDeduplicated by fingerprint — use UPSERT pattern, not blind INSERT.
church_document_uploads / church_document_chunksAlways delete chunks before deleting the parent upload (no cascade).
canned_response_templatesShared system templates — changes affect all churches. Founder approval required before modifying.
inbox_outbox_messagesAudit log of all compose-message sends. Never delete sent rows — they are the paper trail. Use suppressed status for intentional no-ops.
inbox_item_statePer-viewer state including Safety resolutions. Never delete rows — use RPC resolve_inbox_safety_item() for writes.