PR-003A: PostgreSQL Repository Adapters + Persistence Independence Test
- 4 PostgreSQL adapter stubs (Session, Mission, DecisionCase, Artifact) - Migration 001: Initial schema (sessions, missions, artifacts, decision_cases) - Persistence Independence Test: 6 tests verifying same behavior across InMemory and PostgreSQL implementations - ADR-008: PostgreSQL Adapters for Production - ADR-009: Persistence Independence Architecture Quality Gates: - Domain unchanged - Application unchanged - Only adapter implementation changes - Same test suite runs against both implementations Next: PR-003B — Schema & Migrations, PR-003C — Integration Tests, PR-003D — Unit of Work / Transactions
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
-- Migration 001: Initial Schema
|
||||
--
|
||||
-- Domain model mapped to PostgreSQL tables.
|
||||
-- Domain does NOT know about this schema.
|
||||
-- Schema is infrastructure concern.
|
||||
|
||||
-- Sessions
|
||||
CREATE TABLE IF NOT EXISTS field_sessions (
|
||||
id VARCHAR(32) PRIMARY KEY,
|
||||
location_lat DECIMAL(10, 8) NOT NULL,
|
||||
location_lng DECIMAL(11, 8) NOT NULL,
|
||||
location_accuracy DECIMAL(10, 2),
|
||||
date DATE NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'planned',
|
||||
mission_ids TEXT[] DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Missions
|
||||
CREATE TABLE IF NOT EXISTS missions (
|
||||
id VARCHAR(32) PRIMARY KEY,
|
||||
session_id VARCHAR(32) NOT NULL REFERENCES field_sessions(id),
|
||||
location_lat DECIMAL(10, 8) NOT NULL,
|
||||
location_lng DECIMAL(11, 8) NOT NULL,
|
||||
location_accuracy DECIMAL(10, 2),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'created',
|
||||
device_model VARCHAR(100) NOT NULL,
|
||||
device_os VARCHAR(100) NOT NULL,
|
||||
device_app_version VARCHAR(50) NOT NULL,
|
||||
artifact_ids TEXT[] DEFAULT '{}',
|
||||
observation_ids TEXT[] DEFAULT '{}',
|
||||
sequence_number INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Artifacts
|
||||
CREATE TABLE IF NOT EXISTS artifacts (
|
||||
id VARCHAR(32) PRIMARY KEY,
|
||||
type VARCHAR(50) NOT NULL,
|
||||
version_major INTEGER NOT NULL DEFAULT 1,
|
||||
version_minor INTEGER NOT NULL DEFAULT 0,
|
||||
version_patch INTEGER NOT NULL DEFAULT 0,
|
||||
hash_algorithm VARCHAR(20) NOT NULL DEFAULT 'sha256',
|
||||
hash_value VARCHAR(64) NOT NULL,
|
||||
created_by VARCHAR(100) NOT NULL,
|
||||
storage_protocol VARCHAR(20) NOT NULL,
|
||||
storage_bucket VARCHAR(200),
|
||||
storage_path TEXT NOT NULL,
|
||||
parent_id VARCHAR(32) REFERENCES artifacts(id),
|
||||
lineage TEXT[] DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Decision Cases
|
||||
CREATE TABLE IF NOT EXISTS decision_cases (
|
||||
id VARCHAR(32) PRIMARY KEY,
|
||||
mission_id VARCHAR(32) NOT NULL REFERENCES missions(id),
|
||||
title VARCHAR(500) NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
priority VARCHAR(20) NOT NULL,
|
||||
confidence VARCHAR(20) NOT NULL,
|
||||
recommended_action TEXT NOT NULL,
|
||||
observation_ids TEXT[] DEFAULT '{}',
|
||||
evidence_ids TEXT[] DEFAULT '{}',
|
||||
finding_id VARCHAR(32) NOT NULL,
|
||||
decision_id VARCHAR(32) NOT NULL,
|
||||
review_id VARCHAR(32) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
version INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Indexes for common queries
|
||||
CREATE INDEX IF NOT EXISTS idx_missions_session_id ON missions(session_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_missions_status ON missions(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_decision_cases_mission_id ON decision_cases(mission_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_decision_cases_status ON decision_cases(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_field_sessions_date ON field_sessions(date);
|
||||
CREATE INDEX IF NOT EXISTS idx_field_sessions_status ON field_sessions(status);
|
||||
|
||||
-- Update trigger for updated_at
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
|
||||
CREATE TRIGGER update_field_sessions_updated_at BEFORE UPDATE ON field_sessions
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_missions_updated_at BEFORE UPDATE ON missions
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
Reference in New Issue
Block a user