Automated Architecture Validation Report
Date: 2026-04-24
Result: 4 invariant violations found — 2 critical (P0-P1) require attention
Critical Findings (P0-P1)
Invariant #1 — Three-Layer Backend: SQL in Routers
Routers must not contain raw SQL. Violations found:
src/backend/routers/processes.py lines 777–865: cursor = conn.cursor(), CREATE TABLE IF NOT EXISTS process_schedules, INSERT OR REPLACE INTO process_schedules, DELETE FROM process_schedules
src/backend/routers/voice.py lines 176–306: Direct cursor.execute("UPDATE agent_ownership ...") and cursor.execute("SELECT voice_system_prompt ...")
src/backend/routers/triggers.py line 252: cursor.execute("SELECT * FROM process_schedules ...")
SQL must move to db/ layer modules per the Router → Service → DB invariant.
Invariant #3 — Schema in db/schema.py, Migrations in db/migrations.py
CREATE TABLE statements found outside the designated files:
src/backend/routers/processes.py line 781: CREATE TABLE IF NOT EXISTS process_schedules (ad-hoc, no migration)
src/backend/services/process_engine/services/alerts.py line 163: CREATE TABLE IF NOT EXISTS cost_thresholds
src/backend/services/process_engine/services/alerts.py line 178: CREATE TABLE IF NOT EXISTS cost_alerts
src/backend/services/process_engine/services/templates.py line 117: CREATE TABLE IF NOT EXISTS process_templates
src/backend/services/process_engine/repositories/audit.py: CREATE TABLE audit_entries
src/backend/services/process_engine/repositories/sqlite_definitions.py: CREATE TABLE process_definitions
src/backend/services/process_engine/repositories/sqlite_executions.py: CREATE TABLE process_executions, step_executions
src/backend/services/process_engine/repositories/sqlite_events.py: CREATE TABLE execution_events
All DDL must live in db/schema.py with versioned migrations in db/migrations.py.
Non-Critical Findings (P2-P3, informational)
Invariant #6 — Frontend: Store = Domain, View = Page
Direct api.get() / api.post() calls found in view files (should go through Pinia stores):
ProcessList.vue, ProcessWizard.vue, ProcessEditor.vue — 8 violations
Invariant #7 — Single API Client (api.js)
Raw fetch() calls scattered outside api.js — 19+ occurrences in views, components, and router:
AgentDetail.vue, Approvals.vue, ApiKeys.vue, FileManager.vue, ChatPanel.vue, FilesPanel.vue, HostTelemetry.vue, router/index.js, etc.
Invariant #10 — Process Engine: DDD Isolation
Routers importing directly from process_engine.domain (should go through service layer):
routers/processes.py, routers/triggers.py, routers/executions.py, routers/approvals.py
Invariant #15 — Pydantic Models Centralized in models.py
60+ model class definitions scattered across router files instead of in models.py:
fan_out.py, processes.py, settings.py, executions.py, alerts.py, slack.py, and many more
Recommended Actions
- [P1] Extract SQL from
processes.py, voice.py, triggers.py into db/ layer modules following the existing XOperations mixin pattern
- [P1] Move
process_schedules and all Process Engine CREATE TABLE statements into db/schema.py with corresponding migrations in db/migrations.py
- [P2] Migrate Process view API calls (
ProcessEditor.vue, ProcessList.vue, ProcessWizard.vue) to use Pinia stores
- [P2] Consolidate router-local models (
processes.py, settings.py, etc.) into models.py
Generated by scheduled /validate-architecture run
Automated Architecture Validation Report
Date: 2026-04-24
Result: 4 invariant violations found — 2 critical (P0-P1) require attention
Critical Findings (P0-P1)
Invariant #1 — Three-Layer Backend: SQL in Routers
Routers must not contain raw SQL. Violations found:
src/backend/routers/processes.pylines 777–865:cursor = conn.cursor(),CREATE TABLE IF NOT EXISTS process_schedules,INSERT OR REPLACE INTO process_schedules,DELETE FROM process_schedulessrc/backend/routers/voice.pylines 176–306: Directcursor.execute("UPDATE agent_ownership ...")andcursor.execute("SELECT voice_system_prompt ...")src/backend/routers/triggers.pyline 252:cursor.execute("SELECT * FROM process_schedules ...")SQL must move to
db/layer modules per the Router → Service → DB invariant.Invariant #3 — Schema in
db/schema.py, Migrations indb/migrations.pyCREATE TABLEstatements found outside the designated files:src/backend/routers/processes.pyline 781:CREATE TABLE IF NOT EXISTS process_schedules(ad-hoc, no migration)src/backend/services/process_engine/services/alerts.pyline 163:CREATE TABLE IF NOT EXISTS cost_thresholdssrc/backend/services/process_engine/services/alerts.pyline 178:CREATE TABLE IF NOT EXISTS cost_alertssrc/backend/services/process_engine/services/templates.pyline 117:CREATE TABLE IF NOT EXISTS process_templatessrc/backend/services/process_engine/repositories/audit.py:CREATE TABLE audit_entriessrc/backend/services/process_engine/repositories/sqlite_definitions.py:CREATE TABLE process_definitionssrc/backend/services/process_engine/repositories/sqlite_executions.py:CREATE TABLE process_executions,step_executionssrc/backend/services/process_engine/repositories/sqlite_events.py:CREATE TABLE execution_eventsAll DDL must live in
db/schema.pywith versioned migrations indb/migrations.py.Non-Critical Findings (P2-P3, informational)
Invariant #6 — Frontend: Store = Domain, View = Page
Direct
api.get()/api.post()calls found in view files (should go through Pinia stores):ProcessList.vue,ProcessWizard.vue,ProcessEditor.vue— 8 violationsInvariant #7 — Single API Client (
api.js)Raw
fetch()calls scattered outsideapi.js— 19+ occurrences in views, components, and router:AgentDetail.vue,Approvals.vue,ApiKeys.vue,FileManager.vue,ChatPanel.vue,FilesPanel.vue,HostTelemetry.vue,router/index.js, etc.Invariant #10 — Process Engine: DDD Isolation
Routers importing directly from
process_engine.domain(should go through service layer):routers/processes.py,routers/triggers.py,routers/executions.py,routers/approvals.pyInvariant #15 — Pydantic Models Centralized in
models.py60+ model class definitions scattered across router files instead of in
models.py:fan_out.py,processes.py,settings.py,executions.py,alerts.py,slack.py, and many moreRecommended Actions
processes.py,voice.py,triggers.pyintodb/layer modules following the existingXOperationsmixin patternprocess_schedulesand all Process EngineCREATE TABLEstatements intodb/schema.pywith corresponding migrations indb/migrations.pyProcessEditor.vue,ProcessList.vue,ProcessWizard.vue) to use Pinia storesprocesses.py,settings.py, etc.) intomodels.pyGenerated by scheduled /validate-architecture run