Files
poimen-memory/crates/mem-store/migrations/007_versioning_schema.sql
T
rock 7d49a2aaef
CI / CI (pull_request) Failing after 11m15s
refactor: rename memory_entity→knowledge_node, knowledge graph edge→knowledge_edge
Resolves table name collision between:
- memory_edge (provenance DAG: child_sha/parent_sha) — KEPT
- knowledge_edge (knowledge graph: source_id/target_id) — NEW NAME

Changes:
- memory_entity → knowledge_node (all .rs + migrations 003-009)
- knowledge graph memory_edge → knowledge_edge
- memory_entity_version → knowledge_node_version
- memory_edge_version → knowledge_edge_version
- Added knowledge_node + knowledge_edge to init_schema()
- Converted versioning.rs from sqlx::query_as! to runtime queries
  (avoids stale sqlx offline cache dependency)
- Fixed UUID cast: $1::UUID for String→UUID column binds
- Fixed column names: source_entity_id→source_id, target_entity_id→target_id

Production DB: knowledge_node + knowledge_edge tables created,
memory_entity VIEW points to knowledge_node for backward compat.
2026-09-15 15:22:41 +09:00

96 lines
3.2 KiB
PL/PgSQL

-- Migration: 007_versioning_schema.sql
-- Phase 7.1: Entity & Edge Versioning
-- Tracks full snapshots on every mutation for rollback capability
BEGIN;
-- Entity version snapshots (immutable)
CREATE TABLE IF NOT EXISTS knowledge_node_version (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
entity_id VARCHAR(255) NOT NULL,
version_num INTEGER NOT NULL,
operation VARCHAR(20) NOT NULL CHECK (operation IN ('create', 'update', 'delete')),
-- Full snapshot JSONB
snapshot JSONB NOT NULL,
-- Audit metadata
changed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
changed_by VARCHAR(255) NOT NULL, -- JWT sub claim
fields_changed TEXT[] DEFAULT '{}',
-- Temporal
t_created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Constraints
UNIQUE(entity_id, version_num),
CONSTRAINT valid_version_num CHECK (version_num > 0)
);
-- Edge version snapshots
CREATE TABLE IF NOT EXISTS knowledge_edge_version (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
edge_id UUID NOT NULL,
version_num INTEGER NOT NULL,
operation VARCHAR(20) NOT NULL CHECK (operation IN ('create', 'update', 'delete')),
-- Full snapshot JSONB
snapshot JSONB NOT NULL,
-- Audit metadata
changed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
changed_by VARCHAR(255) NOT NULL,
fields_changed TEXT[] DEFAULT '{}',
-- Temporal
t_created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Constraints
UNIQUE(edge_id, version_num),
CONSTRAINT valid_version_num CHECK (version_num > 0)
);
-- Indexes for efficient lookups
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_version_entity_id
ON knowledge_node_version(entity_id, version_num DESC);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_version_changed_at
ON knowledge_node_version(changed_at DESC);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_version_changed_by
ON knowledge_node_version(changed_by);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_version_edge_id
ON knowledge_edge_version(edge_id, version_num DESC);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_version_changed_at
ON knowledge_edge_version(changed_at DESC);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_version_changed_by
ON knowledge_edge_version(changed_by);
-- Immutability enforcement: version tables are append-only
CREATE OR REPLACE FUNCTION prevent_version_table_modification()
RETURNS TRIGGER AS $$
BEGIN
RAISE EXCEPTION 'Version tables are immutable';
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER knowledge_node_version_immutable
BEFORE UPDATE OR DELETE ON knowledge_node_version
FOR EACH ROW EXECUTE FUNCTION prevent_version_table_modification();
CREATE TRIGGER knowledge_edge_version_immutable
BEFORE UPDATE OR DELETE ON knowledge_edge_version
FOR EACH ROW EXECUTE FUNCTION prevent_version_table_modification();
COMMIT;
-- Rollback (for reference):
-- DROP TRIGGER knowledge_node_version_immutable ON knowledge_node_version;
-- DROP TRIGGER knowledge_edge_version_immutable ON knowledge_edge_version;
-- DROP FUNCTION prevent_version_table_modification();
-- DROP TABLE knowledge_node_version;
-- DROP TABLE knowledge_edge_version;