fix(gate-b): fresh-db install path - conditional guards on plugin-table migrations + dual-path convergence migrations
Check Cross-Plugin Imports / check (push) Has been cancelled
Check Cross-Plugin Imports / check (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
-- Dual-path convergence (Gate B): add compliance columns that Alembic
|
||||
-- migration 0119 adds on the core path. Idempotent so both install paths
|
||||
-- converge to the identical schema.
|
||||
ALTER TABLE ai_providers ADD COLUMN IF NOT EXISTS region VARCHAR(20) NOT NULL DEFAULT 'unknown';
|
||||
ALTER TABLE ai_providers ADD COLUMN IF NOT EXISTS hosting_type VARCHAR(30) NOT NULL DEFAULT 'cloud';
|
||||
ALTER TABLE ai_providers ADD COLUMN IF NOT EXISTS dpa_status VARCHAR(20) NOT NULL DEFAULT 'none';
|
||||
ALTER TABLE ai_providers ADD COLUMN IF NOT EXISTS retention_policy TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE ai_providers ADD COLUMN IF NOT EXISTS training_on_customer_data BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE ai_providers ADD COLUMN IF NOT EXISTS transfer_notice TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE ai_providers ADD COLUMN IF NOT EXISTS allowed_data_classes JSONB NOT NULL DEFAULT '[]'::jsonb;
|
||||
@@ -42,7 +42,7 @@ class AIAssistantPlugin(BasePlugin):
|
||||
),
|
||||
],
|
||||
events=[],
|
||||
migrations=["0001_initial.sql", "0002_folders_attachments.sql"],
|
||||
migrations=["0001_initial.sql", "0002_folders_attachments.sql", "0003_sort_order.sql", "0004_compliance_fields.sql"],
|
||||
permissions=[
|
||||
"ai:read",
|
||||
"ai:write",
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
-- Dual-path convergence (Gate B): create the ReAct step-tracking table
|
||||
-- that Alembic migration 0121 creates on the core path, add the Phase-F
|
||||
-- columns from 0122, and apply the RLS policy from 0129/0136. Idempotent
|
||||
-- so both install paths converge to the identical schema.
|
||||
CREATE TABLE IF NOT EXISTS automation_agent_run_steps (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
agent_run_id UUID NOT NULL REFERENCES automation_agent_runs(id) ON DELETE CASCADE,
|
||||
step_number INTEGER NOT NULL,
|
||||
thought TEXT,
|
||||
action VARCHAR(255),
|
||||
action_input JSONB,
|
||||
observation TEXT,
|
||||
cost_usd FLOAT NOT NULL DEFAULT 0.0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS ix_agent_run_steps_run ON automation_agent_run_steps(tenant_id, agent_run_id);
|
||||
|
||||
ALTER TABLE automation_agent_definitions ADD COLUMN IF NOT EXISTS temperature FLOAT NOT NULL DEFAULT 0.3;
|
||||
ALTER TABLE automation_agent_definitions ADD COLUMN IF NOT EXISTS max_tokens INTEGER NOT NULL DEFAULT 1000;
|
||||
ALTER TABLE automation_agent_definitions ADD COLUMN IF NOT EXISTS max_steps INTEGER NOT NULL DEFAULT 20;
|
||||
ALTER TABLE automation_agent_definitions ADD COLUMN IF NOT EXISTS trace_mode VARCHAR(20) NOT NULL DEFAULT 'standard';
|
||||
ALTER TABLE automation_agent_definitions ADD COLUMN IF NOT EXISTS skill_ids JSONB NOT NULL DEFAULT '[]'::jsonb;
|
||||
ALTER TABLE automation_agent_definitions ADD COLUMN IF NOT EXISTS trigger_config JSONB NOT NULL DEFAULT '{}'::jsonb;
|
||||
ALTER TABLE automation_agent_definitions ADD COLUMN IF NOT EXISTS ai_use_case_metadata JSONB NOT NULL DEFAULT '{}'::jsonb;
|
||||
|
||||
-- RLS matching migrations 0129 + 0136 (current_tenant_id variant)
|
||||
ALTER TABLE automation_agent_run_steps ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS tenant_isolation ON automation_agent_run_steps;
|
||||
CREATE POLICY tenant_isolation ON automation_agent_run_steps
|
||||
USING (tenant_id::text = current_setting('app.current_tenant_id', true));
|
||||
@@ -62,7 +62,7 @@ class AutomationPlugin(BasePlugin):
|
||||
"mail.received",
|
||||
"workflow.timeout",
|
||||
],
|
||||
migrations=["0001_initial.sql", "0002_agent_subtasks.sql", "0003_skill_definitions.sql"],
|
||||
migrations=["0001_initial.sql", "0002_agent_subtasks.sql", "0003_skill_definitions.sql", "0004_run_steps_phase_f.sql"],
|
||||
permissions=[
|
||||
"automation:read",
|
||||
"automation:write",
|
||||
|
||||
@@ -25,7 +25,7 @@ class KnowledgePlugin(BasePlugin):
|
||||
"""Register event-driven extraction hooks on activation."""
|
||||
await super().on_activate(db, service_container, event_bus)
|
||||
try:
|
||||
from app.core.hooks import register_action
|
||||
from app.core.hooks import get_hook_registry
|
||||
from app.plugins.builtins.knowledge.services import extract_knowledge
|
||||
async def on_wiki_create(*args, **kwargs):
|
||||
article_id = kwargs.get("article_id") or kwargs.get("entity_id")
|
||||
@@ -41,7 +41,9 @@ class KnowledgePlugin(BasePlugin):
|
||||
source_type="wiki_article", source_id=uuid.UUID(str(article_id)),
|
||||
source_title=title, source_text=content,
|
||||
)
|
||||
register_action("wiki.article.created", on_wiki_create, priority=20, owner_tag="knowledge")
|
||||
get_hook_registry().register_action(
|
||||
"wiki.article.created", on_wiki_create, priority=20, owner_tag="knowledge"
|
||||
)
|
||||
# H-DATA-LIFE: Re-extract when wiki article is updated
|
||||
async def on_wiki_update(*args, **kwargs):
|
||||
article_id = kwargs.get("article_id") or kwargs.get("entity_id")
|
||||
@@ -57,7 +59,9 @@ class KnowledgePlugin(BasePlugin):
|
||||
source_type="wiki_article", source_id=uuid.UUID(str(article_id)),
|
||||
source_title=title, source_text=content,
|
||||
)
|
||||
register_action("wiki.article.updated", on_wiki_update, priority=20, owner_tag="knowledge")
|
||||
get_hook_registry().register_action(
|
||||
"wiki.article.updated", on_wiki_update, priority=20, owner_tag="knowledge"
|
||||
)
|
||||
logger.info("Registered knowledge extraction hooks")
|
||||
except Exception:
|
||||
logger.exception("Failed to register knowledge hooks")
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
-- Dual-path convergence (Gate B): add columns that Alembic migrations
|
||||
-- 0120 (is_system) and 0140 (folder_id) add on the core path. Idempotent
|
||||
-- so both install paths converge to the identical schema.
|
||||
ALTER TABLE comm_conversations ADD COLUMN IF NOT EXISTS is_system BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
CREATE INDEX IF NOT EXISTS ix_comm_conversations_tenant_system ON comm_conversations(tenant_id, is_system);
|
||||
ALTER TABLE comm_conversations ADD COLUMN IF NOT EXISTS folder_id UUID;
|
||||
CREATE INDEX IF NOT EXISTS ix_comm_conversations_folder ON comm_conversations(folder_id);
|
||||
@@ -39,7 +39,7 @@ class KommunikationPlugin(BasePlugin):
|
||||
"participant.left",
|
||||
"reaction.added",
|
||||
],
|
||||
migrations=["0001_initial.sql"],
|
||||
migrations=["0001_initial.sql", "0002_system_channel_folders.sql"],
|
||||
permissions=[
|
||||
"comm:read",
|
||||
"comm:write",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
-- Dual-path convergence (Gate B): add the folder_id column that Alembic
|
||||
-- migration 0139 adds on the core path. Idempotent so both install paths
|
||||
-- converge to the identical schema.
|
||||
ALTER TABLE report_templates ADD COLUMN IF NOT EXISTS folder_id UUID;
|
||||
CREATE INDEX IF NOT EXISTS ix_report_templates_folder ON report_templates(folder_id);
|
||||
@@ -24,7 +24,7 @@ class ReportGeneratorPlugin(BasePlugin):
|
||||
),
|
||||
],
|
||||
events=["report.requested", "report.generated"],
|
||||
migrations=["0001_initial.sql"],
|
||||
migrations=["0001_initial.sql", "0002_reports_folder_id.sql"],
|
||||
permissions=["reports:read", "reports:generate", "reports:manage_templates"],
|
||||
menu_items=[
|
||||
FrontendMenuItem(label_key='nav.reports', label='Berichte', path='/reports', icon='BarChart3', order=70),
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
-- Dual-path convergence (Gate B): apply the tag tree structure that
|
||||
-- Alembic migration 0138 adds on the core path. Idempotent so both install
|
||||
-- paths converge to the identical schema.
|
||||
ALTER TABLE tags ADD COLUMN IF NOT EXISTS parent_id UUID;
|
||||
CREATE INDEX IF NOT EXISTS ix_tags_parent ON tags(parent_id);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_tags_parent_id'
|
||||
) THEN
|
||||
ALTER TABLE tags ADD CONSTRAINT fk_tags_parent_id
|
||||
FOREIGN KEY (parent_id) REFERENCES tags(id) ON DELETE SET NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
ALTER TABLE tags ADD COLUMN IF NOT EXISTS applicable_to JSONB;
|
||||
ALTER TABLE tags ADD COLUMN IF NOT EXISTS icon VARCHAR(50);
|
||||
@@ -23,7 +23,7 @@ class TagsPlugin(BasePlugin):
|
||||
),
|
||||
],
|
||||
events=[],
|
||||
migrations=["0001_initial.sql", "0002_add_deleted_at.sql"],
|
||||
migrations=["0001_initial.sql", "0002_add_deleted_at.sql", "0003_tree_structure.sql"],
|
||||
permissions=[
|
||||
"tags:read",
|
||||
"tags:write",
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
-- Dual-path convergence (Gate B): apply the unified task system that
|
||||
-- Alembic migrations 0124 (columns/indexes/FK) and 0127 (drop legacy FK)
|
||||
-- create on the core path. Idempotent so both install paths converge to
|
||||
-- the identical schema. The end state has NO foreign key on contact_id.
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS assignee_type VARCHAR(20) NOT NULL DEFAULT 'user';
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS assignee_id UUID;
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS entity_type VARCHAR(80);
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS entity_id UUID;
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS creator_type VARCHAR(20) NOT NULL DEFAULT 'user';
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS creator_id UUID;
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS parent_task_id UUID;
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS depends_on JSONB NOT NULL DEFAULT '[]'::jsonb;
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS task_type VARCHAR(30) NOT NULL DEFAULT 'todo';
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS success_criteria JSONB;
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS target_date TIMESTAMPTZ;
|
||||
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS progress INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_tasks_tenant_entity ON tasks(tenant_id, entity_type, entity_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_tasks_tenant_assignee ON tasks(tenant_id, assignee_type, assignee_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_tasks_tenant_parent ON tasks(tenant_id, parent_task_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_tasks_tenant_type ON tasks(tenant_id, task_type);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_tasks_parent_task_id'
|
||||
) THEN
|
||||
ALTER TABLE tasks ADD CONSTRAINT fk_tasks_parent_task_id
|
||||
FOREIGN KEY (parent_task_id) REFERENCES tasks(id) ON DELETE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
@@ -29,7 +29,7 @@ class TasksPlugin(BasePlugin):
|
||||
),
|
||||
],
|
||||
events=[],
|
||||
migrations=["0001_initial.sql"],
|
||||
migrations=["0001_initial.sql", "0002_unified_task_system.sql"],
|
||||
permissions=[
|
||||
"tasks:read",
|
||||
"tasks:write",
|
||||
|
||||
Reference in New Issue
Block a user