Automated Schema Validation Report
Date: 2026-05-08
Result: 25 critical schema drift issues require attention (all P1)
Architectural Invariant #3 states: "All table DDL lives in schema.py. Schema changes require a versioned migration in migrations.py." The findings below show that schema.py is no longer the authoritative DDL source.
Critical Findings (P1)
1. 11 Tables exist only in migrations.py — missing from schema.py
These tables have no CREATE TABLE entry in schema.py and are only created via the migration second-pass. The system functions at runtime, but schema.py cannot be read as a complete schema reference.
| Table |
Migration |
Feature |
agent_notifications |
agent_notifications |
NOTIF-001 |
subscription_credentials |
subscription_credentials |
SUB-001 |
subscription_rate_limit_events |
subscription_rate_limit_tracking |
SUB-003 |
telegram_bindings |
telegram_bindings |
TELEGRAM-001 |
telegram_chat_links |
telegram_bindings |
TELEGRAM-001 |
telegram_group_configs |
telegram_group_configs |
TGRAM-GROUP |
slack_workspaces |
slack_channel_agents |
SLACK-002 |
slack_channel_agents |
slack_channel_agents |
SLACK-002 |
slack_active_threads |
slack_channel_agents |
SLACK-002 |
whatsapp_bindings |
whatsapp_bindings |
WHATSAPP-001 |
whatsapp_chat_links |
whatsapp_bindings |
WHATSAPP-001 |
2. 14 Columns added by migrations not present in schema.py DDL
agent_ownership (3 missing):
full_capabilities INTEGER DEFAULT 0 — migration agent_ownership_full_capabilities
voice_system_prompt TEXT — migration agent_ownership_voice_prompt
max_backlog_depth INTEGER DEFAULT 50 — migration backlog_support (BACKLOG-001)
schedule_executions (9 missing):
source_user_id INTEGER — migration execution_origin_tracking (AUDIT-001)
source_user_email TEXT — migration execution_origin_tracking
source_agent_name TEXT — migration execution_origin_tracking
source_mcp_key_id TEXT — migration execution_origin_tracking
source_mcp_key_name TEXT — migration execution_origin_tracking
claude_session_id TEXT — migration execution_session_tracking (EXEC-023)
fan_out_id TEXT — migration execution_fan_out_id (FANOUT-001)
queued_at TEXT — migration backlog_support (BACKLOG-001)
backlog_metadata TEXT — migration backlog_support (BACKLOG-001)
agent_schedules (2 missing):
webhook_token TEXT — migration agent_schedules_webhook (WEBHOOK-001)
webhook_enabled INTEGER DEFAULT 0 — migration agent_schedules_webhook (WEBHOOK-001)
Recommended Actions
-
Add the 11 missing tables to schema.py — copy the CREATE TABLE IF NOT EXISTS DDL from their respective migrations into schema.py's TABLES dict, in feature-area groups. No migration needed — schema.py CREATE TABLE IF NOT EXISTS is idempotent.
-
Add the 14 missing columns to their CREATE TABLE statements in schema.py — update agent_ownership, schedule_executions, and agent_schedules DDL blocks. Corresponding ALTER TABLE migrations already exist for existing DBs.
-
Add the missing tables' indexes to schema.py's INDEXES list — several migration-only tables also create indexes inline; move those to INDEXES for the same idempotency guarantee.
What Is Clean
- ✅ No ad-hoc
CREATE TABLE or ALTER TABLE outside schema.py / migrations.py
- ✅ All migrations are idempotent (use
_safe_add_column / IF NOT EXISTS)
- ✅ No P0 failures — the dual-pass migration runner ensures all tables/columns land on both fresh and upgraded installs
Generated by scheduled /validate-schema run — 2026-05-08
Automated Schema Validation Report
Date: 2026-05-08
Result: 25 critical schema drift issues require attention (all P1)
Architectural Invariant #3 states: "All table DDL lives in
schema.py. Schema changes require a versioned migration inmigrations.py." The findings below show thatschema.pyis no longer the authoritative DDL source.Critical Findings (P1)
1. 11 Tables exist only in
migrations.py— missing fromschema.pyThese tables have no
CREATE TABLEentry inschema.pyand are only created via the migration second-pass. The system functions at runtime, butschema.pycannot be read as a complete schema reference.agent_notificationsagent_notificationssubscription_credentialssubscription_credentialssubscription_rate_limit_eventssubscription_rate_limit_trackingtelegram_bindingstelegram_bindingstelegram_chat_linkstelegram_bindingstelegram_group_configstelegram_group_configsslack_workspacesslack_channel_agentsslack_channel_agentsslack_channel_agentsslack_active_threadsslack_channel_agentswhatsapp_bindingswhatsapp_bindingswhatsapp_chat_linkswhatsapp_bindings2. 14 Columns added by migrations not present in
schema.pyDDLagent_ownership(3 missing):full_capabilities INTEGER DEFAULT 0— migrationagent_ownership_full_capabilitiesvoice_system_prompt TEXT— migrationagent_ownership_voice_promptmax_backlog_depth INTEGER DEFAULT 50— migrationbacklog_support(BACKLOG-001)schedule_executions(9 missing):source_user_id INTEGER— migrationexecution_origin_tracking(AUDIT-001)source_user_email TEXT— migrationexecution_origin_trackingsource_agent_name TEXT— migrationexecution_origin_trackingsource_mcp_key_id TEXT— migrationexecution_origin_trackingsource_mcp_key_name TEXT— migrationexecution_origin_trackingclaude_session_id TEXT— migrationexecution_session_tracking(EXEC-023)fan_out_id TEXT— migrationexecution_fan_out_id(FANOUT-001)queued_at TEXT— migrationbacklog_support(BACKLOG-001)backlog_metadata TEXT— migrationbacklog_support(BACKLOG-001)agent_schedules(2 missing):webhook_token TEXT— migrationagent_schedules_webhook(WEBHOOK-001)webhook_enabled INTEGER DEFAULT 0— migrationagent_schedules_webhook(WEBHOOK-001)Recommended Actions
Add the 11 missing tables to
schema.py— copy theCREATE TABLE IF NOT EXISTSDDL from their respective migrations intoschema.py'sTABLESdict, in feature-area groups. No migration needed — schema.pyCREATE TABLE IF NOT EXISTSis idempotent.Add the 14 missing columns to their
CREATE TABLEstatements inschema.py— updateagent_ownership,schedule_executions, andagent_schedulesDDL blocks. CorrespondingALTER TABLEmigrations already exist for existing DBs.Add the missing tables' indexes to
schema.py'sINDEXESlist — several migration-only tables also create indexes inline; move those toINDEXESfor the same idempotency guarantee.What Is Clean
CREATE TABLEorALTER TABLEoutsideschema.py/migrations.py_safe_add_column/IF NOT EXISTS)Generated by scheduled /validate-schema run — 2026-05-08