step 4: fresh kernel-only migrations
Deleted all 23+23 old chat-switchboard migration files. Wrote 9+9 clean kernel-only migrations in postgres/ and sqlite/ subdirs. 27 tables per dialect covering all 20 store interfaces: 001: users, refresh_tokens, policies, settings, presence, oidc 002: teams, team_members, groups, group_members 003: packages, package_user_settings, ext_permissions, ext_data_tables 004: ext_connections, ext_dependencies, resource_grants 005: notifications, notification_preferences 006: audit_log 007: workflows, workflow_stages, workflow_versions 008: tasks, task_runs 009: ws_tickets, rate_limit_counters Dropped: providers, personas, channels, messages, knowledge, notes, memory, workspaces, projects, folders, files, usage_log, tool_health, workflow_assignments, ext_view_channels. Schema changes vs old: - pgvector extension removed (no KB embeddings) - resource_grants: resource_type CHECK removed (open-ended) - workflow_stages: persona_id kept as nullable TEXT (no FK) - workflow_stages: stage_mode default=form_only, added custom - tasks: dropped output_channel_id, provider_config_id columns - tasks: task_type removed prompt, output_mode: notification|webhook|log - task_runs: dropped channel_id - platform_policies: kernel-only seeds - global_settings: kernel-only seeds, site name=Switchboard Core - Everyone group: kernel permissions (extension.use, workflow.submit) -2815/+487 lines.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
-- ==========================================
|
||||
-- Chat Switchboard — 001 Core (SQLite)
|
||||
-- Switchboard Core — 001 Core (SQLite)
|
||||
-- ==========================================
|
||||
-- Consolidated v0.28.0
|
||||
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA foreign_keys = ON;
|
||||
@@ -59,13 +58,8 @@ CREATE TABLE IF NOT EXISTS platform_policies (
|
||||
);
|
||||
|
||||
INSERT OR IGNORE INTO platform_policies (key, value) VALUES
|
||||
('allow_user_byok', 'false'),
|
||||
('allow_user_personas', 'false'),
|
||||
('allow_raw_model_access', 'true'),
|
||||
('allow_registration', 'true'),
|
||||
('default_user_active', 'false'),
|
||||
('allow_team_providers', 'true'),
|
||||
('kb_direct_access', 'true');
|
||||
('allow_registration', 'true'),
|
||||
('default_user_active', 'false');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS global_settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
@@ -76,15 +70,23 @@ CREATE TABLE IF NOT EXISTS global_settings (
|
||||
|
||||
INSERT OR IGNORE INTO global_settings (key, value) VALUES
|
||||
('registration', '{"enabled": true}'),
|
||||
('site', '{"name": "Chat Switchboard", "tagline": "Multi-Model AI Chat"}'),
|
||||
('banner', '{"enabled": false, "text": "", "bg": "#007a33", "fg": "#ffffff"}'),
|
||||
('model_roles', '{"utility":{"primary":null,"fallback":null},"embedding":{"primary":null,"fallback":null},"generation":{"primary":null,"fallback":null}}'),
|
||||
('retention_ttl_days', '{"value": 0}');
|
||||
('site', '{"name": "Switchboard Core", "tagline": "Extension Platform"}'),
|
||||
('banner', '{"enabled": false, "text": "", "bg": "#007a33", "fg": "#ffffff"}');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_presence (
|
||||
user_id TEXT PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||
last_seen TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
status TEXT NOT NULL DEFAULT 'online'
|
||||
CHECK (status IN ('online', 'away', 'offline'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_user_presence_last_seen ON user_presence(last_seen DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_presence_last_seen ON user_presence(last_seen);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS oidc_auth_state (
|
||||
state TEXT PRIMARY KEY,
|
||||
nonce TEXT NOT NULL,
|
||||
redirect_to TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_oidc_state_created ON oidc_auth_state(created_at);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
-- Chat Switchboard — 002 Teams & Access Control (SQLite)
|
||||
-- Consolidated v0.28.0
|
||||
-- ==========================================
|
||||
-- Switchboard Core — 002 Teams & Access Control (SQLite)
|
||||
-- ==========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS teams (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT DEFAULT '',
|
||||
created_by TEXT NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
|
||||
created_by TEXT NOT NULL REFERENCES users(id),
|
||||
is_active INTEGER DEFAULT 1,
|
||||
settings TEXT DEFAULT '{}',
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
@@ -14,6 +15,10 @@ CREATE TABLE IF NOT EXISTS teams (
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_teams_active ON teams(is_active);
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS teams_updated_at AFTER UPDATE ON teams
|
||||
FOR EACH ROW WHEN NEW.updated_at = OLD.updated_at
|
||||
BEGIN UPDATE teams SET updated_at = datetime('now') WHERE id = NEW.id; END;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS team_members (
|
||||
id TEXT PRIMARY KEY,
|
||||
team_id TEXT NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
|
||||
@@ -43,7 +48,11 @@ CREATE TABLE IF NOT EXISTS groups (
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_groups_name_scope
|
||||
ON groups(name, COALESCE(team_id, ''));
|
||||
ON groups(name, COALESCE(team_id, '00000000-0000-0000-0000-000000000000'));
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS groups_updated_at AFTER UPDATE ON groups
|
||||
FOR EACH ROW WHEN NEW.updated_at = OLD.updated_at
|
||||
BEGIN UPDATE groups SET updated_at = datetime('now') WHERE id = NEW.id; END;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS group_members (
|
||||
id TEXT PRIMARY KEY,
|
||||
@@ -57,13 +66,11 @@ CREATE TABLE IF NOT EXISTS group_members (
|
||||
CREATE INDEX IF NOT EXISTS idx_group_members_group ON group_members(group_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_group_members_user ON group_members(user_id);
|
||||
|
||||
INSERT OR IGNORE INTO groups
|
||||
(id, name, description, scope, created_by, source, permissions, created_at, updated_at)
|
||||
INSERT OR IGNORE INTO groups (id, name, description, scope, created_by, source, permissions)
|
||||
VALUES (
|
||||
'00000000-0000-0000-0000-000000000001',
|
||||
'Everyone',
|
||||
'Implicit group — all authenticated users receive these permissions.',
|
||||
'global', NULL, 'system',
|
||||
'["model.use","kb.read","channel.create"]',
|
||||
datetime('now'), datetime('now')
|
||||
'["extension.use","workflow.submit"]'
|
||||
);
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
-- Chat Switchboard — 016 Packages (SQLite)
|
||||
-- Unified package registry. Replaces surface_registry + extensions.
|
||||
-- v0.28.7: packages + package_user_settings
|
||||
-- v0.29.0: status column + extension_permissions table
|
||||
-- v0.29.2: ext_data_tables catalog + platform read views
|
||||
-- ==========================================
|
||||
-- Switchboard Core — 003 Packages & Extensions (SQLite)
|
||||
-- ==========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS packages (
|
||||
id TEXT PRIMARY KEY,
|
||||
title TEXT NOT NULL,
|
||||
type TEXT NOT NULL DEFAULT 'surface'
|
||||
CHECK (type IN ('surface', 'extension', 'full', 'workflow')),
|
||||
CHECK (type IN ('surface', 'extension', 'full', 'workflow', 'library')),
|
||||
version TEXT NOT NULL DEFAULT '0.0.0',
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
author TEXT NOT NULL DEFAULT '',
|
||||
@@ -37,20 +35,14 @@ CREATE INDEX IF NOT EXISTS idx_packages_team ON packages(team_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_packages_source ON packages(source);
|
||||
CREATE INDEX IF NOT EXISTS idx_packages_status ON packages(status);
|
||||
|
||||
|
||||
-- Per-user overrides for packages (enable/disable, custom config).
|
||||
|
||||
CREATE TABLE IF NOT EXISTS package_user_settings (
|
||||
package_id TEXT NOT NULL REFERENCES packages(id) ON DELETE CASCADE,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
settings TEXT NOT NULL DEFAULT '{}',
|
||||
settings TEXT NOT NULL DEFAULT '{}',
|
||||
is_enabled INTEGER NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (package_id, user_id)
|
||||
);
|
||||
|
||||
|
||||
-- Extension permissions (v0.29.0)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS extension_permissions (
|
||||
id TEXT PRIMARY KEY,
|
||||
package_id TEXT NOT NULL REFERENCES packages(id) ON DELETE CASCADE,
|
||||
@@ -65,10 +57,6 @@ CREATE TABLE IF NOT EXISTS extension_permissions (
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_perm_package ON extension_permissions(package_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_perm_granted ON extension_permissions(granted);
|
||||
|
||||
|
||||
-- Extension data tables catalog (v0.29.2)
|
||||
-- Tracks namespaced tables created by extension install hooks.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ext_data_tables (
|
||||
package_id TEXT NOT NULL REFERENCES packages(id) ON DELETE CASCADE,
|
||||
table_name TEXT NOT NULL,
|
||||
@@ -78,14 +66,5 @@ CREATE TABLE IF NOT EXISTS ext_data_tables (
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_data_tables_pkg ON ext_data_tables(package_id);
|
||||
|
||||
|
||||
-- Platform views — column-allowlisted read access for extensions (v0.29.2)
|
||||
-- Extensions query these via db.view("users"), db.view("channels").
|
||||
|
||||
DROP VIEW IF EXISTS ext_view_users;
|
||||
CREATE VIEW ext_view_users AS
|
||||
CREATE VIEW IF NOT EXISTS ext_view_users AS
|
||||
SELECT id, display_name, email FROM users;
|
||||
|
||||
DROP VIEW IF EXISTS ext_view_channels;
|
||||
CREATE VIEW ext_view_channels AS
|
||||
SELECT id, title, type, team_id FROM channels;
|
||||
@@ -1,110 +0,0 @@
|
||||
-- Chat Switchboard — 003 Providers & Routing (SQLite)
|
||||
-- Consolidated v0.28.0: adds capability_match policy type
|
||||
|
||||
CREATE TABLE IF NOT EXISTS provider_configs (
|
||||
id TEXT PRIMARY KEY,
|
||||
scope TEXT NOT NULL CHECK (scope IN ('global', 'team', 'personal')),
|
||||
owner_id TEXT,
|
||||
name TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
endpoint TEXT NOT NULL,
|
||||
api_key_enc BLOB,
|
||||
key_nonce BLOB,
|
||||
key_scope TEXT NOT NULL DEFAULT 'global',
|
||||
model_default TEXT,
|
||||
config TEXT DEFAULT '{}',
|
||||
headers TEXT DEFAULT '{}',
|
||||
settings TEXT DEFAULT '{}',
|
||||
is_active INTEGER DEFAULT 1,
|
||||
is_private INTEGER DEFAULT 0,
|
||||
proxy_mode TEXT NOT NULL DEFAULT 'system' CHECK (proxy_mode IN ('system', 'direct', 'custom')),
|
||||
proxy_url TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_configs_scope ON provider_configs(scope);
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_configs_owner ON provider_configs(owner_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_configs_active ON provider_configs(is_active);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS model_catalog (
|
||||
id TEXT PRIMARY KEY,
|
||||
provider_config_id TEXT NOT NULL REFERENCES provider_configs(id) ON DELETE CASCADE,
|
||||
model_id TEXT NOT NULL,
|
||||
display_name TEXT,
|
||||
model_type TEXT DEFAULT 'chat',
|
||||
capabilities TEXT NOT NULL DEFAULT '{}',
|
||||
pricing TEXT,
|
||||
visibility TEXT DEFAULT 'disabled' CHECK (visibility IN ('enabled', 'disabled', 'team')),
|
||||
last_synced_at TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now')),
|
||||
UNIQUE(provider_config_id, model_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_model_catalog_provider ON model_catalog(provider_config_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_model_catalog_enabled ON model_catalog(visibility);
|
||||
CREATE INDEX IF NOT EXISTS idx_model_catalog_type ON model_catalog(model_type);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS model_pricing (
|
||||
id TEXT PRIMARY KEY,
|
||||
provider_config_id TEXT NOT NULL REFERENCES provider_configs(id) ON DELETE CASCADE,
|
||||
model_id TEXT NOT NULL,
|
||||
input_per_m REAL,
|
||||
output_per_m REAL,
|
||||
cache_create_per_m REAL,
|
||||
cache_read_per_m REAL,
|
||||
currency TEXT NOT NULL DEFAULT 'USD',
|
||||
source TEXT NOT NULL DEFAULT 'manual',
|
||||
updated_at TEXT DEFAULT (datetime('now')),
|
||||
updated_by TEXT REFERENCES users(id),
|
||||
UNIQUE(provider_config_id, model_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS provider_health (
|
||||
id TEXT PRIMARY KEY,
|
||||
provider_config_id TEXT NOT NULL REFERENCES provider_configs(id) ON DELETE CASCADE,
|
||||
window_start TEXT NOT NULL,
|
||||
request_count INTEGER NOT NULL DEFAULT 0,
|
||||
error_count INTEGER NOT NULL DEFAULT 0,
|
||||
timeout_count INTEGER NOT NULL DEFAULT 0,
|
||||
total_latency_ms INTEGER NOT NULL DEFAULT 0,
|
||||
max_latency_ms INTEGER NOT NULL DEFAULT 0,
|
||||
rate_limit_count INTEGER NOT NULL DEFAULT 0,
|
||||
last_error TEXT,
|
||||
last_error_at TEXT,
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
UNIQUE (provider_config_id, window_start)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_health_window
|
||||
ON provider_health (provider_config_id, window_start DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS capability_overrides (
|
||||
id TEXT PRIMARY KEY,
|
||||
provider_config_id TEXT REFERENCES provider_configs(id) ON DELETE CASCADE,
|
||||
model_id TEXT NOT NULL,
|
||||
field TEXT NOT NULL,
|
||||
value TEXT NOT NULL,
|
||||
set_by TEXT REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
UNIQUE (provider_config_id, model_id, field)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_capability_overrides_model ON capability_overrides(model_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS routing_policies (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
scope TEXT NOT NULL DEFAULT 'global' CHECK (scope IN ('global', 'team')),
|
||||
team_id TEXT REFERENCES teams(id) ON DELETE CASCADE,
|
||||
priority INTEGER NOT NULL DEFAULT 100,
|
||||
policy_type TEXT NOT NULL
|
||||
CHECK (policy_type IN ('provider_prefer', 'team_route', 'cost_limit', 'model_alias', 'capability_match')),
|
||||
config TEXT NOT NULL DEFAULT '{}',
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_routing_policies_active ON routing_policies(is_active, priority);
|
||||
59
server/database/migrations/sqlite/004_connections.sql
Normal file
59
server/database/migrations/sqlite/004_connections.sql
Normal file
@@ -0,0 +1,59 @@
|
||||
-- ==========================================
|
||||
-- Switchboard Core — 004 Connections & Dependencies (SQLite)
|
||||
-- ==========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ext_connections (
|
||||
id TEXT PRIMARY KEY,
|
||||
type TEXT NOT NULL,
|
||||
package_id TEXT NOT NULL,
|
||||
scope TEXT NOT NULL CHECK (scope IN ('global', 'team', 'personal')),
|
||||
owner_id TEXT NOT NULL DEFAULT '',
|
||||
name TEXT NOT NULL,
|
||||
config TEXT NOT NULL DEFAULT '{}',
|
||||
is_active INTEGER DEFAULT 1,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now')),
|
||||
UNIQUE(type, scope, owner_id, name)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_connections_type ON ext_connections(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_connections_scope ON ext_connections(scope);
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_connections_owner ON ext_connections(owner_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_connections_active ON ext_connections(is_active);
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS ext_connections_updated_at AFTER UPDATE ON ext_connections
|
||||
FOR EACH ROW WHEN NEW.updated_at = OLD.updated_at
|
||||
BEGIN UPDATE ext_connections SET updated_at = datetime('now') WHERE id = NEW.id; END;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ext_dependencies (
|
||||
consumer_id TEXT NOT NULL,
|
||||
library_id TEXT NOT NULL,
|
||||
version_spec TEXT NOT NULL DEFAULT '>=0.0.0',
|
||||
resolved_ver TEXT NOT NULL DEFAULT '0.0.0',
|
||||
PRIMARY KEY (consumer_id, library_id),
|
||||
FOREIGN KEY (consumer_id) REFERENCES packages(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (library_id) REFERENCES packages(id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_deps_consumer ON ext_dependencies(consumer_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_deps_library ON ext_dependencies(library_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS resource_grants (
|
||||
id TEXT PRIMARY KEY,
|
||||
resource_type TEXT NOT NULL,
|
||||
resource_id TEXT NOT NULL,
|
||||
grant_scope TEXT NOT NULL DEFAULT 'team_only'
|
||||
CHECK (grant_scope IN ('team_only', 'global', 'groups')),
|
||||
granted_groups TEXT NOT NULL DEFAULT '[]',
|
||||
created_by TEXT NOT NULL REFERENCES users(id),
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now')),
|
||||
UNIQUE(resource_type, resource_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_resource_grants_resource
|
||||
ON resource_grants(resource_type, resource_id);
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS resource_grants_updated_at AFTER UPDATE ON resource_grants
|
||||
FOR EACH ROW WHEN NEW.updated_at = OLD.updated_at
|
||||
BEGIN UPDATE resource_grants SET updated_at = datetime('now') WHERE id = NEW.id; END;
|
||||
@@ -1,83 +0,0 @@
|
||||
-- Chat Switchboard — 004 Personas & Grants (SQLite)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS personas (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
handle TEXT,
|
||||
description TEXT DEFAULT '',
|
||||
icon TEXT DEFAULT '',
|
||||
avatar TEXT DEFAULT '',
|
||||
base_model_id TEXT NOT NULL,
|
||||
provider_config_id TEXT REFERENCES provider_configs(id) ON DELETE SET NULL,
|
||||
system_prompt TEXT DEFAULT '',
|
||||
temperature REAL,
|
||||
max_tokens INTEGER,
|
||||
thinking_budget INTEGER,
|
||||
top_p REAL,
|
||||
memory_enabled INTEGER NOT NULL DEFAULT 1,
|
||||
memory_extraction_prompt TEXT,
|
||||
scope TEXT NOT NULL CHECK (scope IN ('global', 'team', 'personal')),
|
||||
owner_id TEXT,
|
||||
created_by TEXT NOT NULL REFERENCES users(id),
|
||||
is_active INTEGER DEFAULT 1,
|
||||
is_shared INTEGER DEFAULT 0,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_personas_scope ON personas(scope);
|
||||
CREATE INDEX IF NOT EXISTS idx_personas_owner ON personas(owner_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_personas_active ON personas(is_active);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_personas_handle ON personas(handle) WHERE handle IS NOT NULL;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS persona_groups (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT DEFAULT '',
|
||||
owner_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
scope TEXT NOT NULL DEFAULT 'personal' CHECK (scope IN ('global', 'team', 'personal')),
|
||||
team_id TEXT REFERENCES teams(id) ON DELETE CASCADE,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_persona_groups_owner ON persona_groups(owner_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS persona_group_members (
|
||||
id TEXT PRIMARY KEY,
|
||||
group_id TEXT NOT NULL REFERENCES persona_groups(id) ON DELETE CASCADE,
|
||||
persona_id TEXT NOT NULL REFERENCES personas(id) ON DELETE CASCADE,
|
||||
is_leader INTEGER NOT NULL DEFAULT 0,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
UNIQUE(group_id, persona_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_persona_group_members_group ON persona_group_members(group_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS persona_grants (
|
||||
id TEXT PRIMARY KEY,
|
||||
persona_id TEXT NOT NULL REFERENCES personas(id) ON DELETE CASCADE,
|
||||
grant_type TEXT NOT NULL,
|
||||
grant_ref TEXT NOT NULL,
|
||||
config TEXT DEFAULT '{}',
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
UNIQUE(persona_id, grant_type, grant_ref)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_persona_grants_persona ON persona_grants(persona_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_persona_grants_type ON persona_grants(grant_type);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS resource_grants (
|
||||
id TEXT PRIMARY KEY,
|
||||
resource_type TEXT NOT NULL CHECK (resource_type IN ('persona', 'knowledge_base', 'project')),
|
||||
resource_id TEXT NOT NULL,
|
||||
grant_scope TEXT NOT NULL DEFAULT 'team_only'
|
||||
CHECK (grant_scope IN ('team_only', 'global', 'groups')),
|
||||
granted_groups TEXT NOT NULL DEFAULT '[]',
|
||||
created_by TEXT NOT NULL REFERENCES users(id),
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now')),
|
||||
UNIQUE(resource_type, resource_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_resource_grants_resource ON resource_grants(resource_type, resource_id);
|
||||
@@ -1,160 +0,0 @@
|
||||
-- Chat Switchboard — 005 Channels & Conversations (SQLite)
|
||||
-- Consolidated v0.28.0
|
||||
|
||||
CREATE TABLE IF NOT EXISTS folders (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
parent_id TEXT REFERENCES folders(id) ON DELETE CASCADE,
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now')),
|
||||
UNIQUE(user_id, name, parent_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_folders_user ON folders(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_folders_parent ON folders(parent_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS channels (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT REFERENCES users(id) ON DELETE CASCADE,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
type TEXT DEFAULT 'direct'
|
||||
CHECK (type IN ('direct', 'dm', 'group', 'channel', 'workflow', 'service')),
|
||||
model TEXT,
|
||||
system_prompt TEXT,
|
||||
provider_config_id TEXT REFERENCES provider_configs(id) ON DELETE SET NULL,
|
||||
is_archived INTEGER DEFAULT 0,
|
||||
is_pinned INTEGER DEFAULT 0,
|
||||
folder_id TEXT REFERENCES folders(id) ON DELETE SET NULL,
|
||||
folder TEXT,
|
||||
team_id TEXT REFERENCES teams(id) ON DELETE SET NULL,
|
||||
settings TEXT DEFAULT '{}',
|
||||
tags TEXT DEFAULT '[]',
|
||||
ai_mode TEXT NOT NULL DEFAULT 'auto',
|
||||
topic TEXT,
|
||||
allow_anonymous INTEGER NOT NULL DEFAULT 0,
|
||||
workflow_id TEXT,
|
||||
workflow_version INTEGER,
|
||||
current_stage INTEGER DEFAULT 0,
|
||||
stage_data TEXT DEFAULT '{}',
|
||||
workflow_status TEXT DEFAULT 'active'
|
||||
CHECK (workflow_status IN ('active', 'completed', 'stale', 'cancelled')),
|
||||
last_activity_at TEXT DEFAULT (datetime('now')),
|
||||
stage_entered_at TEXT,
|
||||
kb_auto_inject INTEGER NOT NULL DEFAULT 0,
|
||||
project_id TEXT,
|
||||
workspace_id TEXT,
|
||||
purge_after TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_channels_user ON channels(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_channels_updated ON channels(updated_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_channels_type ON channels(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_channels_team ON channels(team_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_channels_folder ON channels(folder_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_channels_project ON channels(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_channels_workspace ON channels(workspace_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_channels_workflow ON channels(workflow_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id TEXT PRIMARY KEY,
|
||||
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
|
||||
role TEXT NOT NULL CHECK (role IN ('user', 'assistant', 'system', 'tool')),
|
||||
content TEXT NOT NULL,
|
||||
model TEXT,
|
||||
tokens_used INTEGER,
|
||||
tool_calls TEXT,
|
||||
metadata TEXT DEFAULT '{}',
|
||||
parent_id TEXT REFERENCES messages(id) ON DELETE SET NULL,
|
||||
sibling_index INTEGER DEFAULT 0,
|
||||
participant_type TEXT DEFAULT 'user',
|
||||
participant_id TEXT,
|
||||
provider_config_id TEXT REFERENCES provider_configs(id) ON DELETE SET NULL,
|
||||
deleted_at TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_channel ON messages(channel_id, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_parent ON messages(parent_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS channel_participants (
|
||||
id TEXT PRIMARY KEY,
|
||||
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
|
||||
participant_type TEXT NOT NULL DEFAULT 'user'
|
||||
CHECK (participant_type IN ('user', 'persona', 'session')),
|
||||
participant_id TEXT NOT NULL,
|
||||
role TEXT NOT NULL DEFAULT 'member'
|
||||
CHECK (role IN ('owner', 'member', 'observer')),
|
||||
display_name TEXT,
|
||||
avatar_url TEXT,
|
||||
joined_at TEXT DEFAULT (datetime('now')),
|
||||
last_read_at TEXT DEFAULT (datetime('now')),
|
||||
last_read_message_id TEXT,
|
||||
UNIQUE(channel_id, participant_type, participant_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_channel_participants_channel ON channel_participants(channel_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_channel_participants_ref ON channel_participants(participant_type, participant_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS channel_models (
|
||||
id TEXT PRIMARY KEY,
|
||||
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
|
||||
model_id TEXT NOT NULL,
|
||||
provider_config_id TEXT REFERENCES provider_configs(id) ON DELETE SET NULL,
|
||||
persona_id TEXT REFERENCES personas(id) ON DELETE SET NULL,
|
||||
display_name TEXT,
|
||||
system_prompt TEXT,
|
||||
settings TEXT DEFAULT '{}',
|
||||
is_default INTEGER DEFAULT 0,
|
||||
added_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_channel_models_raw
|
||||
ON channel_models(channel_id, model_id, provider_config_id) WHERE persona_id IS NULL;
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_channel_models_persona
|
||||
ON channel_models(channel_id, persona_id) WHERE persona_id IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_channel_models_channel ON channel_models(channel_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS channel_cursors (
|
||||
id TEXT PRIMARY KEY,
|
||||
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
active_leaf_id TEXT REFERENCES messages(id) ON DELETE SET NULL,
|
||||
updated_at TEXT DEFAULT (datetime('now')),
|
||||
UNIQUE(channel_id, user_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_channel_cursors_channel ON channel_cursors(channel_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_channel_cursors_user ON channel_cursors(user_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_model_settings (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
model_id TEXT NOT NULL,
|
||||
provider_config_id TEXT NOT NULL REFERENCES provider_configs(id) ON DELETE CASCADE,
|
||||
hidden INTEGER DEFAULT 0,
|
||||
preferred_temperature REAL,
|
||||
preferred_max_tokens INTEGER,
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now')),
|
||||
UNIQUE(user_id, model_id, provider_config_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_user_model_settings_user ON user_model_settings(user_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS session_participants (
|
||||
id TEXT PRIMARY KEY,
|
||||
session_token TEXT NOT NULL UNIQUE,
|
||||
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
|
||||
display_name TEXT NOT NULL DEFAULT 'Visitor',
|
||||
fingerprint TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_session_participants_channel ON session_participants(channel_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_session_participants_token ON session_participants(session_token);
|
||||
@@ -1,4 +1,6 @@
|
||||
-- Chat Switchboard — 011 Notifications (SQLite)
|
||||
-- ==========================================
|
||||
-- Switchboard Core — 005 Notifications (SQLite)
|
||||
-- ==========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS notifications (
|
||||
id TEXT PRIMARY KEY,
|
||||
@@ -12,8 +14,10 @@ CREATE TABLE IF NOT EXISTS notifications (
|
||||
created_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_notifications_user_unread ON notifications(user_id, is_read, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_notifications_user_created ON notifications(user_id, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_notifications_user_unread
|
||||
ON notifications(user_id, is_read, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_notifications_user_created
|
||||
ON notifications(user_id, created_at);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS notification_preferences (
|
||||
id TEXT PRIMARY KEY,
|
||||
20
server/database/migrations/sqlite/006_audit.sql
Normal file
20
server/database/migrations/sqlite/006_audit.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
-- ==========================================
|
||||
-- Switchboard Core — 006 Audit (SQLite)
|
||||
-- ==========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS audit_log (
|
||||
id TEXT PRIMARY KEY,
|
||||
actor_id TEXT REFERENCES users(id) ON DELETE SET NULL,
|
||||
action TEXT NOT NULL,
|
||||
resource_type TEXT NOT NULL,
|
||||
resource_id TEXT,
|
||||
metadata TEXT DEFAULT '{}',
|
||||
ip_address TEXT,
|
||||
user_agent TEXT DEFAULT '',
|
||||
created_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_log_created ON audit_log(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_log_actor ON audit_log(actor_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_log_resource ON audit_log(resource_type, resource_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_log_action ON audit_log(action);
|
||||
@@ -1,73 +0,0 @@
|
||||
-- Chat Switchboard — 006 Knowledge Bases (SQLite)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS knowledge_bases (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
scope TEXT NOT NULL DEFAULT 'global',
|
||||
owner_id TEXT REFERENCES users(id) ON DELETE CASCADE,
|
||||
team_id TEXT REFERENCES teams(id) ON DELETE CASCADE,
|
||||
embedding_config TEXT NOT NULL DEFAULT '{}',
|
||||
document_count INTEGER NOT NULL DEFAULT 0,
|
||||
chunk_count INTEGER NOT NULL DEFAULT 0,
|
||||
total_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
discoverable INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_kb_scope ON knowledge_bases(scope);
|
||||
CREATE INDEX IF NOT EXISTS idx_kb_owner ON knowledge_bases(owner_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_kb_team ON knowledge_bases(team_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS kb_documents (
|
||||
id TEXT PRIMARY KEY,
|
||||
kb_id TEXT NOT NULL REFERENCES knowledge_bases(id) ON DELETE CASCADE,
|
||||
filename TEXT NOT NULL,
|
||||
content_type TEXT NOT NULL,
|
||||
size_bytes INTEGER NOT NULL,
|
||||
storage_key TEXT NOT NULL,
|
||||
extracted_text TEXT,
|
||||
chunk_count INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
error TEXT,
|
||||
uploaded_by TEXT NOT NULL REFERENCES users(id),
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_kbdoc_kb ON kb_documents(kb_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS kb_chunks (
|
||||
id TEXT PRIMARY KEY,
|
||||
kb_id TEXT NOT NULL REFERENCES knowledge_bases(id) ON DELETE CASCADE,
|
||||
document_id TEXT NOT NULL REFERENCES kb_documents(id) ON DELETE CASCADE,
|
||||
chunk_index INTEGER NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
token_count INTEGER NOT NULL DEFAULT 0,
|
||||
metadata TEXT NOT NULL DEFAULT '{}',
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_kbchunk_kb ON kb_chunks(kb_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_kbchunk_doc ON kb_chunks(document_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS channel_knowledge_bases (
|
||||
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
|
||||
kb_id TEXT NOT NULL REFERENCES knowledge_bases(id) ON DELETE CASCADE,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
added_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
PRIMARY KEY (channel_id, kb_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS persona_knowledge_bases (
|
||||
persona_id TEXT NOT NULL REFERENCES personas(id) ON DELETE CASCADE,
|
||||
kb_id TEXT NOT NULL REFERENCES knowledge_bases(id) ON DELETE CASCADE,
|
||||
auto_search INTEGER NOT NULL DEFAULT 0,
|
||||
added_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
PRIMARY KEY (persona_id, kb_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_persona_kb_persona ON persona_knowledge_bases(persona_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_persona_kb_kb ON persona_knowledge_bases(kb_id);
|
||||
@@ -1,34 +0,0 @@
|
||||
-- Chat Switchboard — 007 Notes & Links (SQLite)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS notes (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
title TEXT NOT NULL,
|
||||
content TEXT DEFAULT '',
|
||||
folder_path TEXT DEFAULT '/',
|
||||
tags TEXT DEFAULT '[]',
|
||||
metadata TEXT DEFAULT '{}',
|
||||
source_channel_id TEXT REFERENCES channels(id) ON DELETE SET NULL,
|
||||
source_message_id TEXT,
|
||||
team_id TEXT REFERENCES teams(id) ON DELETE SET NULL,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_user ON notes(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_folder ON notes(user_id, folder_path);
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_updated ON notes(user_id, updated_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_team ON notes(team_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_source_msg ON notes(source_message_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS note_links (
|
||||
source_note_id TEXT NOT NULL REFERENCES notes(id) ON DELETE CASCADE,
|
||||
target_note_id TEXT REFERENCES notes(id) ON DELETE CASCADE,
|
||||
target_title TEXT NOT NULL,
|
||||
display_text TEXT,
|
||||
is_transclusion INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
PRIMARY KEY (source_note_id, target_title)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_note_links_target ON note_links(target_note_id);
|
||||
@@ -1,5 +1,6 @@
|
||||
-- Chat Switchboard — 018 Workflows (SQLite)
|
||||
-- Consolidated v0.28.0: merges 023 + 025 + 027
|
||||
-- ==========================================
|
||||
-- Switchboard Core — 007 Workflows (SQLite)
|
||||
-- ==========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS workflows (
|
||||
id TEXT PRIMARY KEY,
|
||||
@@ -22,25 +23,28 @@ CREATE TABLE IF NOT EXISTS workflows (
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_workflows_team_slug
|
||||
ON workflows(team_id, slug) WHERE team_id IS NOT NULL;
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_workflows_global_slug
|
||||
ON workflows(slug) WHERE team_id IS NULL;
|
||||
ON workflows(team_id, slug);
|
||||
CREATE INDEX IF NOT EXISTS idx_workflows_active ON workflows(is_active);
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS workflows_updated_at AFTER UPDATE ON workflows
|
||||
FOR EACH ROW WHEN NEW.updated_at = OLD.updated_at
|
||||
BEGIN UPDATE workflows SET updated_at = datetime('now') WHERE id = NEW.id; END;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS workflow_stages (
|
||||
id TEXT PRIMARY KEY,
|
||||
workflow_id TEXT NOT NULL REFERENCES workflows(id) ON DELETE CASCADE,
|
||||
ordinal INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
persona_id TEXT REFERENCES personas(id) ON DELETE SET NULL,
|
||||
persona_id TEXT,
|
||||
assignment_team_id TEXT REFERENCES teams(id) ON DELETE SET NULL,
|
||||
form_template TEXT NOT NULL DEFAULT '{}',
|
||||
stage_mode TEXT NOT NULL DEFAULT 'chat_only'
|
||||
CHECK (stage_mode IN ('chat_only', 'form_only', 'form_chat', 'review')),
|
||||
stage_mode TEXT NOT NULL DEFAULT 'form_only'
|
||||
CHECK (stage_mode IN ('form_only', 'form_chat', 'review', 'custom')),
|
||||
history_mode TEXT NOT NULL DEFAULT 'full'
|
||||
CHECK (history_mode IN ('full', 'summary', 'fresh')),
|
||||
auto_transition INTEGER NOT NULL DEFAULT 0,
|
||||
transition_rules TEXT NOT NULL DEFAULT '{}',
|
||||
surface_pkg_id TEXT,
|
||||
surface_pkg_id TEXT REFERENCES packages(id) ON DELETE SET NULL,
|
||||
sla_seconds INTEGER,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
@@ -59,22 +63,3 @@ CREATE TABLE IF NOT EXISTS workflow_versions (
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_workflow_versions_workflow
|
||||
ON workflow_versions(workflow_id, version_number);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS workflow_assignments (
|
||||
id TEXT PRIMARY KEY,
|
||||
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
|
||||
stage INTEGER NOT NULL,
|
||||
team_id TEXT NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
|
||||
assigned_to TEXT REFERENCES users(id) ON DELETE SET NULL,
|
||||
status TEXT NOT NULL DEFAULT 'unassigned'
|
||||
CHECK (status IN ('unassigned', 'claimed', 'completed')),
|
||||
review_comments TEXT NOT NULL DEFAULT '[]',
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
claimed_at TEXT,
|
||||
completed_at TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_workflow_assignments_channel
|
||||
ON workflow_assignments(channel_id, stage);
|
||||
CREATE INDEX IF NOT EXISTS idx_workflow_assignments_team_status
|
||||
ON workflow_assignments(team_id, status);
|
||||
@@ -1,45 +0,0 @@
|
||||
-- Chat Switchboard — 008 Memory (SQLite)
|
||||
-- Consolidated v0.28.0: adds last_compacted_at + decay_rate
|
||||
|
||||
CREATE TABLE IF NOT EXISTS memories (
|
||||
id TEXT PRIMARY KEY,
|
||||
scope TEXT NOT NULL CHECK (scope IN ('user', 'persona', 'persona_user')),
|
||||
owner_id TEXT NOT NULL,
|
||||
user_id TEXT,
|
||||
key TEXT NOT NULL,
|
||||
value TEXT NOT NULL,
|
||||
source_channel_id TEXT,
|
||||
confidence REAL NOT NULL DEFAULT 1.0,
|
||||
status TEXT NOT NULL DEFAULT 'active'
|
||||
CHECK (status IN ('active', 'pending_review', 'archived')),
|
||||
embedding TEXT,
|
||||
last_compacted_at TEXT,
|
||||
decay_rate REAL NOT NULL DEFAULT 0.0,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_memories_scope_owner
|
||||
ON memories(scope, owner_id, status);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_memories_persona_user
|
||||
ON memories(owner_id, user_id);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_memories_unique_key
|
||||
ON memories(scope, owner_id, COALESCE(user_id, '00000000-0000-0000-0000-000000000000'), key);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_memories_source_channel
|
||||
ON memories(source_channel_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS memory_extraction_log (
|
||||
id TEXT PRIMARY KEY,
|
||||
channel_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
last_message_id TEXT NOT NULL,
|
||||
extracted_at TEXT DEFAULT (datetime('now')),
|
||||
memory_count INTEGER NOT NULL DEFAULT 0,
|
||||
UNIQUE(channel_id, user_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_mem_extract_log_channel
|
||||
ON memory_extraction_log(channel_id);
|
||||
@@ -1,6 +1,6 @@
|
||||
-- Chat Switchboard — 019 Tasks (SQLite)
|
||||
-- Consolidated v0.28.0: merges 026 + 027
|
||||
-- v0.28.0-cs3: trigger_token, action task_type, queued run status.
|
||||
-- ==========================================
|
||||
-- Switchboard Core — 008 Tasks (SQLite)
|
||||
-- ==========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tasks (
|
||||
id TEXT PRIMARY KEY,
|
||||
@@ -8,10 +8,12 @@ CREATE TABLE IF NOT EXISTS tasks (
|
||||
team_id TEXT REFERENCES teams(id) ON DELETE SET NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT DEFAULT '',
|
||||
scope TEXT NOT NULL DEFAULT 'personal',
|
||||
task_type TEXT NOT NULL DEFAULT 'prompt',
|
||||
scope TEXT NOT NULL DEFAULT 'personal'
|
||||
CHECK (scope IN ('personal', 'team', 'global')),
|
||||
task_type TEXT NOT NULL DEFAULT 'action'
|
||||
CHECK (task_type IN ('action', 'workflow', 'system')),
|
||||
system_function TEXT DEFAULT '',
|
||||
persona_id TEXT REFERENCES personas(id) ON DELETE SET NULL,
|
||||
persona_id TEXT,
|
||||
model_id TEXT,
|
||||
system_prompt TEXT DEFAULT '',
|
||||
user_prompt TEXT DEFAULT '',
|
||||
@@ -24,11 +26,10 @@ CREATE TABLE IF NOT EXISTS tasks (
|
||||
max_tokens INTEGER NOT NULL DEFAULT 4096,
|
||||
max_tool_calls INTEGER NOT NULL DEFAULT 10,
|
||||
max_wall_clock INTEGER NOT NULL DEFAULT 300,
|
||||
output_mode TEXT NOT NULL DEFAULT 'channel',
|
||||
output_channel_id TEXT REFERENCES channels(id) ON DELETE SET NULL,
|
||||
output_mode TEXT NOT NULL DEFAULT 'log'
|
||||
CHECK (output_mode IN ('notification', 'webhook', 'log')),
|
||||
webhook_url TEXT,
|
||||
webhook_secret TEXT,
|
||||
provider_config_id TEXT REFERENCES provider_configs(id) ON DELETE SET NULL,
|
||||
notify_on_complete INTEGER NOT NULL DEFAULT 0,
|
||||
notify_on_failure INTEGER NOT NULL DEFAULT 1,
|
||||
last_run_at TEXT,
|
||||
@@ -38,16 +39,16 @@ CREATE TABLE IF NOT EXISTS tasks (
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_next_run ON tasks (next_run_at) WHERE is_active = 1;
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_owner ON tasks (owner_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_team ON tasks (team_id);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_trigger_token ON tasks (trigger_token) WHERE trigger_token IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_next_run ON tasks(next_run_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_owner ON tasks(owner_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_team ON tasks(team_id);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_trigger_token ON tasks(trigger_token);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS task_runs (
|
||||
id TEXT PRIMARY KEY,
|
||||
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
||||
channel_id TEXT REFERENCES channels(id) ON DELETE SET NULL,
|
||||
status TEXT NOT NULL DEFAULT 'running',
|
||||
status TEXT NOT NULL DEFAULT 'running'
|
||||
CHECK (status IN ('queued', 'running', 'completed', 'failed', 'budget_exceeded', 'cancelled')),
|
||||
trigger_payload TEXT,
|
||||
started_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
completed_at TEXT,
|
||||
@@ -57,5 +58,5 @@ CREATE TABLE IF NOT EXISTS task_runs (
|
||||
error TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_task_runs_task ON task_runs (task_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_task_runs_status ON task_runs (task_id, status);
|
||||
CREATE INDEX IF NOT EXISTS idx_task_runs_task ON task_runs(task_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_task_runs_status ON task_runs(task_id, status);
|
||||
21
server/database/migrations/sqlite/009_ha.sql
Normal file
21
server/database/migrations/sqlite/009_ha.sql
Normal file
@@ -0,0 +1,21 @@
|
||||
-- ==========================================
|
||||
-- Switchboard Core — 009 Multi-Replica HA (SQLite)
|
||||
-- ==========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ws_tickets (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
expires_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ws_tickets_expires ON ws_tickets(expires_at);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rate_limit_counters (
|
||||
key TEXT NOT NULL,
|
||||
window_start TEXT NOT NULL,
|
||||
tokens REAL NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (key, window_start)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_rate_limit_counters_window
|
||||
ON rate_limit_counters(window_start);
|
||||
@@ -1,69 +0,0 @@
|
||||
-- Chat Switchboard — 009 Workspaces & Git (SQLite)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS workspaces (
|
||||
id TEXT PRIMARY KEY,
|
||||
owner_type TEXT NOT NULL CHECK (owner_type IN ('user', 'project', 'channel', 'team')),
|
||||
owner_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
root_path TEXT NOT NULL,
|
||||
max_bytes INTEGER,
|
||||
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'archived', 'deleting')),
|
||||
indexing_enabled INTEGER NOT NULL DEFAULT 1,
|
||||
git_remote_url TEXT,
|
||||
git_branch TEXT,
|
||||
git_credential_id TEXT,
|
||||
git_last_sync TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_workspaces_owner ON workspaces(owner_type, owner_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_workspaces_status ON workspaces(status);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS workspace_files (
|
||||
id TEXT PRIMARY KEY,
|
||||
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
||||
path TEXT NOT NULL,
|
||||
is_directory INTEGER NOT NULL DEFAULT 0,
|
||||
content_type TEXT,
|
||||
size_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
sha256 TEXT,
|
||||
index_status TEXT DEFAULT 'pending' CHECK (index_status IN ('pending', 'indexing', 'ready', 'error', 'skipped')),
|
||||
chunk_count INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_files_path ON workspace_files(workspace_id, path);
|
||||
CREATE INDEX IF NOT EXISTS idx_workspace_files_workspace ON workspace_files(workspace_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_workspace_files_type ON workspace_files(workspace_id, content_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_workspace_files_index_status ON workspace_files(workspace_id, index_status);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS workspace_chunks (
|
||||
id TEXT PRIMARY KEY,
|
||||
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
||||
file_id TEXT NOT NULL REFERENCES workspace_files(id) ON DELETE CASCADE,
|
||||
chunk_index INTEGER NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
token_count INTEGER NOT NULL DEFAULT 0,
|
||||
metadata TEXT DEFAULT '{}',
|
||||
created_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_workspace_chunks_file ON workspace_chunks(file_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_workspace_chunks_workspace ON workspace_chunks(workspace_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS git_credentials (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL DEFAULT '',
|
||||
auth_type TEXT NOT NULL DEFAULT 'https_pat',
|
||||
encrypted_data BLOB NOT NULL DEFAULT '',
|
||||
nonce BLOB NOT NULL DEFAULT '',
|
||||
public_key TEXT NOT NULL DEFAULT '',
|
||||
fingerprint TEXT NOT NULL DEFAULT '',
|
||||
persona_id TEXT REFERENCES personas(id) ON DELETE SET NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_git_credentials_user ON git_credentials(user_id);
|
||||
@@ -1,62 +0,0 @@
|
||||
-- Chat Switchboard — 010 Projects (SQLite)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS projects (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
color TEXT,
|
||||
icon TEXT,
|
||||
scope TEXT NOT NULL DEFAULT 'personal' CHECK (scope IN ('personal', 'team', 'global')),
|
||||
owner_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
team_id TEXT REFERENCES teams(id) ON DELETE SET NULL,
|
||||
workspace_id TEXT REFERENCES workspaces(id) ON DELETE SET NULL,
|
||||
is_archived INTEGER NOT NULL DEFAULT 0,
|
||||
settings TEXT DEFAULT '{}',
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_projects_owner ON projects(owner_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_projects_team ON projects(team_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_projects_scope ON projects(scope);
|
||||
CREATE INDEX IF NOT EXISTS idx_projects_workspace ON projects(workspace_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_channels (
|
||||
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
|
||||
position INTEGER NOT NULL DEFAULT 0,
|
||||
folder TEXT,
|
||||
added_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
PRIMARY KEY (project_id, channel_id),
|
||||
UNIQUE (channel_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_project_channels_project ON project_channels(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_project_channels_channel ON project_channels(channel_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_knowledge_bases (
|
||||
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
kb_id TEXT NOT NULL REFERENCES knowledge_bases(id) ON DELETE CASCADE,
|
||||
auto_search INTEGER NOT NULL DEFAULT 0,
|
||||
added_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
PRIMARY KEY (project_id, kb_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_project_kb_project ON project_knowledge_bases(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_project_kb_kb ON project_knowledge_bases(kb_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_notes (
|
||||
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
note_id TEXT NOT NULL REFERENCES notes(id) ON DELETE CASCADE,
|
||||
added_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
PRIMARY KEY (project_id, note_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_project_notes_project ON project_notes(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_project_notes_note ON project_notes(note_id);
|
||||
|
||||
-- Cross-domain FK columns on channels (SQLite cannot ADD COLUMN with FK in all cases,
|
||||
-- so these may already exist from initial channel creation — safe to skip on error)
|
||||
-- ALTER TABLE channels ADD COLUMN project_id TEXT REFERENCES projects(id) ON DELETE SET NULL;
|
||||
-- ALTER TABLE channels ADD COLUMN workspace_id TEXT REFERENCES workspaces(id) ON DELETE SET NULL;
|
||||
-- Note: SQLite ADD COLUMN IF NOT EXISTS not supported; channels table created with these columns.
|
||||
@@ -1,3 +0,0 @@
|
||||
-- Chat Switchboard — 012 (placeholder, SQLite)
|
||||
-- Previously: extensions + extension_user_settings tables.
|
||||
-- v0.28.7: Both tables removed. Unified package registry in 016.
|
||||
@@ -1,28 +0,0 @@
|
||||
-- Chat Switchboard — 013 Files (SQLite)
|
||||
-- Consolidated v0.28.0: clean install, no legacy attachments migration
|
||||
|
||||
CREATE TABLE IF NOT EXISTS files (
|
||||
id TEXT PRIMARY KEY,
|
||||
channel_id TEXT REFERENCES channels(id) ON DELETE CASCADE,
|
||||
message_id TEXT REFERENCES messages(id) ON DELETE SET NULL,
|
||||
user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
|
||||
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
||||
origin TEXT NOT NULL DEFAULT 'user_upload'
|
||||
CHECK (origin IN ('user_upload', 'tool_output', 'system')),
|
||||
filename TEXT NOT NULL,
|
||||
content_type TEXT NOT NULL DEFAULT 'application/octet-stream',
|
||||
size_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
storage_key TEXT NOT NULL,
|
||||
display_hint TEXT NOT NULL DEFAULT 'download'
|
||||
CHECK (display_hint IN ('inline', 'download', 'thumbnail')),
|
||||
extracted_text TEXT,
|
||||
metadata TEXT DEFAULT '{}',
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_files_channel ON files(channel_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_files_message ON files(message_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_files_user ON files(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_files_project ON files(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_files_origin ON files(origin);
|
||||
@@ -1,42 +0,0 @@
|
||||
-- Chat Switchboard — 014 Audit & Usage (SQLite)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS audit_log (
|
||||
id TEXT PRIMARY KEY,
|
||||
actor_id TEXT REFERENCES users(id) ON DELETE SET NULL,
|
||||
action TEXT NOT NULL,
|
||||
resource_type TEXT NOT NULL,
|
||||
resource_id TEXT,
|
||||
metadata TEXT DEFAULT '{}',
|
||||
ip_address TEXT,
|
||||
user_agent TEXT DEFAULT '',
|
||||
created_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_log_created ON audit_log(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_log_actor ON audit_log(actor_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_log_resource ON audit_log(resource_type, resource_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_log_action ON audit_log(action);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS usage_log (
|
||||
id TEXT PRIMARY KEY,
|
||||
channel_id TEXT REFERENCES channels(id) ON DELETE SET NULL,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
provider_config_id TEXT REFERENCES provider_configs(id) ON DELETE SET NULL,
|
||||
provider_scope TEXT NOT NULL DEFAULT 'global',
|
||||
model_id TEXT NOT NULL,
|
||||
role TEXT,
|
||||
prompt_tokens INTEGER NOT NULL DEFAULT 0,
|
||||
completion_tokens INTEGER NOT NULL DEFAULT 0,
|
||||
cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
|
||||
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
||||
cost_input REAL,
|
||||
cost_output REAL,
|
||||
routing_decision TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_log_user ON usage_log(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_log_created ON usage_log(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_log_provider ON usage_log(provider_config_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_log_model ON usage_log(model_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_log_scope ON usage_log(provider_scope);
|
||||
@@ -1,17 +0,0 @@
|
||||
-- Chat Switchboard — 015 Tool Health (SQLite)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tool_health (
|
||||
id TEXT PRIMARY KEY,
|
||||
tool_name TEXT NOT NULL,
|
||||
window_start TEXT NOT NULL,
|
||||
request_count INTEGER NOT NULL DEFAULT 0,
|
||||
error_count INTEGER NOT NULL DEFAULT 0,
|
||||
total_latency_ms INTEGER NOT NULL DEFAULT 0,
|
||||
max_latency_ms INTEGER NOT NULL DEFAULT 0,
|
||||
last_error TEXT,
|
||||
last_error_at TEXT,
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
UNIQUE (tool_name, window_start)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_tool_health_window ON tool_health(tool_name, window_start);
|
||||
@@ -1,11 +0,0 @@
|
||||
-- Chat Switchboard — 017 Auth Providers (SQLite)
|
||||
-- Consolidated v0.28.0
|
||||
|
||||
CREATE TABLE IF NOT EXISTS oidc_auth_state (
|
||||
state TEXT PRIMARY KEY,
|
||||
nonce TEXT NOT NULL,
|
||||
redirect_to TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_oidc_state_created ON oidc_auth_state(created_at);
|
||||
@@ -1,34 +0,0 @@
|
||||
-- ==========================================
|
||||
-- Chat Switchboard — 020 Multi-Replica HA
|
||||
-- ==========================================
|
||||
-- Shared state tables for multi-replica operation.
|
||||
-- v0.32.0: ws_tickets, rate_limit_counters.
|
||||
-- SQLite parity — functional for single-process test coverage.
|
||||
-- ==========================================
|
||||
|
||||
-- =========================================
|
||||
-- WEBSOCKET TICKETS
|
||||
-- =========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ws_tickets (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
expires_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ws_tickets_expires
|
||||
ON ws_tickets (expires_at);
|
||||
|
||||
-- =========================================
|
||||
-- RATE LIMIT COUNTERS
|
||||
-- =========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rate_limit_counters (
|
||||
key TEXT NOT NULL,
|
||||
window_start TEXT NOT NULL,
|
||||
tokens REAL NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (key, window_start)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_rate_limit_counters_window
|
||||
ON rate_limit_counters (window_start);
|
||||
@@ -1,15 +0,0 @@
|
||||
-- ==========================================
|
||||
-- Chat Switchboard — 021 Data Portability
|
||||
-- ==========================================
|
||||
-- v0.34.0: Indexes for data export and GDPR operations.
|
||||
-- SQLite version (no partial indexes).
|
||||
-- ==========================================
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_channel_active
|
||||
ON messages (channel_id, created_at);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_channels_user_id
|
||||
ON channels (user_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_files_user_id
|
||||
ON files (user_id);
|
||||
@@ -1,24 +0,0 @@
|
||||
-- ==========================================
|
||||
-- Chat Switchboard — 022 Extension Connections
|
||||
-- ==========================================
|
||||
-- v0.38.1: Scoped credential management for extensions.
|
||||
-- SQLite version (no partial indexes, TEXT types).
|
||||
-- ==========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ext_connections (
|
||||
id TEXT PRIMARY KEY,
|
||||
type TEXT NOT NULL,
|
||||
package_id TEXT NOT NULL,
|
||||
scope TEXT NOT NULL CHECK (scope IN ('global', 'team', 'personal')),
|
||||
owner_id TEXT NOT NULL DEFAULT '',
|
||||
name TEXT NOT NULL,
|
||||
config TEXT NOT NULL DEFAULT '{}',
|
||||
is_active INTEGER DEFAULT 1,
|
||||
created_at TEXT,
|
||||
updated_at TEXT,
|
||||
UNIQUE(type, scope, owner_id, name)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_connections_type ON ext_connections(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_connections_scope ON ext_connections(scope);
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_connections_owner ON ext_connections(owner_id);
|
||||
@@ -1,62 +0,0 @@
|
||||
-- ==========================================
|
||||
-- Chat Switchboard — 023 Extension Dependencies
|
||||
-- ==========================================
|
||||
-- v0.38.2: Library package dependency tracking.
|
||||
-- SQLite version.
|
||||
--
|
||||
-- Also adds 'library' to the packages type CHECK constraint.
|
||||
-- SQLite doesn't support ALTER CONSTRAINT, so we rebuild the table.
|
||||
-- ==========================================
|
||||
|
||||
-- Step 1: Rebuild packages table with updated CHECK constraint.
|
||||
CREATE TABLE IF NOT EXISTS packages_new (
|
||||
id TEXT PRIMARY KEY,
|
||||
title TEXT NOT NULL,
|
||||
type TEXT NOT NULL DEFAULT 'surface'
|
||||
CHECK (type IN ('surface', 'extension', 'full', 'workflow', 'library')),
|
||||
version TEXT NOT NULL DEFAULT '0.0.0',
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
author TEXT NOT NULL DEFAULT '',
|
||||
tier TEXT NOT NULL DEFAULT 'browser'
|
||||
CHECK (tier IN ('browser', 'starlark', 'sidecar')),
|
||||
is_system INTEGER NOT NULL DEFAULT 0,
|
||||
scope TEXT NOT NULL DEFAULT 'global'
|
||||
CHECK (scope IN ('global', 'team', 'personal')),
|
||||
team_id TEXT REFERENCES teams(id) ON DELETE CASCADE,
|
||||
installed_by TEXT REFERENCES users(id) ON DELETE SET NULL,
|
||||
manifest TEXT NOT NULL DEFAULT '{}',
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
status TEXT NOT NULL DEFAULT 'active'
|
||||
CHECK (status IN ('active', 'pending_review', 'suspended')),
|
||||
schema_version INTEGER NOT NULL DEFAULT 0,
|
||||
package_settings TEXT NOT NULL DEFAULT '{}',
|
||||
source TEXT NOT NULL DEFAULT 'core'
|
||||
CHECK (source IN ('core', 'builtin', 'extension', 'registry')),
|
||||
installed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
INSERT INTO packages_new SELECT * FROM packages;
|
||||
DROP TABLE packages;
|
||||
ALTER TABLE packages_new RENAME TO packages;
|
||||
|
||||
-- Recreate indexes (dropped with old table)
|
||||
CREATE INDEX IF NOT EXISTS idx_packages_type ON packages(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_packages_enabled ON packages(enabled);
|
||||
CREATE INDEX IF NOT EXISTS idx_packages_team ON packages(team_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_packages_source ON packages(source);
|
||||
CREATE INDEX IF NOT EXISTS idx_packages_status ON packages(status);
|
||||
|
||||
-- Step 2: Dependencies table.
|
||||
CREATE TABLE IF NOT EXISTS ext_dependencies (
|
||||
consumer_id TEXT NOT NULL,
|
||||
library_id TEXT NOT NULL,
|
||||
version_spec TEXT NOT NULL DEFAULT '>=0.0.0',
|
||||
resolved_ver TEXT NOT NULL DEFAULT '0.0.0',
|
||||
PRIMARY KEY (consumer_id, library_id),
|
||||
FOREIGN KEY (consumer_id) REFERENCES packages(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (library_id) REFERENCES packages(id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_deps_consumer ON ext_dependencies(consumer_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_ext_deps_library ON ext_dependencies(library_id);
|
||||
Reference in New Issue
Block a user