-- AP0.4: Feature, Prompt, Placeholder and Configuration registries CREATE TABLE features ( feature_key VARCHAR(128) PRIMARY KEY, module VARCHAR(64) NOT NULL, name VARCHAR(255) NOT NULL, description TEXT NOT NULL DEFAULT '', is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE prompt_definitions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), prompt_key VARCHAR(128) NOT NULL UNIQUE, name VARCHAR(255) NOT NULL, purpose TEXT NOT NULL DEFAULT '', context_kind VARCHAR(64) NOT NULL, execution_mode VARCHAR(32) NOT NULL DEFAULT 'single' CHECK (execution_mode IN ('single', 'pipeline', 'workflow')), status VARCHAR(32) NOT NULL DEFAULT 'active' CHECK (status IN ('draft', 'active', 'archived')), active_version_id UUID, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE prompt_versions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), prompt_definition_id UUID NOT NULL REFERENCES prompt_definitions(id) ON DELETE CASCADE, version VARCHAR(64) NOT NULL, body TEXT NOT NULL DEFAULT '', input_schema JSONB, output_schema JSONB, model_policy_key VARCHAR(128), created_by UUID REFERENCES users(id) ON DELETE SET NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), changelog TEXT NOT NULL DEFAULT '', UNIQUE (prompt_definition_id, version) ); ALTER TABLE prompt_definitions ADD CONSTRAINT fk_prompt_definitions_active_version FOREIGN KEY (active_version_id) REFERENCES prompt_versions(id) ON DELETE SET NULL; CREATE TABLE prompt_steps ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), prompt_version_id UUID NOT NULL REFERENCES prompt_versions(id) ON DELETE CASCADE, step_key VARCHAR(128) NOT NULL, step_order INT NOT NULL DEFAULT 0, step_type VARCHAR(32) NOT NULL DEFAULT 'template' CHECK (step_type IN ('template', 'resolver', 'llm_call', 'postprocess', 'validation')), template_body TEXT NOT NULL DEFAULT '', input_mapping JSONB, output_mapping JSONB, enabled BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE (prompt_version_id, step_key) ); CREATE INDEX idx_prompt_steps_version_order ON prompt_steps(prompt_version_id, step_order); CREATE TABLE placeholder_definitions ( placeholder_key VARCHAR(128) NOT NULL, context_kind VARCHAR(64) NOT NULL, value_type VARCHAR(32) NOT NULL DEFAULT 'string' CHECK (value_type IN ('string', 'number', 'boolean', 'object', 'array', 'json')), description TEXT NOT NULL DEFAULT '', required BOOLEAN NOT NULL DEFAULT FALSE, source VARCHAR(64) NOT NULL DEFAULT 'input', is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), PRIMARY KEY (placeholder_key, context_kind) ); CREATE TABLE configuration_entries ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), config_key VARCHAR(128) NOT NULL, scope VARCHAR(32) NOT NULL DEFAULT 'global' CHECK (scope IN ('global', 'tenant')), tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE, value JSONB NOT NULL DEFAULT '{}', value_type VARCHAR(32) NOT NULL DEFAULT 'string' CHECK (value_type IN ('string', 'number', 'boolean', 'object', 'array', 'json')), description TEXT NOT NULL DEFAULT '', is_secret BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CHECK ( (scope = 'global' AND tenant_id IS NULL) OR (scope = 'tenant' AND tenant_id IS NOT NULL) ) ); CREATE UNIQUE INDEX uq_configuration_entries_global ON configuration_entries (config_key) WHERE scope = 'global'; CREATE UNIQUE INDEX uq_configuration_entries_tenant ON configuration_entries (config_key, tenant_id) WHERE scope = 'tenant'; CREATE TABLE prompt_execution_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), prompt_definition_id UUID REFERENCES prompt_definitions(id) ON DELETE SET NULL, prompt_version_id UUID REFERENCES prompt_versions(id) ON DELETE SET NULL, execution_mode VARCHAR(32) NOT NULL, status VARCHAR(32) NOT NULL CHECK (status IN ('success', 'error', 'skipped')), rendered_preview TEXT, input_summary JSONB, error_message TEXT, created_by UUID REFERENCES users(id) ON DELETE SET NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_prompt_execution_logs_created ON prompt_execution_logs(created_at DESC);