Kansho/backend/schema.sql

205 lines
7.2 KiB
SQL

CREATE TABLE IF NOT EXISTS schema_migrations (
id TEXT PRIMARY KEY,
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS tiers (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
active INTEGER NOT NULL DEFAULT 1,
sort_order INTEGER NOT NULL DEFAULT 0,
created TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS features (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
category TEXT NOT NULL DEFAULT 'platform',
limit_type TEXT NOT NULL CHECK (limit_type IN ('boolean', 'count')),
default_limit INTEGER,
reset_period TEXT NOT NULL DEFAULT 'none' CHECK (reset_period IN ('none', 'day', 'month')),
active INTEGER NOT NULL DEFAULT 1,
created TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS tier_limits (
tier_id TEXT NOT NULL REFERENCES tiers(id) ON DELETE CASCADE,
feature_id TEXT NOT NULL REFERENCES features(id) ON DELETE CASCADE,
limit_value INTEGER,
PRIMARY KEY (tier_id, feature_id)
);
CREATE TABLE IF NOT EXISTS profiles (
id TEXT PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
password_hash TEXT NOT NULL,
role TEXT NOT NULL CHECK (role IN ('user', 'admin')),
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'disabled')),
tier_id TEXT NOT NULL DEFAULT 'local' REFERENCES tiers(id),
session_days INTEGER NOT NULL DEFAULT 30,
created TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS sessions (
token TEXT PRIMARY KEY,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
expires_at TEXT NOT NULL,
created TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS user_feature_restrictions (
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
feature_id TEXT NOT NULL REFERENCES features(id) ON DELETE CASCADE,
limit_value INTEGER,
PRIMARY KEY (profile_id, feature_id)
);
CREATE TABLE IF NOT EXISTS user_feature_usage (
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
feature_id TEXT NOT NULL REFERENCES features(id) ON DELETE CASCADE,
period_key TEXT NOT NULL,
used INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (profile_id, feature_id, period_key)
);
CREATE TABLE IF NOT EXISTS ai_prompts (
id TEXT PRIMARY KEY,
slug TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
category TEXT NOT NULL DEFAULT 'uncategorized',
prompt_type TEXT NOT NULL DEFAULT 'base' CHECK (prompt_type IN ('base', 'pipeline', 'workflow')),
template TEXT NOT NULL DEFAULT '',
stages_json TEXT,
graph_json TEXT,
output_format TEXT NOT NULL DEFAULT 'text',
output_schema_json TEXT,
required_feature TEXT NOT NULL DEFAULT 'ai_calls',
active INTEGER NOT NULL DEFAULT 1,
is_system_default INTEGER NOT NULL DEFAULT 0,
default_template TEXT NOT NULL DEFAULT '',
sort_order INTEGER NOT NULL DEFAULT 0,
created TEXT NOT NULL DEFAULT (datetime('now')),
updated TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS usage_sessions (
id TEXT PRIMARY KEY,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
intent TEXT NOT NULL DEFAULT '',
started_at TEXT NOT NULL DEFAULT (datetime('now')),
ended_at TEXT,
created TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS conversations (
id TEXT PRIMARY KEY,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
usage_session_id TEXT REFERENCES usage_sessions(id),
title TEXT NOT NULL DEFAULT '',
created TEXT NOT NULL DEFAULT (datetime('now')),
updated TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS messages (
id TEXT PRIMARY KEY,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
seq INTEGER NOT NULL,
role TEXT NOT NULL,
body TEXT NOT NULL,
created TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE (conversation_id, seq)
);
CREATE TABLE IF NOT EXISTS threads (
id TEXT PRIMARY KEY,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
title TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'open',
visibility TEXT NOT NULL DEFAULT 'internal' CHECK (visibility IN ('internal', 'user')),
resurfacing_at TEXT,
created TEXT NOT NULL DEFAULT (datetime('now')),
updated TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS conversation_threads (
conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
thread_id TEXT NOT NULL REFERENCES threads(id) ON DELETE CASCADE,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
PRIMARY KEY (conversation_id, thread_id)
);
CREATE TABLE IF NOT EXISTS spaces (
id TEXT PRIMARY KEY,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
title TEXT NOT NULL DEFAULT '',
visibility TEXT NOT NULL DEFAULT 'internal' CHECK (visibility IN ('internal', 'user')),
created TEXT NOT NULL DEFAULT (datetime('now')),
updated TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS thread_spaces (
thread_id TEXT NOT NULL REFERENCES threads(id) ON DELETE CASCADE,
space_id TEXT NOT NULL REFERENCES spaces(id) ON DELETE CASCADE,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
confidence REAL,
PRIMARY KEY (thread_id, space_id)
);
CREATE TABLE IF NOT EXISTS derived_records (
id TEXT PRIMARY KEY,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
kind TEXT NOT NULL,
subject_type TEXT NOT NULL,
subject_id TEXT NOT NULL,
source_message_ids TEXT NOT NULL,
as_of TEXT NOT NULL,
confidence REAL,
visibility TEXT NOT NULL DEFAULT 'internal' CHECK (visibility IN ('internal', 'user')),
body TEXT NOT NULL DEFAULT '',
created TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS handoffs (
id TEXT PRIMARY KEY,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
target TEXT NOT NULL CHECK (target IN ('journal', 'memory', 'knowledge', 'action', 'mindnet', 'obsidian')),
status TEXT NOT NULL DEFAULT 'draft',
source_conversation_id TEXT REFERENCES conversations(id),
payload_json TEXT NOT NULL DEFAULT '{}',
created TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS external_refs (
id TEXT PRIMARY KEY,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
target TEXT NOT NULL CHECK (target IN ('mindnet', 'obsidian')),
external_id TEXT NOT NULL DEFAULT '',
kansho_type TEXT NOT NULL,
kansho_id TEXT NOT NULL,
created TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS re_grounding_events (
id TEXT PRIMARY KEY,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
subject_type TEXT NOT NULL,
subject_id TEXT NOT NULL,
reason TEXT NOT NULL DEFAULT '',
source_message_ids TEXT NOT NULL DEFAULT '[]',
created TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS identity_mappings (
id TEXT PRIMARY KEY,
profile_id TEXT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
token TEXT NOT NULL,
local_label TEXT NOT NULL DEFAULT '',
created TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE (profile_id, token)
);