Package Postgres migrations with user-engine
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

This commit is contained in:
tegwick 2026-07-27 23:20:40 +02:00
parent 2869c1030d
commit c27012afe5
4 changed files with 71 additions and 10 deletions

View file

@ -27,7 +27,7 @@
| workplan | USER-WP-0017 | finished | — | workplans/USER-WP-0017-durable-store-record-serialization.md | | workplan | USER-WP-0017 | finished | — | workplans/USER-WP-0017-durable-store-record-serialization.md |
| workplan | USER-WP-0018 | finished | — | workplans/USER-WP-0018-postgres-store-adapter.md | | workplan | USER-WP-0018 | finished | — | workplans/USER-WP-0018-postgres-store-adapter.md |
| workplan | USER-WP-0019 | finished | — | workplans/USER-WP-0019-provider-backed-postgres-conformance.md | | workplan | USER-WP-0019 | finished | — | workplans/USER-WP-0019-provider-backed-postgres-conformance.md |
| workplan | USER-WP-0020 | ready | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md | | workplan | USER-WP-0020 | active | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md |
| task | USER-WP-0001-T1 | done | — | workplans/USER-WP-0001-preparation-and-interface-adoption.md | | task | USER-WP-0001-T1 | done | — | workplans/USER-WP-0001-preparation-and-interface-adoption.md |
| task | USER-WP-0001-T2 | done | — | workplans/USER-WP-0001-preparation-and-interface-adoption.md | | task | USER-WP-0001-T2 | done | — | workplans/USER-WP-0001-preparation-and-interface-adoption.md |
| task | USER-WP-0001-T3 | done | — | workplans/USER-WP-0001-preparation-and-interface-adoption.md | | task | USER-WP-0001-T3 | done | — | workplans/USER-WP-0001-preparation-and-interface-adoption.md |
@ -145,11 +145,11 @@
| task | USER-WP-0019-T3 | done | — | workplans/USER-WP-0019-provider-backed-postgres-conformance.md | | task | USER-WP-0019-T3 | done | — | workplans/USER-WP-0019-provider-backed-postgres-conformance.md |
| task | USER-WP-0019-T4 | done | — | workplans/USER-WP-0019-provider-backed-postgres-conformance.md | | task | USER-WP-0019-T4 | done | — | workplans/USER-WP-0019-provider-backed-postgres-conformance.md |
| task | USER-WP-0019-T5 | done | — | workplans/USER-WP-0019-provider-backed-postgres-conformance.md | | task | USER-WP-0019-T5 | done | — | workplans/USER-WP-0019-provider-backed-postgres-conformance.md |
| task | USER-WP-0020-T01 | todo | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md | | task | USER-WP-0020-T01 | done | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md |
| task | USER-WP-0020-T02 | wait | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md | | task | USER-WP-0020-T02 | progress | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md |
| task | USER-WP-0020-T03 | wait | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md | | task | USER-WP-0020-T03 | progress | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md |
| task | USER-WP-0020-T04 | wait | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md | | task | USER-WP-0020-T04 | progress | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md |
| task | USER-WP-0020-T05 | wait | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md | | task | USER-WP-0020-T05 | progress | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md |
| task | USER-WP-0020-T06 | wait | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md | | task | USER-WP-0020-T06 | wait | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md |
| task | USER-WP-0020-T07 | wait | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md | | task | USER-WP-0020-T07 | wait | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md |
| task | USER-WP-0020-T08 | wait | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md | | task | USER-WP-0020-T08 | wait | — | workplans/USER-WP-0020-self-service-and-user-administration-portal.md |

View file

@ -17,6 +17,9 @@ build-backend = "setuptools.build_meta"
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
where = ["src"] where = ["src"]
[tool.setuptools.package-data]
user_engine = ["migrations/postgres/*.sql"]
[tool.user-engine] [tool.user-engine]
package = "user_engine" package = "user_engine"
workplan = "USER-WP-0006" workplan = "USER-WP-0006"

View file

@ -9,7 +9,7 @@ from __future__ import annotations
import json import json
from contextlib import contextmanager from contextlib import contextmanager
from pathlib import Path from importlib.resources import files
from typing import Any, Iterable, Iterator, Mapping, Protocol, cast from typing import Any, Iterable, Iterator, Mapping, Protocol, cast
from user_engine.domain import ( from user_engine.domain import (
@ -624,9 +624,10 @@ def _first_column(row: Any) -> Any:
def _load_bootstrap_sql() -> str: def _load_bootstrap_sql() -> str:
repo_root = Path(__file__).resolve().parents[3] return (
return (repo_root / "migrations/postgres/0001_user_engine_store.sql").read_text( files("user_engine")
encoding="utf-8" .joinpath("migrations/postgres/0001_user_engine_store.sql")
.read_text(encoding="utf-8")
) )

View file

@ -0,0 +1,57 @@
CREATE TABLE IF NOT EXISTS user_engine_schema_versions (
version text PRIMARY KEY,
name text NOT NULL,
applied_at timestamptz NOT NULL DEFAULT now(),
checksum text
);
CREATE TABLE IF NOT EXISTS user_engine_records (
record_type text NOT NULL,
record_key text NOT NULL,
tenant text,
user_id text,
application_id text,
scope_type text,
scope_id text,
payload jsonb NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (record_type, record_key)
);
CREATE INDEX IF NOT EXISTS user_engine_records_tenant_idx ON user_engine_records (tenant, record_type);
CREATE INDEX IF NOT EXISTS user_engine_records_user_idx ON user_engine_records (user_id, record_type);
CREATE INDEX IF NOT EXISTS user_engine_records_application_idx ON user_engine_records (application_id, record_type);
CREATE INDEX IF NOT EXISTS user_engine_records_scope_idx ON user_engine_records (scope_type, scope_id, record_type);
CREATE TABLE IF NOT EXISTS user_engine_audit_records (
audit_id text PRIMARY KEY,
tenant text NOT NULL,
actor_issuer text NOT NULL,
actor_subject text NOT NULL,
action text NOT NULL,
subject text NOT NULL,
correlation_id text NOT NULL,
summary text,
payload jsonb NOT NULL,
recorded_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS user_engine_audit_records_tenant_idx ON user_engine_audit_records (tenant, recorded_at);
CREATE INDEX IF NOT EXISTS user_engine_audit_records_subject_idx ON user_engine_audit_records (subject, recorded_at);
CREATE TABLE IF NOT EXISTS user_engine_outbox_events (
event_id text PRIMARY KEY,
tenant text NOT NULL,
event_type text NOT NULL,
aggregate_id text NOT NULL,
correlation_id text NOT NULL,
payload jsonb NOT NULL,
occurred_at timestamptz NOT NULL DEFAULT now(),
claimed_at timestamptz,
claimed_by text,
delivered_at timestamptz,
failed_at timestamptz,
failure_reason text
);
CREATE INDEX IF NOT EXISTS user_engine_outbox_events_pending_idx
ON user_engine_outbox_events (occurred_at)
WHERE claimed_at IS NULL AND delivered_at IS NULL;
INSERT INTO user_engine_schema_versions (version, name)
VALUES ('0001_initial', 'initial durable store')
ON CONFLICT (version) DO NOTHING;