127 lines
5.3 KiB
SQL
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 $$;
|