145 lines
4.7 KiB
SQL
145 lines
4.7 KiB
SQL
PRAGMA foreign_keys = ON;
|
|
|
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
version INTEGER PRIMARY KEY,
|
|
applied_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE projects (
|
|
project_id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
created_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE actors (
|
|
actor_id TEXT PRIMARY KEY,
|
|
auth_subject TEXT NOT NULL UNIQUE,
|
|
display_name TEXT NOT NULL,
|
|
created_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE project_memberships (
|
|
project_id TEXT NOT NULL REFERENCES projects(project_id),
|
|
actor_id TEXT NOT NULL REFERENCES actors(actor_id),
|
|
role TEXT NOT NULL CHECK (role IN (
|
|
'SYSTEM','PO','PM','PA','ARCHITECT','LEAD_ENGINEER',
|
|
'IMPLEMENTER','REVIEWER','SECURITY_REVIEWER','OBSERVER'
|
|
)),
|
|
active INTEGER NOT NULL DEFAULT 1 CHECK (active IN (0, 1)),
|
|
created_at TEXT NOT NULL,
|
|
PRIMARY KEY (project_id, actor_id)
|
|
);
|
|
|
|
CREATE TABLE work_packages (
|
|
project_id TEXT NOT NULL REFERENCES projects(project_id),
|
|
work_package_id TEXT NOT NULL,
|
|
title TEXT NOT NULL,
|
|
description TEXT NOT NULL,
|
|
acceptance_criteria_json TEXT NOT NULL,
|
|
status TEXT NOT NULL CHECK (status IN (
|
|
'OPEN','CLAIMED','RESULT_SUBMITTED','IN_REVIEW','REVIEWED',
|
|
'ACCEPTED','REJECTED','CANCELLED'
|
|
)),
|
|
issued_by TEXT NOT NULL REFERENCES actors(actor_id),
|
|
claimed_by TEXT REFERENCES actors(actor_id),
|
|
result_submitted_by TEXT REFERENCES actors(actor_id),
|
|
result_json TEXT,
|
|
accepted_by TEXT REFERENCES actors(actor_id),
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
PRIMARY KEY (project_id, work_package_id)
|
|
);
|
|
CREATE INDEX work_packages_project_status
|
|
ON work_packages(project_id, status, updated_at);
|
|
|
|
CREATE TABLE review_requests (
|
|
project_id TEXT NOT NULL REFERENCES projects(project_id),
|
|
review_id TEXT NOT NULL,
|
|
work_package_id TEXT NOT NULL,
|
|
requested_by TEXT NOT NULL REFERENCES actors(actor_id),
|
|
reviewer_id TEXT NOT NULL REFERENCES actors(actor_id),
|
|
review_type TEXT NOT NULL,
|
|
status TEXT NOT NULL CHECK (status IN ('OPEN','SUBMITTED')),
|
|
verdict TEXT CHECK (verdict IN ('APPROVE','CHANGES_REQUESTED','REJECT')),
|
|
findings_json TEXT,
|
|
created_at TEXT NOT NULL,
|
|
submitted_at TEXT,
|
|
PRIMARY KEY (project_id, review_id),
|
|
FOREIGN KEY (project_id, work_package_id)
|
|
REFERENCES work_packages(project_id, work_package_id)
|
|
);
|
|
CREATE INDEX review_requests_project_status
|
|
ON review_requests(project_id, status, reviewer_id);
|
|
|
|
CREATE TABLE decisions (
|
|
project_id TEXT NOT NULL REFERENCES projects(project_id),
|
|
decision_id TEXT NOT NULL,
|
|
kind TEXT NOT NULL CHECK (kind IN ('PRODUCT','ARCHITECTURE','OPERATIONAL','GATE')),
|
|
title TEXT NOT NULL,
|
|
decision TEXT NOT NULL,
|
|
rationale TEXT NOT NULL,
|
|
decided_by TEXT NOT NULL REFERENCES actors(actor_id),
|
|
work_package_id TEXT,
|
|
created_at TEXT NOT NULL,
|
|
PRIMARY KEY (project_id, decision_id),
|
|
FOREIGN KEY (project_id, work_package_id)
|
|
REFERENCES work_packages(project_id, work_package_id)
|
|
);
|
|
|
|
CREATE TABLE escalations (
|
|
project_id TEXT NOT NULL REFERENCES projects(project_id),
|
|
escalation_id TEXT NOT NULL,
|
|
raised_by TEXT NOT NULL REFERENCES actors(actor_id),
|
|
severity TEXT NOT NULL CHECK (severity IN ('LOW','MEDIUM','HIGH','CRITICAL')),
|
|
title TEXT NOT NULL,
|
|
description TEXT NOT NULL,
|
|
status TEXT NOT NULL CHECK (status IN ('OPEN','RESOLVED')),
|
|
target_role TEXT,
|
|
resolution TEXT,
|
|
resolved_by TEXT REFERENCES actors(actor_id),
|
|
created_at TEXT NOT NULL,
|
|
resolved_at TEXT,
|
|
PRIMARY KEY (project_id, escalation_id)
|
|
);
|
|
|
|
CREATE TABLE event_log (
|
|
cursor INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
event_id TEXT NOT NULL UNIQUE,
|
|
project_id TEXT NOT NULL REFERENCES projects(project_id),
|
|
event_type TEXT NOT NULL,
|
|
actor_id TEXT NOT NULL REFERENCES actors(actor_id),
|
|
actor_role TEXT NOT NULL,
|
|
aggregate_type TEXT NOT NULL,
|
|
aggregate_id TEXT NOT NULL,
|
|
correlation_id TEXT,
|
|
causation_event_id TEXT,
|
|
payload_json TEXT NOT NULL,
|
|
created_at TEXT NOT NULL
|
|
);
|
|
CREATE INDEX event_log_project_cursor ON event_log(project_id, cursor);
|
|
CREATE INDEX event_log_aggregate ON event_log(project_id, aggregate_type, aggregate_id, cursor);
|
|
|
|
CREATE TRIGGER event_log_no_update
|
|
BEFORE UPDATE ON event_log
|
|
BEGIN
|
|
SELECT RAISE(ABORT, 'event_log is append-only');
|
|
END;
|
|
|
|
CREATE TRIGGER event_log_no_delete
|
|
BEFORE DELETE ON event_log
|
|
BEGIN
|
|
SELECT RAISE(ABORT, 'event_log is append-only');
|
|
END;
|
|
|
|
CREATE TABLE idempotency_records (
|
|
project_id TEXT NOT NULL,
|
|
actor_id TEXT NOT NULL,
|
|
idempotency_key TEXT NOT NULL,
|
|
operation TEXT NOT NULL,
|
|
request_hash TEXT NOT NULL,
|
|
response_json TEXT NOT NULL,
|
|
created_at TEXT NOT NULL,
|
|
PRIMARY KEY (project_id, actor_id, idempotency_key)
|
|
);
|