2026-09-05 00:31:28 -07:00
|
|
|
-- Phase 2.8: Authentication and Multi-Tenant Schema
|
|
|
|
|
--
|
|
|
|
|
-- Adds:
|
|
|
|
|
-- 1. memory_projects table (source of truth for project ownership)
|
|
|
|
|
-- 2. contributed_by columns (attribution tracking)
|
|
|
|
|
-- 3. Indexes for fast lookups
|
|
|
|
|
--
|
|
|
|
|
-- Note: RBAC itself lives in auth provider (Authentik, custom service, etc).
|
|
|
|
|
-- This schema only tracks project ownership and user attribution.
|
|
|
|
|
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
-- 1. Projects table (source of truth for ownership)
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS memory_projects (
|
|
|
|
|
id VARCHAR(255) PRIMARY KEY,
|
|
|
|
|
|
|
|
|
|
-- Ownership
|
|
|
|
|
owner_id VARCHAR(255) NOT NULL, -- JWT "sub" of creator
|
|
|
|
|
visibility VARCHAR(20) NOT NULL, -- "private" | "team" | "public"
|
|
|
|
|
|
|
|
|
|
-- Metadata
|
|
|
|
|
name VARCHAR(255), -- Display name
|
|
|
|
|
description TEXT,
|
|
|
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
|
|
|
|
-- Soft delete
|
|
|
|
|
deleted_at TIMESTAMPTZ
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_memory_projects_owner_id
|
|
|
|
|
ON memory_projects(owner_id)
|
|
|
|
|
WHERE deleted_at IS NULL;
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_memory_projects_visibility
|
|
|
|
|
ON memory_projects(visibility)
|
|
|
|
|
WHERE deleted_at IS NULL;
|
|
|
|
|
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
-- 2. Add attribution columns to entities
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
2026-09-15 15:22:41 +09:00
|
|
|
ALTER TABLE knowledge_node ADD COLUMN IF NOT EXISTS (
|
2026-09-05 00:31:28 -07:00
|
|
|
contributed_by VARCHAR(255), -- JWT "sub" who added this
|
|
|
|
|
contribution_type VARCHAR(50), -- "extracted" | "manual" | "inferred"
|
|
|
|
|
contribution_date TIMESTAMPTZ
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
-- Populate contributed_by with defaults (assume "system" if not present)
|
2026-09-15 15:22:41 +09:00
|
|
|
UPDATE knowledge_node
|
2026-09-05 00:31:28 -07:00
|
|
|
SET contributed_by = 'system'
|
|
|
|
|
WHERE contributed_by IS NULL;
|
|
|
|
|
|
2026-09-15 15:22:41 +09:00
|
|
|
ALTER TABLE knowledge_node
|
2026-09-05 00:31:28 -07:00
|
|
|
ALTER COLUMN contributed_by SET NOT NULL;
|
|
|
|
|
|
2026-09-15 15:22:41 +09:00
|
|
|
CREATE INDEX IF NOT EXISTS idx_knowledge_node_contributed_by
|
|
|
|
|
ON knowledge_node(contributed_by);
|
2026-09-05 00:31:28 -07:00
|
|
|
|
2026-09-15 15:22:41 +09:00
|
|
|
CREATE INDEX IF NOT EXISTS idx_knowledge_node_contribution_date
|
|
|
|
|
ON knowledge_node(contribution_date)
|
2026-09-05 00:31:28 -07:00
|
|
|
WHERE contribution_date IS NOT NULL;
|
|
|
|
|
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
-- 3. Add attribution columns to edges
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
2026-09-15 15:22:41 +09:00
|
|
|
ALTER TABLE knowledge_edge ADD COLUMN IF NOT EXISTS (
|
2026-09-05 00:31:28 -07:00
|
|
|
contributed_by VARCHAR(255), -- JWT "sub" who added this
|
|
|
|
|
contribution_type VARCHAR(50) -- "extracted" | "inferred"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
-- Populate contributed_by with defaults
|
2026-09-15 15:22:41 +09:00
|
|
|
UPDATE knowledge_edge
|
2026-09-05 00:31:28 -07:00
|
|
|
SET contributed_by = 'system'
|
|
|
|
|
WHERE contributed_by IS NULL;
|
|
|
|
|
|
2026-09-15 15:22:41 +09:00
|
|
|
ALTER TABLE knowledge_edge
|
2026-09-05 00:31:28 -07:00
|
|
|
ALTER COLUMN contributed_by SET NOT NULL;
|
|
|
|
|
|
2026-09-15 15:22:41 +09:00
|
|
|
CREATE INDEX IF NOT EXISTS idx_knowledge_edge_contributed_by
|
|
|
|
|
ON knowledge_edge(contributed_by);
|
2026-09-05 00:31:28 -07:00
|
|
|
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
-- 4. Add project_id to entities and edges (optional, for faster filtering)
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
2026-09-15 15:22:41 +09:00
|
|
|
-- ALTER TABLE knowledge_node ADD COLUMN IF NOT EXISTS project_id VARCHAR(255);
|
|
|
|
|
-- ALTER TABLE knowledge_edge ADD COLUMN IF NOT EXISTS project_id VARCHAR(255);
|
2026-09-05 00:31:28 -07:00
|
|
|
--
|
|
|
|
|
-- Note: Deferred. Can use project info from path/source instead.
|
|
|
|
|
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
-- 5. Views for common queries
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
-- Entities contributed by a user in a time range
|
|
|
|
|
CREATE OR REPLACE VIEW v_user_contributions AS
|
|
|
|
|
SELECT
|
|
|
|
|
contributed_by,
|
|
|
|
|
COUNT(*) as entity_count,
|
|
|
|
|
MAX(contribution_date) as last_contribution,
|
|
|
|
|
ARRAY_AGG(DISTINCT contribution_type) as contribution_types
|
2026-09-15 15:22:41 +09:00
|
|
|
FROM knowledge_node
|
2026-09-05 00:31:28 -07:00
|
|
|
WHERE contribution_date IS NOT NULL
|
|
|
|
|
GROUP BY contributed_by;
|
|
|
|
|
|
|
|
|
|
-- Recent contributions (last 7 days)
|
|
|
|
|
CREATE OR REPLACE VIEW v_recent_contributions AS
|
|
|
|
|
SELECT
|
|
|
|
|
contributed_by,
|
|
|
|
|
COUNT(*) as count,
|
|
|
|
|
MAX(contribution_date) as latest
|
2026-09-15 15:22:41 +09:00
|
|
|
FROM knowledge_node
|
2026-09-05 00:31:28 -07:00
|
|
|
WHERE contribution_date > CURRENT_TIMESTAMP - INTERVAL '7 days'
|
|
|
|
|
GROUP BY contributed_by;
|
|
|
|
|
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
-- 6. Rollback support
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
-- To rollback this migration:
|
|
|
|
|
--
|
|
|
|
|
-- DROP VIEW IF EXISTS v_recent_contributions;
|
|
|
|
|
-- DROP VIEW IF EXISTS v_user_contributions;
|
|
|
|
|
--
|
|
|
|
|
-- DROP INDEX IF EXISTS idx_memory_projects_owner_id;
|
|
|
|
|
-- DROP INDEX IF EXISTS idx_memory_projects_visibility;
|
|
|
|
|
-- DROP TABLE IF EXISTS memory_projects;
|
|
|
|
|
--
|
2026-09-15 15:22:41 +09:00
|
|
|
-- DROP INDEX IF EXISTS idx_knowledge_node_contributed_by;
|
|
|
|
|
-- DROP INDEX IF EXISTS idx_knowledge_node_contribution_date;
|
|
|
|
|
-- ALTER TABLE knowledge_node DROP COLUMN IF EXISTS contributed_by;
|
|
|
|
|
-- ALTER TABLE knowledge_node DROP COLUMN IF EXISTS contribution_type;
|
|
|
|
|
-- ALTER TABLE knowledge_node DROP COLUMN IF EXISTS contribution_date;
|
2026-09-05 00:31:28 -07:00
|
|
|
--
|
2026-09-15 15:22:41 +09:00
|
|
|
-- DROP INDEX IF EXISTS idx_knowledge_edge_contributed_by;
|
|
|
|
|
-- ALTER TABLE knowledge_edge DROP COLUMN IF EXISTS contributed_by;
|
|
|
|
|
-- ALTER TABLE knowledge_edge DROP COLUMN IF EXISTS contribution_type;
|