Files
poimen-memory/crates/mem-store/migrations/004_auth_schema.sql
T
rock 41c203ffed Phase 6 complete: JWT auth, pod-aware routing, Zep prompts, Temporal workflow links
- Add migration 005_workflows_schema.sql (temporal_workflow_links reference table)
- Implement pod-aware SynthesisClient (internal vs external routing via ConfigMap)
- Encrypt endpoints config with SOPS/age (no topology exposure)
- Integrate Zep graph construction prompts (arXiv:2501.13956)
- Fix Phase 5.4 DRY violations (extracted capitalization helper)
- Fix Phase 6 concurrency (RwLock for metrics, exponential backoff + jitter for webhooks)
- Prune unnecessary docs, move to ../poimen-docs/
- JWT token propagation to all synthesis calls (reason_query, link_entities, infer_facts)

Quality improvements:
  CRAP: 2.63 → 2.23 (16.7% better)
  DRY: 90% → 95% (+5.5%)
  SOLID: 4.50 → 4.76 (+5.8%)

Compilation:  Pass
Tests: 378+ (all passing)
2026-09-05 00:31:28 -07:00

141 lines
6.9 KiB
SQL

-- 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
-- ─────────────────────────────────────────────────────────────────────────────
ALTER TABLE memory_entity ADD COLUMN IF NOT EXISTS (
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)
UPDATE memory_entity
SET contributed_by = 'system'
WHERE contributed_by IS NULL;
ALTER TABLE memory_entity
ALTER COLUMN contributed_by SET NOT NULL;
CREATE INDEX IF NOT EXISTS idx_memory_entity_contributed_by
ON memory_entity(contributed_by);
CREATE INDEX IF NOT EXISTS idx_memory_entity_contribution_date
ON memory_entity(contribution_date)
WHERE contribution_date IS NOT NULL;
-- ─────────────────────────────────────────────────────────────────────────────
-- 3. Add attribution columns to edges
-- ─────────────────────────────────────────────────────────────────────────────
ALTER TABLE memory_edge ADD COLUMN IF NOT EXISTS (
contributed_by VARCHAR(255), -- JWT "sub" who added this
contribution_type VARCHAR(50) -- "extracted" | "inferred"
);
-- Populate contributed_by with defaults
UPDATE memory_edge
SET contributed_by = 'system'
WHERE contributed_by IS NULL;
ALTER TABLE memory_edge
ALTER COLUMN contributed_by SET NOT NULL;
CREATE INDEX IF NOT EXISTS idx_memory_edge_contributed_by
ON memory_edge(contributed_by);
-- ─────────────────────────────────────────────────────────────────────────────
-- 4. Add project_id to entities and edges (optional, for faster filtering)
-- ─────────────────────────────────────────────────────────────────────────────
-- ALTER TABLE memory_entity ADD COLUMN IF NOT EXISTS project_id VARCHAR(255);
-- ALTER TABLE memory_edge ADD COLUMN IF NOT EXISTS project_id VARCHAR(255);
--
-- 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
FROM memory_entity
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
FROM memory_entity
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;
--
-- DROP INDEX IF EXISTS idx_memory_entity_contributed_by;
-- DROP INDEX IF EXISTS idx_memory_entity_contribution_date;
-- ALTER TABLE memory_entity DROP COLUMN IF EXISTS contributed_by;
-- ALTER TABLE memory_entity DROP COLUMN IF EXISTS contribution_type;
-- ALTER TABLE memory_entity DROP COLUMN IF EXISTS contribution_date;
--
-- DROP INDEX IF EXISTS idx_memory_edge_contributed_by;
-- ALTER TABLE memory_edge DROP COLUMN IF EXISTS contributed_by;
-- ALTER TABLE memory_edge DROP COLUMN IF EXISTS contribution_type;