83 lines
3.6 KiB
PL/PgSQL
83 lines
3.6 KiB
PL/PgSQL
BEGIN;
|
|
|
|
CREATE TABLE tenant (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
public_id uuid NOT NULL UNIQUE DEFAULT gen_random_uuid(),
|
|
name varchar(200) NOT NULL,
|
|
status varchar(32) NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'suspended', 'closed')),
|
|
version bigint NOT NULL DEFAULT 1 CHECK (version > 0),
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
deleted_at timestamptz
|
|
);
|
|
|
|
CREATE TABLE user_account (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
public_id uuid NOT NULL UNIQUE DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenant(id),
|
|
identity_subject varchar(255) NOT NULL,
|
|
display_name varchar(120),
|
|
status varchar(32) NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'disabled', 'deleted')),
|
|
version bigint NOT NULL DEFAULT 1 CHECK (version > 0),
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
deleted_at timestamptz,
|
|
UNIQUE (tenant_id, identity_subject)
|
|
);
|
|
|
|
CREATE TABLE audit_event (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid REFERENCES tenant(id),
|
|
actor_type varchar(32) NOT NULL,
|
|
actor_public_id uuid,
|
|
action varchar(120) NOT NULL,
|
|
resource_type varchar(80) NOT NULL,
|
|
resource_id uuid,
|
|
request_id varchar(128),
|
|
purpose varchar(255),
|
|
result varchar(32) NOT NULL CHECK (result IN ('success', 'failure', 'denied')),
|
|
detail jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
occurred_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
CREATE INDEX audit_event_tenant_time_idx ON audit_event (tenant_id, occurred_at DESC);
|
|
CREATE INDEX audit_event_request_idx ON audit_event (request_id) WHERE request_id IS NOT NULL;
|
|
|
|
CREATE TABLE idempotency_record (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid REFERENCES tenant(id),
|
|
scope varchar(120) NOT NULL,
|
|
idempotency_key varchar(255) NOT NULL,
|
|
request_hash char(64) NOT NULL,
|
|
state varchar(24) NOT NULL CHECK (state IN ('processing', 'completed', 'failed')),
|
|
response_status integer,
|
|
response_body jsonb,
|
|
resource_id uuid,
|
|
expires_at timestamptz NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE (tenant_id, scope, idempotency_key)
|
|
);
|
|
CREATE INDEX idempotency_record_expiry_idx ON idempotency_record (expires_at);
|
|
|
|
CREATE TABLE outbox_event (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid REFERENCES tenant(id),
|
|
aggregate_type varchar(80) NOT NULL,
|
|
aggregate_id uuid NOT NULL,
|
|
event_type varchar(120) NOT NULL,
|
|
payload jsonb NOT NULL,
|
|
status varchar(24) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'completed', 'dead')),
|
|
attempt_count integer NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
|
|
available_at timestamptz NOT NULL DEFAULT now(),
|
|
locked_at timestamptz,
|
|
locked_by varchar(120),
|
|
last_error_code varchar(120),
|
|
completed_at timestamptz,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
CREATE INDEX outbox_event_claim_idx ON outbox_event (status, available_at, created_at)
|
|
WHERE status IN ('pending', 'processing');
|
|
|
|
COMMIT;
|