Changeset 0.28.0.1 (#173)

This commit is contained in:
2026-03-11 14:45:37 +00:00
parent 93c72daadf
commit 58313f7e31
57 changed files with 5139 additions and 3206 deletions

View File

@@ -42,6 +42,9 @@ CREATE TABLE IF NOT EXISTS groups (
updated_at TEXT DEFAULT (datetime('now'))
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_groups_name_scope
ON groups(name, COALESCE(team_id, ''));
CREATE TABLE IF NOT EXISTS group_members (
id TEXT PRIMARY KEY,
group_id TEXT NOT NULL REFERENCES groups(id) ON DELETE CASCADE,

View File

@@ -1,23 +0,0 @@
-- ==========================================
-- Chat Switchboard — 006 Multi-User: DMs + Channels (SQLite)
-- ==========================================
-- SQLite does not support ALTER CONSTRAINT or DROP CONSTRAINT.
-- The type check is enforced by application logic for SQLite.
-- ==========================================
-- ── ai_mode ──────────────────────────────────────────────────────────
-- SQLite ignores CHECK constraints on existing rows; we add the column
-- and rely on app-layer validation for the enum values.
ALTER TABLE channels ADD COLUMN ai_mode TEXT NOT NULL DEFAULT 'auto';
-- ── topic ─────────────────────────────────────────────────────────────
ALTER TABLE channels ADD COLUMN topic TEXT;
-- ── Presence ──────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS user_presence (
user_id TEXT PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
last_seen DATETIME NOT NULL DEFAULT (datetime('now')),
status TEXT NOT NULL DEFAULT 'online'
);
CREATE INDEX IF NOT EXISTS idx_user_presence_last_seen ON user_presence(last_seen DESC);

View File

@@ -1,3 +0,0 @@
-- Chat Switchboard — 017 Unread Counts (SQLite)
ALTER TABLE channel_participants ADD COLUMN last_read_message_id TEXT;

View File

@@ -1,8 +0,0 @@
-- Chat Switchboard — 018 Auth Abstraction (SQLite) (v0.24.0)
ALTER TABLE users ADD COLUMN auth_source TEXT NOT NULL DEFAULT 'builtin';
ALTER TABLE users ADD COLUMN external_id TEXT;
ALTER TABLE users ADD COLUMN handle TEXT;
UPDATE users SET handle = LOWER(REPLACE(REPLACE(username, ' ', '-'), '_', '-'))
WHERE handle IS NULL;
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_handle ON users(handle COLLATE NOCASE);
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_external_id ON users(auth_source, external_id);

View File

@@ -1,13 +0,0 @@
-- Chat Switchboard — 019 Auth Providers (SQLite) (v0.24.1)
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);
ALTER TABLE groups ADD COLUMN source TEXT NOT NULL DEFAULT 'manual';

View File

@@ -1,25 +0,0 @@
-- Chat Switchboard — 020 Permissions (SQLite) (v0.24.2)
-- SQLite cannot drop NOT NULL inline; recreating the constraint isn't needed
-- since SQLite doesn't enforce CHECK constraints strictly and the column
-- already accepts NULL in practice. The store layer guards source='system'.
ALTER TABLE groups ADD COLUMN permissions TEXT NOT NULL DEFAULT '[]';
ALTER TABLE groups ADD COLUMN token_budget_daily INTEGER;
ALTER TABLE groups ADD COLUMN token_budget_monthly INTEGER;
ALTER TABLE groups ADD COLUMN allowed_models TEXT;
-- Seed the Everyone group with a stable well-known ID.
INSERT OR IGNORE INTO groups
(id, name, description, scope, created_by, source, permissions, created_at, updated_at)
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')
);

View File

@@ -1,20 +0,0 @@
-- 021_sessions.sql (SQLite)
-- Anonymous / session participants for workflow channels (v0.24.3)
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 DATETIME 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);
-- Allow channels to opt in to anonymous session access.
ALTER TABLE channels ADD COLUMN allow_anonymous INTEGER NOT NULL DEFAULT 0;

View File

@@ -1,56 +0,0 @@
-- 023_workflows.sql (SQLite)
-- Workflow definitions, stages, and version snapshots (v0.26.1)
CREATE TABLE IF NOT EXISTS workflows (
id TEXT PRIMARY KEY,
team_id TEXT REFERENCES teams(id) ON DELETE CASCADE,
name TEXT NOT NULL,
slug TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
branding TEXT NOT NULL DEFAULT '{}',
entry_mode TEXT NOT NULL DEFAULT 'public_link'
CHECK (entry_mode IN ('public_link', 'team_only')),
is_active INTEGER NOT NULL DEFAULT 0,
version INTEGER NOT NULL DEFAULT 1,
on_complete TEXT,
retention TEXT NOT NULL DEFAULT '{"mode": "archive"}',
created_by TEXT NOT NULL REFERENCES users(id),
created_at DATETIME NOT NULL DEFAULT (datetime('now')),
updated_at DATETIME NOT NULL DEFAULT (datetime('now'))
);
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;
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,
assignment_team_id TEXT REFERENCES teams(id) ON DELETE SET NULL,
form_template TEXT NOT NULL DEFAULT '{}',
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 '{}',
created_at DATETIME NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_workflow_stages_workflow
ON workflow_stages(workflow_id, ordinal);
CREATE TABLE IF NOT EXISTS workflow_versions (
id TEXT PRIMARY KEY,
workflow_id TEXT NOT NULL REFERENCES workflows(id) ON DELETE CASCADE,
version_number INTEGER NOT NULL,
snapshot TEXT NOT NULL,
created_at DATETIME NOT NULL DEFAULT (datetime('now')),
UNIQUE (workflow_id, version_number)
);
CREATE INDEX IF NOT EXISTS idx_workflow_versions_workflow
ON workflow_versions(workflow_id, version_number);

View File

@@ -1,13 +0,0 @@
-- 024_workflow_instances.sql (SQLite)
-- Workflow instance columns on channels (v0.26.2)
ALTER TABLE channels ADD COLUMN workflow_id TEXT REFERENCES workflows(id) ON DELETE SET NULL;
ALTER TABLE channels ADD COLUMN workflow_version INTEGER;
ALTER TABLE channels ADD COLUMN current_stage INTEGER DEFAULT 0;
ALTER TABLE channels ADD COLUMN stage_data TEXT DEFAULT '{}';
ALTER TABLE channels ADD COLUMN workflow_status TEXT DEFAULT 'active'
CHECK (workflow_status IN ('active', 'completed', 'stale', 'cancelled'));
ALTER TABLE channels ADD COLUMN last_activity_at DATETIME DEFAULT (datetime('now'));
CREATE INDEX IF NOT EXISTS idx_channels_workflow
ON channels(workflow_id) WHERE workflow_id IS NOT NULL;

View File

@@ -1,21 +0,0 @@
-- 025_workflow_assignments.sql (SQLite)
-- Assignment queue for workflow stages (v0.26.4)
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')),
created_at DATETIME NOT NULL DEFAULT (datetime('now')),
claimed_at DATETIME,
completed_at DATETIME
);
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);

View File

@@ -1,63 +0,0 @@
-- 026_tasks.sql — Task scheduling for autonomous agents (v0.27.1) — SQLite
-- Note: SQLite CHECK on channels.type is in the CREATE TABLE (005),
-- which cannot be altered. The 'service' type is accepted by convention;
-- the Go layer validates.
CREATE TABLE IF NOT EXISTS tasks (
id TEXT PRIMARY KEY,
owner_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
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',
persona_id TEXT REFERENCES personas(id) ON DELETE SET NULL,
model_id TEXT,
system_prompt TEXT DEFAULT '',
user_prompt TEXT DEFAULT '',
workflow_id TEXT REFERENCES workflows(id) ON DELETE SET NULL,
tool_grants TEXT,
schedule TEXT NOT NULL,
timezone TEXT NOT NULL DEFAULT 'UTC',
is_active INTEGER NOT NULL DEFAULT 1,
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,
webhook_url 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,
next_run_at TEXT,
run_count INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
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 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',
started_at TEXT NOT NULL DEFAULT (datetime('now')),
completed_at TEXT,
tokens_used INTEGER DEFAULT 0,
tool_calls INTEGER DEFAULT 0,
wall_clock INTEGER DEFAULT 0,
error TEXT
);
CREATE INDEX IF NOT EXISTS idx_task_runs_task ON task_runs (task_id);

View File

@@ -1,5 +0,0 @@
-- 027_webhooks.sql — Webhook secrets + workflow webhook support (v0.27.3) — SQLite
ALTER TABLE tasks ADD COLUMN webhook_secret TEXT;
ALTER TABLE workflows ADD COLUMN webhook_url TEXT;
ALTER TABLE workflows ADD COLUMN webhook_secret TEXT;