addition of new dashboard

This commit is contained in:
2026-08-20 15:08:32 +00:00
parent 0622018d95
commit bf59249ed7
161 changed files with 13170 additions and 119 deletions

View File

@@ -0,0 +1,45 @@
-- DROP TABLE IF EXISTS public.user CASCADE;
CREATE TABLE public.user (
id BIGSERIAL PRIMARY KEY,
username TEXT,
photo TEXT,
issuer TEXT NOT NULL,
type TEXT NOT NULL,
identifier TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__user__issuer_identifier UNIQUE (issuer, identifier)
);
CREATE INDEX idx__user__username ON public.user (username);
CREATE INDEX idx__user__identifier ON public.user (identifier);
CREATE INDEX idx__user__type ON public.user (type);
CREATE INDEX idx__user__issuer ON public.user (issuer);
CREATE INDEX idx__user__created_ts ON public.user (created_ts);
CREATE INDEX idx__user__updated_ts ON public.user (updated_ts);
-- DROP TABLE IF EXISTS public.app CASCADE;
CREATE TABLE public.app (
id BIGSERIAL PRIMARY KEY,
type TEXT UNIQUE NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__app__type ON public.app (type);
CREATE INDEX idx__app__created_ts ON public.app (created_ts);
CREATE INDEX idx__app__updated_ts ON public.app (updated_ts);
-- DROP TABLE IF EXISTS public.auth CASCADE;
CREATE TABLE public.auth (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
app_id BIGINT NOT NULL REFERENCES public.app(id),
api_key TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__auth__user_id_app_id UNIQUE (user_id, app_id)
);
CREATE INDEX idx__auth__user_id ON public.auth (user_id);
CREATE INDEX idx__auth__app_id ON public.auth (app_id);
CREATE INDEX idx__auth__api_key ON public.auth (api_key);
CREATE INDEX idx__auth__created_ts ON public.auth (created_ts);
CREATE INDEX idx__auth__updated_ts ON public.auth (updated_ts);

View File

@@ -0,0 +1,42 @@
CREATE TYPE HASH_TYPE AS ENUM ('SHA256');
CREATE TYPE SIGNATURE_TYPE AS ENUM ('JWS/JCS');
-- DROP TABLE IF EXISTS public.audit CASCADE;
CREATE TABLE public.audit (
audit_id BIGSERIAL PRIMARY KEY,
version SMALLINT NOT NULL,
event_id UUID,
agreement_id UUID,
hash_type HASH_TYPE NOT NULL,
digest TEXT NOT NULL,
created BIGINT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__audit__event_id ON public.audit (event_id);
CREATE INDEX idx__public__audit__agreement_id ON public.audit (agreement_id);
CREATE INDEX idx__public__audit__created ON public.audit (created);
CREATE INDEX idx__public__audit__created_ts ON public.audit (created_ts);
CREATE INDEX idx__public__audit__updated_ts ON public.audit (updated_ts);
ALTER TABLE public.audit
ADD CONSTRAINT cnst__audit__event_or_agreement
CHECK (num_nonnulls(event_id, agreement_id) = 1);
-- DROP TABLE IF EXISTS public.audit_signature CASCADE;
CREATE TABLE public.audit_signature (
signature_id BIGSERIAL PRIMARY KEY,
audit_id BIGINT NOT NULL REFERENCES public.audit(audit_id),
version SMALLINT NOT NULL,
id TEXT NOT NULL,
signedOn BIGINT NOT NULL,
type SIGNATURE_TYPE NOT NULL,
jws TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__audit_signature__id ON public.audit_signature (id);
CREATE INDEX idx__public__audit_signature__signedOn ON public.audit_signature (signedOn);
CREATE INDEX idx__public__audit_signature__type ON public.audit_signature (type);
CREATE INDEX idx__public__audit_signature__created_ts ON public.audit_signature (created_ts);
CREATE INDEX idx__public__audit_signature__updated_ts ON public.audit_signature (updated_ts);

View File

@@ -0,0 +1,28 @@
-- DROP TABLE IF EXISTS public.usage_url CASCADE;
CREATE TABLE public.usage_url (
id BIGSERIAL PRIMARY KEY,
url TEXT NOT NULL,
module TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__usage_url__url_module UNIQUE (url, module)
);
CREATE INDEX idx__public__usage_url__url ON public.usage_url (url);
CREATE INDEX idx__public__usage_url__module ON public.usage_url (module);
CREATE INDEX idx__public__usage_url__created_ts ON public.usage_url (created_ts);
CREATE INDEX idx__public__usage_url__updated_ts ON public.usage_url (updated_ts);
-- DROP TABLE IF EXISTS public.usage CASCADE;
CREATE TABLE public.usage (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
usage_url_id BIGINT NOT NULL REFERENCES public.usage_url(id),
success BOOLEAN NOT NULL DEFAULT TRUE,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__usage__user_id ON public.usage (user_id);
CREATE INDEX idx__public__usage__usage_url_id ON public.usage (usage_url_id);
CREATE INDEX idx__public__usage__success ON public.usage (success);
CREATE INDEX idx__public__usage__created_ts ON public.usage (created_ts);
CREATE INDEX idx__public__usage__updated_ts ON public.usage (updated_ts);

View File

@@ -0,0 +1,220 @@
-- Agreements
-- DROP TABLE IF EXISTS public.agreement CASCADE;
CREATE TABLE public.agreement (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT REFERENCES public.user(id),
version SMALLINT NOT NULL,
parent TEXT NOT NULL,
agreement_id_uuid UUID UNIQUE NOT NULL,
created BIGINT NOT NULL,
created_as_ts TIMESTAMPTZ NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__agreement__user_id ON public.agreement (user_id);
CREATE INDEX idx__public__agreement__version ON public.agreement (version);
CREATE INDEX idx__public__agreement__parent ON public.agreement (parent);
CREATE INDEX idx__public__agreement__agreement_id_uuid ON public.agreement (agreement_id_uuid);
CREATE INDEX idx__public__agreement__created ON public.agreement (created);
CREATE INDEX idx__public__agreement__created_as_ts ON public.agreement (created_as_ts);
CREATE INDEX idx__public__agreement__created_ts ON public.agreement (created_ts);
CREATE INDEX idx__public__agreement__updated_ts ON public.agreement (updated_ts);
-- DROP TABLE IF EXISTS public.agreement_required_id CASCADE;
CREATE TABLE public.agreement_required_id (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
agreement_id BIGINT NOT NULL REFERENCES public.agreement(id),
required_id TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__agreement_required_id UNIQUE (user_id, agreement_id, required_id)
);
CREATE INDEX idx__public__agreement_required_id__user_id ON public.agreement_required_id (user_id);
CREATE INDEX idx__public__agreement_required_id__agreement_id ON public.agreement_required_id (agreement_id);
CREATE INDEX idx__public__agreement_required_id__created_ts ON public.agreement_required_id (created_ts);
CREATE INDEX idx__public__agreement_required_id__updated_ts ON public.agreement_required_id (updated_ts);
-- DROP TABLE IF EXISTS public.purpose CASCADE;
CREATE TABLE public.purpose (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
value TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__purpose UNIQUE (user_id, value)
);
CREATE INDEX idx__public__purpose__user_id ON public.purpose (user_id);
CREATE INDEX idx__public__purpose__value ON public.purpose (value);
CREATE INDEX idx__public__purpose__created_ts ON public.purpose (created_ts);
CREATE INDEX idx__public__purpose__updated_ts ON public.purpose (updated_ts);
-- DROP TABLE IF EXISTS public.agreement_purpose CASCADE;
CREATE TABLE public.agreement_purpose (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
agreement_id BIGINT NOT NULL REFERENCES public.agreement(id),
purpose_id BIGINT NOT NULL REFERENCES public.purpose(id),
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__agreement_purpose UNIQUE (user_id, agreement_id, purpose_id)
);
CREATE INDEX idx__public__agreement_purpose__user_id ON public.agreement_purpose (user_id);
CREATE INDEX idx__public__agreement_purpose__agreement_id ON public.agreement_purpose (agreement_id);
CREATE INDEX idx__public__agreement_purpose__purpose_id ON public.agreement_purpose (purpose_id);
CREATE INDEX idx__public__agreement_purpose__created_ts ON public.agreement_purpose (created_ts);
CREATE INDEX idx__public__agreement_purpose__updated_ts ON public.agreement_purpose (updated_ts);
-- DROP TABLE IF EXISTS public.caveat CASCADE;
CREATE TABLE public.caveat (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
value TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__caveat UNIQUE (user_id, value)
);
CREATE INDEX idx__public__caveat__user_id ON public.caveat (user_id);
CREATE INDEX idx__public__caveat__value ON public.caveat (value);
CREATE INDEX idx__public__caveat__created_ts ON public.caveat (created_ts);
CREATE INDEX idx__public__caveat__updated_ts ON public.caveat (updated_ts);
-- DROP TABLE IF EXISTS public.agreement_caveat CASCADE;
CREATE TABLE public.agreement_caveat (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
agreement_id BIGINT NOT NULL REFERENCES public.agreement(id),
caveat_id BIGINT NOT NULL REFERENCES public.caveat(id),
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__agreement_caveat UNIQUE (user_id, agreement_id, caveat_id)
);
CREATE INDEX idx__public__agreement_caveat__user_id ON public.agreement_caveat (user_id);
CREATE INDEX idx__public__agreement_caveat__agreement_id ON public.agreement_caveat (agreement_id);
CREATE INDEX idx__public__agreement_caveat__caveat_id ON public.agreement_caveat (caveat_id);
CREATE INDEX idx__public__agreement_caveat__created_ts ON public.agreement_caveat (created_ts);
CREATE INDEX idx__public__agreement_caveat__updated_ts ON public.agreement_caveat (updated_ts);
-- DROP TABLE IF EXISTS public.role CASCADE;
CREATE TABLE public.role (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
value TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__role UNIQUE (user_id, value)
);
CREATE INDEX idx__public__role__user_id ON public.role (user_id);
CREATE INDEX idx__public__role__value ON public.role (value);
CREATE INDEX idx__public__role__created_ts ON public.role (created_ts);
CREATE INDEX idx__public__role__updated_ts ON public.role (updated_ts);
-- DROP TABLE IF EXISTS public.agreement_role CASCADE;
CREATE TABLE public.agreement_role (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
agreement_id BIGINT NOT NULL REFERENCES public.agreement(id),
role_id BIGINT NOT NULL REFERENCES public.role(id),
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__agreement_role UNIQUE (user_id, agreement_id, role_id)
);
CREATE INDEX idx__public__agreement_role__user_id ON public.agreement_role (user_id);
CREATE INDEX idx__public__agreement_role__agreement_id ON public.agreement_role (agreement_id);
CREATE INDEX idx__public__agreement_role__role_id ON public.agreement_role (role_id);
CREATE INDEX idx__public__agreement_role__created_ts ON public.agreement_role (created_ts);
CREATE INDEX idx__public__agreement_role__updated_ts ON public.agreement_role (updated_ts);
-- Events
-- DROP TABLE IF EXISTS public.event_type CASCADE;
CREATE TABLE public.event_type (
id BIGSERIAL PRIMARY KEY,
value TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__event_type__value ON public.event_type (value);
CREATE INDEX idx__public__event_type__created_ts ON public.event_type (created_ts);
CREATE INDEX idx__public__event_type__updated_ts ON public.event_type (updated_ts);
INSERT INTO public.event_type (value) VALUES ('data');
-- DROP TABLE IF EXISTS public.event CASCADE;
CREATE TABLE public.event (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
version SMALLINT NOT NULL,
event_id_uuid UUID UNIQUE NOT NULL,
event_type_id BIGINT NOT NULL REFERENCES public.event_type(id),
agreement_id BIGINT NOT NULL REFERENCES public.agreement(id),
sender_id TEXT NOT NULL,
recipient_id TEXT NOT NULL,
created BIGINT NOT NULL,
created_as_ts TIMESTAMPTZ NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__event__user_id ON public.event (user_id);
CREATE INDEX idx__public__event__version ON public.event (version);
CREATE INDEX idx__public__event__event_id_uuid ON public.event (event_id_uuid);
CREATE INDEX idx__public__event__event_type_id ON public.event (event_type_id);
CREATE INDEX idx__public__event__agreement_id ON public.event (agreement_id);
CREATE INDEX idx__public__event__sender_id ON public.event (sender_id);
CREATE INDEX idx__public__event__recipient_id ON public.event (recipient_id);
CREATE INDEX idx__public__event__created_ts ON public.event (created_ts);
CREATE INDEX idx__public__event__updated_ts ON public.event (updated_ts);
-- DROP TABLE IF EXISTS public.event_data CASCADE;
-- DROP SEQUENCE IF EXISTS seq__event_data__id;
-- CREATE SEQUENCE seq__event_data__id;
-- CREATE TABLE public.event_data (
-- id BIGINT NOT NULL DEFAULT nextval('seq__event_data__id'),
-- user_id BIGINT NOT NULL REFERENCES public.user(id),
-- event_id BIGINT NOT NULL REFERENCES public.event(id),
-- data TEXT NOT NULL,
-- created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- PRIMARY KEY (user_id, id)
-- ) PARTITION BY LIST (user_id);
CREATE TABLE public.event_data (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
event_id BIGINT NOT NULL REFERENCES public.event(id),
data TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__event_data__event_id ON public.event_data (event_id);
CREATE INDEX idx__public__event_data__user_id ON public.event_data (user_id);
CREATE INDEX idx__public__event_data__created_ts ON public.event_data (created_ts);
CREATE INDEX idx__public__event_data__updated_ts ON public.event_data (updated_ts);
-- Signatures
-- DROP TABLE IF EXISTS public.signature CASCADE;
CREATE TABLE public.signature (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
version SMALLINT NOT NULL,
signer_id TEXT NOT NULL,
signed_on BIGINT NOT NULL,
type TEXT NOT NULL,
jws TEXT NOT NULL,
role_id BIGINT REFERENCES public.role(id),
agreement_id BIGINT REFERENCES public.agreement(id),
event_id BIGINT REFERENCES public.event(id),
signed_on_as_ts TIMESTAMPTZ NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__signature__agreement UNIQUE (user_id, signer_id, agreement_id),
CONSTRAINT uniq__signature__event UNIQUE (user_id, signer_id, event_id)
);
CREATE INDEX idx__public__signature__user_id ON public.signature (user_id);
CREATE INDEX idx__public__signature__version ON public.signature (version);
CREATE INDEX idx__public__signature__signed_on ON public.signature (signed_on);
CREATE INDEX idx__public__signature__role_id ON public.signature (role_id);
CREATE INDEX idx__public__signature__agreement_id ON public.signature (agreement_id);
CREATE INDEX idx__public__signature__event_id ON public.signature (event_id);
CREATE INDEX idx__public__signature__signed_on_as_ts ON public.signature (signed_on_as_ts);
CREATE INDEX idx__public__signature__created_ts ON public.signature (created_ts);
CREATE INDEX idx__public__signature__updated_ts ON public.signature (updated_ts);

View File

@@ -0,0 +1,19 @@
-- DROP TABLE IF EXISTS public.entity CASCADE;
CREATE TABLE public.entity (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
fedid_url TEXT NOT NULL,
short_name TEXT NOT NULL,
did_id TEXT NOT NULL,
control_private_key_b64u TEXT NOT NULL,
recovery_private_key_b64u TEXT NOT NULL,
did_doc JSONB NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__entity__user_id ON public.entity (user_id);
CREATE INDEX idx__public__entity__fedid_url ON public.entity (fedid_url);
CREATE INDEX idx__public__entity__short_name ON public.entity (short_name);
CREATE INDEX idx__public__entity__did_id ON public.entity (did_id);
CREATE INDEX idx__public__entity__created_ts ON public.entity (created_ts);
CREATE INDEX idx__public__entity__updated_ts ON public.entity (updated_ts);

View File

@@ -0,0 +1,14 @@
-- DROP TABLE IF EXISTS public.agreement_content CASCADE;
CREATE TABLE public.agreement_content (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT REFERENCES public.user(id),
title TEXT NOT NULL,
markdown TEXT NOT NULL,
hash TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__agreement_content UNIQUE NULLS NOT DISTINCT (user_id, title)
);
CREATE INDEX idx__public__agreement_content__user_id ON public.agreement_content (user_id);
CREATE INDEX idx__public__agreement_content__created_ts ON public.agreement_content (created_ts);
CREATE INDEX idx__public__agreement_content__updated_ts ON public.agreement_content (updated_ts);

View File

@@ -0,0 +1 @@
CREATE INDEX idx__public__audit_signature__audit_id ON public.audit_signature (audit_id);

View File

@@ -0,0 +1,31 @@
-- DROP TABLE IF EXISTS public.event_meta CASCADE;
CREATE TABLE public.event_meta (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
event_id BIGINT NOT NULL REFERENCES public.event(id),
key TEXT NOT NULL,
value TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__event_meta__event_id ON public.event_meta (event_id);
CREATE INDEX idx__public__event_meta__user_id ON public.event_meta (user_id);
CREATE INDEX idx__public__event_meta__key ON public.event_meta (key);
CREATE INDEX idx__public__event_meta__value ON public.event_meta (value);
CREATE INDEX idx__public__event_meta__created_ts ON public.event_meta (created_ts);
CREATE INDEX idx__public__event_meta__updated_ts ON public.event_meta (updated_ts);
-- DROP TABLE IF EXISTS public.audit_meta CASCADE;
CREATE TABLE public.audit_meta (
id BIGSERIAL PRIMARY KEY,
audit_id BIGINT NOT NULL REFERENCES public.audit(audit_id),
key TEXT NOT NULL,
value TEXT NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__audit_meta__audit_id ON public.audit_meta (audit_id);
CREATE INDEX idx__public__audit_meta__key ON public.audit_meta (key);
CREATE INDEX idx__public__audit_meta__value ON public.audit_meta (value);
CREATE INDEX idx__public__audit_meta__created_ts ON public.audit_meta (created_ts);
CREATE INDEX idx__public__audit_meta__updated_ts ON public.audit_meta (updated_ts);

View File

@@ -0,0 +1,45 @@
-- DROP TABLE IF EXISTS public.queue_type CASCADE;
CREATE TABLE public.queue_type (
id BIGSERIAL PRIMARY KEY,
value TEXT NOT NULL UNIQUE,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__queue_type__value ON public.queue_type (value);
CREATE INDEX idx__public__queue_type__created_ts ON public.queue_type (created_ts);
CREATE INDEX idx__public__queue_type__updated_ts ON public.queue_type (updated_ts);
INSERT INTO public.queue_type (value) VALUES ('audit') ON CONFLICT DO NOTHING;
-- DROP TABLE IF EXISTS public.queue_url CASCADE;
CREATE TABLE public.queue_url (
id BIGSERIAL PRIMARY KEY,
value TEXT NOT NULL UNIQUE,
next_run_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__queue_url__value ON public.queue_url (value);
CREATE INDEX idx__public__queue_url__next_run_ts ON public.queue_url (next_run_ts);
CREATE INDEX idx__public__queue_url__created_ts ON public.queue_url (created_ts);
CREATE INDEX idx__public__queue_url__updated_ts ON public.queue_url (updated_ts);
-- DROP TABLE IF EXISTS public.queue CASCADE;
CREATE TABLE public.queue (
id BIGSERIAL PRIMARY KEY,
queue_type_id BIGINT NOT NULL REFERENCES public.queue_type(id),
queue_url_id BIGINT NOT NULL REFERENCES public.queue_url(id),
headers JSON,
data JSON,
run_count BIGINT NOT NULL DEFAULT 0,
last_fail TEXT,
last_run_ts TIMESTAMPTZ,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__queue__queue_type_id ON public.queue (queue_type_id);
CREATE INDEX idx__public__queue__run_count ON public.queue (run_count);
CREATE INDEX idx__public__queue__last_run_ts ON public.queue (last_run_ts);
CREATE INDEX idx__public__queue__created_ts ON public.queue (created_ts);
CREATE INDEX idx__public__queue__updated_ts ON public.queue (updated_ts);

View File

@@ -0,0 +1,11 @@
DO $$ BEGIN
IF EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_name = 'agreement'
AND column_name = 'user_id'
AND is_nullable = 'NO'
) THEN
EXECUTE 'ALTER TABLE agreement ALTER COLUMN user_id DROP NOT NULL';
END IF;
END $$;

View File

@@ -0,0 +1,46 @@
ALTER TABLE public.caveat RENAME TO prohibition;
ALTER TABLE public.prohibition RENAME CONSTRAINT uniq__caveat TO uniq__prohibition;
ALTER INDEX idx__public__caveat__user_id RENAME TO idx__public__prohibition__user_id;
ALTER INDEX idx__public__caveat__value RENAME TO idx__public__prohibition__value;
ALTER INDEX idx__public__caveat__created_ts RENAME TO idx__public__prohibition__created_ts;
ALTER INDEX idx__public__caveat__updated_ts RENAME TO idx__public__prohibition__updated_ts;
ALTER TABLE public.agreement_caveat RENAME TO agreement_prohibition;
ALTER TABLE public.agreement_prohibition RENAME CONSTRAINT uniq__agreement_caveat TO uniq__agreement_prohibition;
ALTER TABLE public.agreement_prohibition RENAME COLUMN caveat_id TO prohibition_id;
ALTER TABLE public.agreement_prohibition
DROP CONSTRAINT IF EXISTS agreement_caveat_caveat_id_fkey,
ADD CONSTRAINT agreement_prohibition_prohibition_id_fkey
FOREIGN KEY (prohibition_id)
REFERENCES public.prohibition(id);
ALTER INDEX idx__public__agreement_caveat__user_id RENAME TO idx__public__agreement_prohibition__user_id;
ALTER INDEX idx__public__agreement_caveat__agreement_id RENAME TO idx__public__agreement_prohibition__agreement_id;
ALTER INDEX idx__public__agreement_caveat__caveat_id RENAME TO idx__public__agreement_prohibition__prohibition_id;
ALTER INDEX idx__public__agreement_caveat__created_ts RENAME TO idx__public__agreement_prohibition__created_ts;
ALTER INDEX idx__public__agreement_caveat__updated_ts RENAME TO idx__public__agreement_prohibition__updated_ts;
ALTER TABLE agreement_content ADD COLUMN key VARCHAR(255) UNIQUE;
CREATE INDEX idx__agreement_content__key ON public.agreement_content (key);
ALTER TABLE agreement_content ADD COLUMN agreement_uuid UUID UNIQUE NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
ALTER TABLE purpose ALTER COLUMN user_id DROP NOT NULL;
ALTER TABLE prohibition ALTER COLUMN user_id DROP NOT NULL;
ALTER TABLE role ALTER COLUMN user_id DROP NOT NULL;
ALTER TABLE agreement_purpose ALTER COLUMN user_id DROP NOT NULL;
ALTER TABLE agreement_prohibition ALTER COLUMN user_id DROP NOT NULL;
ALTER TABLE agreement_role ALTER COLUMN user_id DROP NOT NULL;
ALTER TABLE public.purpose DROP CONSTRAINT uniq__purpose;
CREATE UNIQUE INDEX uniq__purpose ON public.purpose (COALESCE(user_id, -1), value);
ALTER TABLE public.prohibition DROP CONSTRAINT uniq__prohibition;
CREATE UNIQUE INDEX uniq__prohibition ON public.prohibition (COALESCE(user_id, -1), value);
ALTER TABLE public.role DROP CONSTRAINT uniq__role;
CREATE UNIQUE INDEX uniq__role ON public.role (COALESCE(user_id, -1), value);
ALTER TABLE public.agreement_purpose DROP CONSTRAINT uniq__agreement_purpose;
CREATE UNIQUE INDEX uniq__agreement_purpose ON public.agreement_purpose (COALESCE(user_id, -1), agreement_id, purpose_id);
ALTER TABLE public.agreement_prohibition DROP CONSTRAINT uniq__agreement_prohibition;
CREATE UNIQUE INDEX uniq__agreement_prohibition ON public.agreement_prohibition (COALESCE(user_id, -1), agreement_id, prohibition_id);
ALTER TABLE public.agreement_role DROP CONSTRAINT uniq__agreement_role;
CREATE UNIQUE INDEX uniq__agreement_role ON public.agreement_role (COALESCE(user_id, -1), agreement_id, role_id);
ALTER TABLE public.agreement ADD COLUMN context VARCHAR(255) DEFAULT 'https://protocol.jlinc.org/context/jlinc-v7.jsonld';

View File

@@ -0,0 +1 @@
ALTER TABLE public.agreement ALTER COLUMN context SET DEFAULT NULL;

View File

@@ -0,0 +1,29 @@
-- DROP TABLE IF EXISTS public.reference CASCADE;
CREATE TABLE public.reference (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
uri TEXT NOT NULL UNIQUE,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx__public__reference__user_id ON public.reference (user_id);
CREATE INDEX idx__public__reference__created_ts ON public.reference (created_ts);
CREATE INDEX idx__public__reference__updated_ts ON public.reference (updated_ts);
-- DROP TABLE IF EXISTS public.agreement_reference CASCADE;
CREATE TABLE public.agreement_reference (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
agreement_id BIGINT NOT NULL REFERENCES public.agreement(id),
reference_id BIGINT NOT NULL REFERENCES public.reference(id),
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__agreement_reference_id UNIQUE (user_id, agreement_id, reference_id)
);
CREATE INDEX idx__public__agreement_reference__user_id ON public.agreement_reference (user_id);
CREATE INDEX idx__public__agreement_reference__agreement_id ON public.agreement_reference (agreement_id);
CREATE INDEX idx__public__agreement_reference__reference_id ON public.agreement_reference (reference_id);
CREATE INDEX idx__public__agreement_reference__created_ts ON public.agreement_reference (created_ts);
CREATE INDEX idx__public__agreement_reference__updated_ts ON public.agreement_reference (updated_ts);
ALTER TABLE public.agreement ALTER COLUMN parent DROP NOT NULL;

View File

@@ -0,0 +1 @@
ALTER TABLE public.agreement ADD COLUMN public BOOLEAN DEFAULT FALSE;

View File

@@ -0,0 +1,3 @@
ALTER TABLE public.reference DROP CONSTRAINT reference_uri_key;
ALTER TABLE public.reference ADD CONSTRAINT uniq__agreement_reference_uri_user_id UNIQUE (uri, user_id);
CREATE INDEX idx__public__reference__uri ON public.reference (uri);

View File

@@ -0,0 +1,11 @@
-- Session store for express-session (see http/sessionStore.js).
CREATE TABLE IF NOT EXISTS public.session (
sid VARCHAR NOT NULL PRIMARY KEY,
sess JSONB NOT NULL,
expire TIMESTAMPTZ NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx__public__session__expire ON public.session (expire);
CREATE INDEX IF NOT EXISTS idx__public__session__created_ts ON public.session (created_ts);
CREATE INDEX IF NOT EXISTS idx__public__session__updated_ts ON public.session (updated_ts);

View File

@@ -0,0 +1,14 @@
-- Per-tenant read-through cache; updated_ts drives TTL freshness.
CREATE TABLE IF NOT EXISTS public.cache (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
tag TEXT NOT NULL,
data JSONB NOT NULL,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uniq__cache__user_id_tag UNIQUE (user_id, tag)
);
CREATE INDEX IF NOT EXISTS idx__public__cache__user_id ON public.cache (user_id);
CREATE INDEX IF NOT EXISTS idx__public__cache__tag ON public.cache (tag);
CREATE INDEX IF NOT EXISTS idx__public__cache__created_ts ON public.cache (created_ts);
CREATE INDEX IF NOT EXISTS idx__public__cache__updated_ts ON public.cache (updated_ts);

View File

@@ -0,0 +1,21 @@
-- User-managed API keys. key_hash is a salted scrypt digest, so lookups go via
-- the indexed key_prefix rather than the hash.
CREATE TABLE IF NOT EXISTS public.api_key (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES public.user(id),
app_id BIGINT NOT NULL REFERENCES public.app(id),
label TEXT,
key_hash TEXT NOT NULL,
key_prefix TEXT NOT NULL,
expires_ts TIMESTAMPTZ,
last_used_ts TIMESTAMPTZ,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx__public__api_key__key_prefix ON public.api_key (key_prefix);
CREATE INDEX IF NOT EXISTS idx__public__api_key__user_id ON public.api_key (user_id);
CREATE INDEX IF NOT EXISTS idx__public__api_key__app_id ON public.api_key (app_id);
CREATE INDEX IF NOT EXISTS idx__public__api_key__expires_ts ON public.api_key (expires_ts);
CREATE INDEX IF NOT EXISTS idx__public__api_key__last_used_ts ON public.api_key (last_used_ts);
CREATE INDEX IF NOT EXISTS idx__public__api_key__created_ts ON public.api_key (created_ts);
CREATE INDEX IF NOT EXISTS idx__public__api_key__updated_ts ON public.api_key (updated_ts);

View File

@@ -0,0 +1,6 @@
ALTER TABLE public.usage
ADD COLUMN IF NOT EXISTS event_id_uuid UUID,
ADD COLUMN IF NOT EXISTS agreement_id_uuid UUID;
CREATE INDEX IF NOT EXISTS idx__public__usage__event_id_uuid ON public.usage (event_id_uuid);
CREATE INDEX IF NOT EXISTS idx__public__usage__agreement_id_uuid ON public.usage (agreement_id_uuid);

View File

@@ -0,0 +1,30 @@
CREATE TABLE IF NOT EXISTS public.user_type (
id BIGSERIAL PRIMARY KEY,
value TEXT NOT NULL,
can_view_json BOOLEAN NOT NULL DEFAULT FALSE,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- value is the natural key (the unique index also backs the ON CONFLICT below).
CREATE UNIQUE INDEX IF NOT EXISTS idx__public__user_type__value ON public.user_type (value);
CREATE INDEX IF NOT EXISTS idx__public__user_type__created_ts ON public.user_type (created_ts);
CREATE INDEX IF NOT EXISTS idx__public__user_type__updated_ts ON public.user_type (updated_ts);
-- can_view_json is the capability the app reads; roles are defined only here.
INSERT INTO public.user_type (value, can_view_json)
VALUES ('administrator', TRUE), ('full', TRUE), ('standard', FALSE)
ON CONFLICT (value) DO NOTHING;
ALTER TABLE public.user
ADD COLUMN IF NOT EXISTS user_type_id BIGINT REFERENCES public.user_type(id);
CREATE INDEX IF NOT EXISTS idx__public__user__user_type_id ON public.user (user_type_id);
-- Backfill: every existing user becomes an administrator (safe to re-run: only NULLs).
UPDATE public.user
SET user_type_id = (SELECT id FROM public.user_type WHERE value = 'administrator')
WHERE user_type_id IS NULL;
-- All rows are populated and checkUser() always supplies it going forward.
ALTER TABLE public.user ALTER COLUMN user_type_id SET NOT NULL;

View File

@@ -0,0 +1,2 @@
ALTER TABLE public.agreement_content ADD COLUMN IF NOT EXISTS remote_url TEXT;
CREATE INDEX IF NOT EXISTS idx__agreement_content__remote_url ON public.agreement_content(remote_url);

View File

@@ -0,0 +1,15 @@
-- Retry bookkeeping for remote agreement-markdown fetches. Kept separate from
-- agreement_content (which is immutable once inserted) because this state is
-- mutable: attempts and the next scheduled try are updated on each failure and
-- the row is deleted once the content is successfully cached.
CREATE TABLE IF NOT EXISTS public.agreement_fetch (
agreement_uuid UUID PRIMARY KEY,
remote_url TEXT NOT NULL,
attempts INTEGER NOT NULL DEFAULT 0,
next_attempt_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
last_error TEXT,
created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx__public__agreement_fetch__next_attempt_ts ON public.agreement_fetch (next_attempt_ts);