Some checks failed
CI / Frontend Lint (push) Has been cancelled
CI / Frontend Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Frontend E2E Tests (push) Has been cancelled
CI / Orchestrator Build (push) Has been cancelled
CI / Contracts Compile (push) Has been cancelled
CI / Contracts Test (push) Has been cancelled
Security Scan / Dependency Vulnerability Scan (push) Has been cancelled
Security Scan / OWASP ZAP Scan (push) Has been cancelled
44 lines
1.4 KiB
TypeScript
44 lines
1.4 KiB
TypeScript
import { query } from "../postgres";
|
|
|
|
/**
|
|
* Migration 003 — append-only events journal (arch §4.5, §5.5, §7).
|
|
*
|
|
* The `events` table is the system-of-record for normalised workflow
|
|
* events (arch §7.2: `transaction.created`, `instrument.ready`,
|
|
* `payment.settled`, `transaction.committed`, …). It is:
|
|
*
|
|
* - append-only (no UPDATE / DELETE)
|
|
* - signed (HMAC of (plan_id, type, payload_hash, prev_hash))
|
|
* - hash-chained via prev_hash for tamper-evident forensic replay
|
|
* - indexed by plan_id so the SSE endpoint can stream efficiently
|
|
*/
|
|
export async function up() {
|
|
await query(
|
|
`CREATE TABLE IF NOT EXISTS events (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
plan_id UUID NOT NULL REFERENCES plans(plan_id) ON DELETE CASCADE,
|
|
type VARCHAR(128) NOT NULL,
|
|
actor VARCHAR(255),
|
|
payload JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
payload_hash CHAR(64) NOT NULL,
|
|
prev_hash CHAR(64),
|
|
signature CHAR(64) NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
)`,
|
|
);
|
|
|
|
await query(
|
|
`CREATE INDEX IF NOT EXISTS idx_events_plan_id_created
|
|
ON events(plan_id, created_at)`,
|
|
);
|
|
|
|
await query(
|
|
`CREATE INDEX IF NOT EXISTS idx_events_type
|
|
ON events(type)`,
|
|
);
|
|
}
|
|
|
|
export async function down() {
|
|
await query("DROP TABLE IF EXISTS events CASCADE");
|
|
}
|