Implement PostgreSQL production store path
All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 41s
All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 41s
Add the PostgreSQL backend, migration and stopped-write transfer tools, lease-aware deployment manifests, tenancy declarations, and shared conformance coverage. Persist grouping mutations in durable stores and separate process liveness from database readiness.
This commit is contained in:
parent
2063470ac8
commit
749461b97b
30 changed files with 2364 additions and 71 deletions
82
migrations/postgres/0001_tenant_store.sql
Normal file
82
migrations/postgres/0001_tenant_store.sql
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tenants (
|
||||
tenant_id TEXT PRIMARY KEY,
|
||||
identifier TEXT UNIQUE NOT NULL,
|
||||
grouping_name TEXT NOT NULL,
|
||||
display_name TEXT,
|
||||
contact_email TEXT,
|
||||
lifecycle TEXT NOT NULL DEFAULT 'active'
|
||||
CHECK (lifecycle IN ('active', 'retired')),
|
||||
version BIGINT NOT NULL DEFAULT 1 CHECK (version > 0),
|
||||
-- Pre-lifecycle SQLite rows legitimately carry no timestamp. Nullable here
|
||||
-- preserves them exactly during the store move; new domain writes set both.
|
||||
created_at TIMESTAMPTZ,
|
||||
updated_at TIMESTAMPTZ,
|
||||
retired_at TIMESTAMPTZ,
|
||||
reactivated_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS grants (
|
||||
grant_id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL REFERENCES tenants(tenant_id),
|
||||
role TEXT NOT NULL,
|
||||
grant_reason TEXT NOT NULL,
|
||||
plan_id TEXT,
|
||||
granted_by TEXT NOT NULL,
|
||||
granted_at TIMESTAMPTZ NOT NULL,
|
||||
correlation_id TEXT NOT NULL,
|
||||
revoked_at TIMESTAMPTZ
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS grants_tenant_active_idx
|
||||
ON grants (tenant_id) WHERE revoked_at IS NULL;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS plans (
|
||||
tenant_id TEXT PRIMARY KEY REFERENCES tenants(tenant_id),
|
||||
plan_id TEXT NOT NULL,
|
||||
assigned_at TIMESTAMPTZ NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS events (
|
||||
seq BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
event_type TEXT NOT NULL,
|
||||
tenant_id TEXT NOT NULL REFERENCES tenants(tenant_id),
|
||||
at TIMESTAMPTZ NOT NULL,
|
||||
payload JSONB NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS events_tenant_seq_idx ON events (tenant_id, seq);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS idempotency_receipts (
|
||||
tenant_id TEXT NOT NULL REFERENCES tenants(tenant_id),
|
||||
idempotency_key TEXT NOT NULL,
|
||||
request_fingerprint TEXT NOT NULL,
|
||||
result JSONB NOT NULL,
|
||||
recorded_at TIMESTAMPTZ NOT NULL,
|
||||
PRIMARY KEY (tenant_id, idempotency_key)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS guardrail_overrides (
|
||||
tenant_id TEXT NOT NULL REFERENCES tenants(tenant_id),
|
||||
limit_key TEXT NOT NULL,
|
||||
kind TEXT NOT NULL,
|
||||
amount TEXT NOT NULL,
|
||||
currency TEXT,
|
||||
period TEXT,
|
||||
PRIMARY KEY (tenant_id, limit_key)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS guardrail_changes (
|
||||
change_id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL REFERENCES tenants(tenant_id),
|
||||
limit_key TEXT NOT NULL,
|
||||
previous JSONB,
|
||||
current JSONB,
|
||||
changed_by TEXT NOT NULL,
|
||||
reason TEXT NOT NULL,
|
||||
correlation_id TEXT NOT NULL,
|
||||
changed_at TIMESTAMPTZ NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS guardrail_changes_tenant_time_idx
|
||||
ON guardrail_changes (tenant_id, changed_at, change_id);
|
||||
|
||||
COMMIT;
|
||||
Loading…
Add table
Add a link
Reference in a new issue