This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/server/database/migrations/009_workspaces.sql
2026-03-15 01:33:38 +00:00

127 lines
5.3 KiB
SQL

-- ==========================================
-- Chat Switchboard — 009 Workspaces & Git
-- ==========================================
-- File workspaces, workspace file index, semantic chunks, git credentials.
-- ICD §7 (Workspaces & Git)
-- ==========================================
-- =========================================
-- WORKSPACES
-- =========================================
CREATE TABLE IF NOT EXISTS workspaces (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
owner_type VARCHAR(20) NOT NULL
CHECK (owner_type IN ('user', 'project', 'channel', 'team')),
owner_id UUID NOT NULL,
name VARCHAR(200) NOT NULL,
root_path TEXT NOT NULL,
max_bytes BIGINT,
status VARCHAR(20) NOT NULL DEFAULT 'active'
CHECK (status IN ('active', 'archived', 'deleting')),
indexing_enabled BOOLEAN NOT NULL DEFAULT true,
-- Git integration (v0.21.4)
git_remote_url TEXT,
git_branch TEXT,
git_credential_id UUID,
git_last_sync TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT 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) WHERE status != 'deleting';
DROP TRIGGER IF EXISTS workspaces_updated_at ON workspaces;
CREATE TRIGGER workspaces_updated_at BEFORE UPDATE ON workspaces
FOR EACH ROW EXECUTE FUNCTION update_updated_at();
COMMENT ON TABLE workspaces IS 'File workspaces bound to users, projects, channels, or teams';
COMMENT ON COLUMN workspaces.root_path IS 'PVC-relative path to workspace root directory';
-- =========================================
-- WORKSPACE FILES
-- =========================================
CREATE TABLE IF NOT EXISTS workspace_files (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
path TEXT NOT NULL,
is_directory BOOLEAN NOT NULL DEFAULT false,
content_type VARCHAR(100),
size_bytes BIGINT NOT NULL DEFAULT 0,
sha256 VARCHAR(64),
index_status VARCHAR(20) DEFAULT 'pending'
CHECK (index_status IN ('pending', 'indexing', 'ready', 'error', 'skipped')),
chunk_count INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT 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) WHERE content_type IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_workspace_files_index_status
ON workspace_files(workspace_id, index_status)
WHERE index_status IN ('pending', 'indexing');
DROP TRIGGER IF EXISTS workspace_files_updated_at ON workspace_files;
CREATE TRIGGER workspace_files_updated_at BEFORE UPDATE ON workspace_files
FOR EACH ROW EXECUTE FUNCTION update_updated_at();
COMMENT ON TABLE workspace_files IS 'Metadata index for workspace files — filesystem is source of truth';
-- =========================================
-- WORKSPACE CHUNKS (v0.21.2)
-- =========================================
CREATE TABLE IF NOT EXISTS workspace_chunks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
file_id UUID NOT NULL REFERENCES workspace_files(id) ON DELETE CASCADE,
chunk_index INT NOT NULL,
content TEXT NOT NULL,
token_count INT NOT NULL DEFAULT 0,
embedding vector(3072),
metadata JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT 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);
COMMENT ON TABLE workspace_chunks IS 'Text chunks with vector embeddings for workspace file semantic search';
-- =========================================
-- GIT CREDENTIALS (v0.21.4)
-- =========================================
CREATE TABLE IF NOT EXISTS git_credentials (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL DEFAULT '',
auth_type TEXT NOT NULL DEFAULT 'https_pat',
encrypted_data BYTEA NOT NULL DEFAULT '',
nonce BYTEA NOT NULL DEFAULT '',
public_key TEXT NOT NULL DEFAULT '',
fingerprint TEXT NOT NULL DEFAULT '',
persona_id UUID REFERENCES personas(id) ON DELETE SET NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_git_credentials_user ON git_credentials(user_id);
-- Deferred FK: workspaces.git_credential_id → git_credentials.id
DO $$ BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'fk_workspaces_git_credential'
) THEN
ALTER TABLE workspaces ADD CONSTRAINT fk_workspaces_git_credential
FOREIGN KEY (git_credential_id) REFERENCES git_credentials(id) ON DELETE SET NULL;
END IF;
END $$;