- replace default Convex control-plane wording with Rust SQLite control-plane across architecture, AGENTS, Reasonix, and design docs - retire root Convex functions source and deploy script into recycle while keeping explicit cloud/compat/sync-replica boundaries - add control-plane migration guard/docs and keep CodeGraph refreshed after the SQLite control-plane cutover
173 lines
5.3 KiB
SQL
173 lines
5.3 KiB
SQL
-- 001-initial-schema.sql
|
|
-- MNote control-plane v1 schema
|
|
--
|
|
-- All tables use TEXT for datetime columns (ISO-8601) so the database
|
|
-- remains readable without language-specific timestamp types.
|
|
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id TEXT PRIMARY KEY,
|
|
email TEXT UNIQUE,
|
|
username TEXT UNIQUE NOT NULL,
|
|
display_name TEXT NOT NULL,
|
|
role TEXT NOT NULL DEFAULT 'user',
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
revision INTEGER NOT NULL DEFAULT 1
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS auth_identities (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
provider TEXT NOT NULL,
|
|
provider_subject TEXT NOT NULL,
|
|
password_hash TEXT,
|
|
password_version INTEGER NOT NULL DEFAULT 1,
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
UNIQUE(provider, provider_subject)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS auth_sessions (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
token_hash TEXT NOT NULL UNIQUE,
|
|
user_agent TEXT,
|
|
ip_hash TEXT,
|
|
created_at TEXT NOT NULL,
|
|
expires_at TEXT NOT NULL,
|
|
revoked_at TEXT,
|
|
last_seen_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_auth_sessions_user ON auth_sessions(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_auth_sessions_token ON auth_sessions(token_hash);
|
|
|
|
CREATE TABLE IF NOT EXISTS workspaces (
|
|
id TEXT PRIMARY KEY,
|
|
owner_user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
kind TEXT NOT NULL DEFAULT 'personal',
|
|
root_uri TEXT NOT NULL UNIQUE,
|
|
root_path TEXT NOT NULL,
|
|
source_kind TEXT NOT NULL DEFAULT 'local_folder',
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
revision INTEGER NOT NULL DEFAULT 1
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_workspaces_owner ON workspaces(owner_user_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS workspace_members (
|
|
id TEXT PRIMARY KEY,
|
|
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
role TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
revision INTEGER NOT NULL DEFAULT 1,
|
|
UNIQUE(workspace_id, user_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS directory_grants (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
workspace_id TEXT REFERENCES workspaces(id) ON DELETE SET NULL,
|
|
root_uri TEXT NOT NULL,
|
|
root_path TEXT NOT NULL,
|
|
permission TEXT NOT NULL,
|
|
recursive INTEGER NOT NULL DEFAULT 1,
|
|
capabilities_json TEXT NOT NULL DEFAULT '[]',
|
|
source TEXT NOT NULL DEFAULT 'admin',
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
created_by TEXT REFERENCES users(id),
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
revision INTEGER NOT NULL DEFAULT 1
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_directory_grants_user ON directory_grants(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_directory_grants_root_uri ON directory_grants(root_uri);
|
|
|
|
CREATE TABLE IF NOT EXISTS share_links (
|
|
id TEXT PRIMARY KEY,
|
|
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
resource_kind TEXT NOT NULL,
|
|
resource_id TEXT NOT NULL,
|
|
token_hash TEXT NOT NULL UNIQUE,
|
|
permission TEXT NOT NULL,
|
|
created_by TEXT NOT NULL REFERENCES users(id),
|
|
expires_at TEXT,
|
|
revoked_at TEXT,
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
revision INTEGER NOT NULL DEFAULT 1
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_share_links_resource ON share_links(workspace_id, resource_kind, resource_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS sync_state (
|
|
id TEXT PRIMARY KEY,
|
|
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
remote_kind TEXT NOT NULL,
|
|
remote_id TEXT,
|
|
cursor TEXT,
|
|
last_synced_at TEXT,
|
|
status TEXT NOT NULL DEFAULT 'idle',
|
|
error_json TEXT,
|
|
updated_at TEXT NOT NULL,
|
|
revision INTEGER NOT NULL DEFAULT 1,
|
|
UNIQUE(workspace_id, remote_kind)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS ai_policies (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT REFERENCES users(id) ON DELETE CASCADE,
|
|
workspace_id TEXT REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
allowed_roots_json TEXT NOT NULL DEFAULT '[]',
|
|
model_policy_json TEXT NOT NULL DEFAULT '{}',
|
|
quota_json TEXT NOT NULL DEFAULT '{}',
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
revision INTEGER NOT NULL DEFAULT 1
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS audit_log (
|
|
id TEXT PRIMARY KEY,
|
|
actor_user_id TEXT REFERENCES users(id),
|
|
action TEXT NOT NULL,
|
|
target_kind TEXT NOT NULL,
|
|
target_id TEXT,
|
|
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
created_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_audit_actor ON audit_log(actor_user_id, created_at);
|
|
CREATE INDEX IF NOT EXISTS idx_audit_target ON audit_log(target_kind, target_id, created_at);
|
|
|
|
CREATE TABLE IF NOT EXISTS outbox_events (
|
|
id TEXT PRIMARY KEY,
|
|
topic TEXT NOT NULL,
|
|
event_type TEXT NOT NULL,
|
|
payload_json TEXT NOT NULL,
|
|
created_at TEXT NOT NULL,
|
|
delivered_at TEXT,
|
|
attempts INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_outbox_pending ON outbox_events(delivered_at, created_at);
|
|
|
|
CREATE TABLE IF NOT EXISTS legacy_id_map (
|
|
id TEXT PRIMARY KEY,
|
|
legacy_system TEXT NOT NULL,
|
|
legacy_kind TEXT NOT NULL,
|
|
legacy_id TEXT NOT NULL,
|
|
new_kind TEXT NOT NULL,
|
|
new_id TEXT NOT NULL,
|
|
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
created_at TEXT NOT NULL,
|
|
UNIQUE(legacy_system, legacy_kind, legacy_id)
|
|
);
|