34 lines
1.4 KiB
MySQL
34 lines
1.4 KiB
MySQL
|
|
-- WP-0006-T04: hosted Target Ledger append API.
|
||
|
|
-- Depends on migrations/0001_registries.sql (phase_manifests, licensors).
|
||
|
|
|
||
|
|
BEGIN;
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS ledger_entries (
|
||
|
|
sequence bigint GENERATED ALWAYS AS IDENTITY,
|
||
|
|
entry_id text NOT NULL,
|
||
|
|
phase_id text NOT NULL REFERENCES phase_manifests(phase_id),
|
||
|
|
entry jsonb NOT NULL,
|
||
|
|
previous_entry_hash text NOT NULL,
|
||
|
|
signature text NOT NULL,
|
||
|
|
recognized_at timestamptz NOT NULL,
|
||
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
||
|
|
PRIMARY KEY (phase_id, sequence),
|
||
|
|
UNIQUE (entry_id)
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Ordering within a Phase must be exactly append order for the fold and
|
||
|
|
-- hash chain to mean anything; index supports the ORDER BY sequence read
|
||
|
|
-- path (registry/ledger.py get_ledger()).
|
||
|
|
CREATE INDEX IF NOT EXISTS ledger_entries_phase_sequence_idx
|
||
|
|
ON ledger_entries (phase_id, sequence);
|
||
|
|
|
||
|
|
GRANT SELECT, INSERT ON ledger_entries TO trf_app;
|
||
|
|
-- Deliberately no UPDATE, no DELETE, and no direct control over `sequence`
|
||
|
|
-- (GENERATED ALWAYS AS IDENTITY — trf_app cannot even attempt to set it) for
|
||
|
|
-- trf_app: append-only is a database fact here, matching phase_manifests
|
||
|
|
-- and extensions in migrations/0001_registries.sql, not merely an API
|
||
|
|
-- design intention (ADR-0002 compensating guardrail 2).
|
||
|
|
GRANT USAGE, SELECT ON ledger_entries_sequence_seq TO trf_app;
|
||
|
|
|
||
|
|
COMMIT;
|