From 05193baff4cd5987cf5fb9e2ce4192182d788457 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Wed, 4 Nov 2026 15:08:36 -0800 Subject: [PATCH] fix(hub): apply the approval rounds migration on every database 0037's journal timestamp sorts before 0036's, so the migrator skipped it on databases already past 0036. 0038 reapplies it idempotently, and a test keeps journal timestamps increasing. --- apps/hub/src/db/migrate.test.ts | 18 + .../0038_approval_round_reapply.sql | 32 + .../src/db/migrations/meta/0038_snapshot.json | 1309 +++++++++++++++++ apps/hub/src/db/migrations/meta/_journal.json | 7 + 4 files changed, 1366 insertions(+) create mode 100644 apps/hub/src/db/migrate.test.ts create mode 100644 apps/hub/src/db/migrations/0038_approval_round_reapply.sql create mode 100644 apps/hub/src/db/migrations/meta/0038_snapshot.json diff --git a/apps/hub/src/db/migrate.test.ts b/apps/hub/src/db/migrate.test.ts new file mode 100644 index 00000000..3ab66517 --- /dev/null +++ b/apps/hub/src/db/migrate.test.ts @@ -0,0 +1,18 @@ +import { expect, test } from "bun:test"; +import journal from "./migrations/meta/_journal.json"; + +// 0038 reapplies 0037 on databases that skipped it, so 0037 stays as shipped. +const repairedOutOfOrder = new Set(["0037_approval_round"]); + +// The migrator skips any migration whose `when` is not later than the newest +// one already applied, so an out-of-order entry never runs on existing databases. +test("migration journal timestamps strictly increase", () => { + const entries = [...journal.entries].sort((a, b) => a.idx - b.idx); + let latest = 0; + const outOfOrder: string[] = []; + for (const entry of entries) { + if (entry.when <= latest) outOfOrder.push(entry.tag); + latest = Math.max(latest, entry.when); + } + expect(outOfOrder).toEqual([...repairedOutOfOrder]); +}); diff --git a/apps/hub/src/db/migrations/0038_approval_round_reapply.sql b/apps/hub/src/db/migrations/0038_approval_round_reapply.sql new file mode 100644 index 00000000..f7807277 --- /dev/null +++ b/apps/hub/src/db/migrations/0038_approval_round_reapply.sql @@ -0,0 +1,32 @@ +-- 0037's journal timestamp sorts before 0036's, so databases migrated past +-- 0036 skipped it. This reapplies 0037 so it is a no-op where it already ran. +CREATE TABLE IF NOT EXISTS "sb_approval_round" ( + "id" text PRIMARY KEY NOT NULL, + "tenant_id" text NOT NULL, + "project_id" text NOT NULL, + "artifact_id" text NOT NULL, + "package_version" integer NOT NULL, + "package_sha256" text NOT NULL, + "started_by" text NOT NULL, + "expiry_preset" text NOT NULL, + "expires_at" timestamp with time zone NOT NULL, + "settled_at" timestamp with time zone, + "reviewers" jsonb NOT NULL, + "triage" jsonb DEFAULT '[]'::jsonb NOT NULL, + "triggered_run_id" text, + "created_at" timestamp with time zone DEFAULT now() NOT NULL +); +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "sb_approval_round" ADD CONSTRAINT "sb_approval_round_tenant_id_tenant_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenant"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION WHEN duplicate_object THEN NULL; +END $$;--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "sb_approval_round" ADD CONSTRAINT "sb_approval_round_project_id_project_id_fk" FOREIGN KEY ("project_id") REFERENCES "public"."project"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION WHEN duplicate_object THEN NULL; +END $$;--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "sb_approval_round" ADD CONSTRAINT "sb_approval_round_started_by_principal_id_fk" FOREIGN KEY ("started_by") REFERENCES "public"."principal"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION WHEN duplicate_object THEN NULL; +END $$;--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "sb_approval_round_project_idx" ON "sb_approval_round" USING btree ("tenant_id","project_id","created_at"); diff --git a/apps/hub/src/db/migrations/meta/0038_snapshot.json b/apps/hub/src/db/migrations/meta/0038_snapshot.json new file mode 100644 index 00000000..36a6a1ff --- /dev/null +++ b/apps/hub/src/db/migrations/meta/0038_snapshot.json @@ -0,0 +1,1309 @@ +{ + "id": "8e8049e9-c10b-4041-9dcd-d15d50c3201c", + "prevId": "2157db3b-c1c6-4217-867d-ba9a31a07130", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.sb_approval_round": { + "name": "sb_approval_round", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "artifact_id": { + "name": "artifact_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "package_version": { + "name": "package_version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "package_sha256": { + "name": "package_sha256", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "started_by": { + "name": "started_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expiry_preset": { + "name": "expiry_preset", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "settled_at": { + "name": "settled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "reviewers": { + "name": "reviewers", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "triage": { + "name": "triage", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "triggered_run_id": { + "name": "triggered_run_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "sb_approval_round_project_idx": { + "name": "sb_approval_round_project_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + } + }, + "foreignKeys": { + "sb_approval_round_tenant_id_tenant_id_fk": { + "name": "sb_approval_round_tenant_id_tenant_id_fk", + "tableFrom": "sb_approval_round", + "columnsFrom": ["tenant_id"], + "tableTo": "tenant", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "sb_approval_round_project_id_project_id_fk": { + "name": "sb_approval_round_project_id_project_id_fk", + "tableFrom": "sb_approval_round", + "columnsFrom": ["project_id"], + "tableTo": "project", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "sb_approval_round_started_by_principal_id_fk": { + "name": "sb_approval_round_started_by_principal_id_fk", + "tableFrom": "sb_approval_round", + "columnsFrom": ["started_by"], + "tableTo": "principal", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sb_artifact_approval": { + "name": "sb_artifact_approval", + "schema": "", + "columns": { + "approval_id": { + "name": "approval_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "artifact_id": { + "name": "artifact_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tool": { + "name": "tool", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "sb_artifact_approval_artifact_idx": { + "name": "sb_artifact_approval_artifact_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "artifact_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + } + }, + "foreignKeys": { + "sb_artifact_approval_approval_id_approval_id_fk": { + "name": "sb_artifact_approval_approval_id_approval_id_fk", + "tableFrom": "sb_artifact_approval", + "columnsFrom": ["approval_id"], + "tableTo": "approval", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "sb_artifact_approval_tenant_id_tenant_id_fk": { + "name": "sb_artifact_approval_tenant_id_tenant_id_fk", + "tableFrom": "sb_artifact_approval", + "columnsFrom": ["tenant_id"], + "tableTo": "tenant", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "sb_artifact_approval_project_id_project_id_fk": { + "name": "sb_artifact_approval_project_id_project_id_fk", + "tableFrom": "sb_artifact_approval", + "columnsFrom": ["project_id"], + "tableTo": "project", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + } + }, + "compositePrimaryKeys": { + "sb_artifact_approval_approval_id_artifact_id_pk": { + "name": "sb_artifact_approval_approval_id_artifact_id_pk", + "columns": ["approval_id", "artifact_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sb_artifact_import_approval": { + "name": "sb_artifact_import_approval", + "schema": "", + "columns": { + "artifact_id": { + "name": "artifact_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "principal_id": { + "name": "principal_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "sb_artifact_import_approval_tenant_idx": { + "name": "sb_artifact_import_approval_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "artifact_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + } + }, + "foreignKeys": { + "sb_artifact_import_approval_tenant_id_tenant_id_fk": { + "name": "sb_artifact_import_approval_tenant_id_tenant_id_fk", + "tableFrom": "sb_artifact_import_approval", + "columnsFrom": ["tenant_id"], + "tableTo": "tenant", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "sb_artifact_import_approval_project_id_project_id_fk": { + "name": "sb_artifact_import_approval_project_id_project_id_fk", + "tableFrom": "sb_artifact_import_approval", + "columnsFrom": ["project_id"], + "tableTo": "project", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "sb_artifact_import_approval_principal_id_principal_id_fk": { + "name": "sb_artifact_import_approval_principal_id_principal_id_fk", + "tableFrom": "sb_artifact_import_approval", + "columnsFrom": ["principal_id"], + "tableTo": "principal", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + } + }, + "compositePrimaryKeys": { + "sb_artifact_import_approval_artifact_id_version_pk": { + "name": "sb_artifact_import_approval_artifact_id_version_pk", + "columns": ["artifact_id", "version"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sb_custom_model_provider": { + "name": "sb_custom_model_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "model_provider_id": { + "name": "model_provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "models": { + "name": "models", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "keyless": { + "name": "keyless", + "type": "boolean", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "sb_custom_model_provider_model_provider_id_model_provider_id_fk": { + "name": "sb_custom_model_provider_model_provider_id_model_provider_id_fk", + "tableFrom": "sb_custom_model_provider", + "columnsFrom": ["model_provider_id"], + "tableTo": "model_provider", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "sb_custom_model_provider_model_provider_id_unique": { + "name": "sb_custom_model_provider_model_provider_id_unique", + "columns": ["model_provider_id"], + "nullsNotDistinct": false + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sb_design_concept": { + "name": "sb_design_concept", + "schema": "", + "columns": { + "run_id": { + "name": "run_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "direction": { + "name": "direction", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "sb_design_concept_tenant_idx": { + "name": "sb_design_concept_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "label", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + } + }, + "foreignKeys": { + "sb_design_concept_run_id_workflow_run_id_fk": { + "name": "sb_design_concept_run_id_workflow_run_id_fk", + "tableFrom": "sb_design_concept", + "columnsFrom": ["run_id"], + "tableTo": "workflow_run", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "sb_design_concept_tenant_id_tenant_id_fk": { + "name": "sb_design_concept_tenant_id_tenant_id_fk", + "tableFrom": "sb_design_concept", + "columnsFrom": ["tenant_id"], + "tableTo": "tenant", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "sb_design_concept_project_id_project_id_fk": { + "name": "sb_design_concept_project_id_project_id_fk", + "tableFrom": "sb_design_concept", + "columnsFrom": ["project_id"], + "tableTo": "project", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.device_code": { + "name": "device_code", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "device_code": { + "name": "device_code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_code": { + "name": "user_code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_polled_at": { + "name": "last_polled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "polling_interval": { + "name": "polling_interval", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "device_code_device_code_unique": { + "name": "device_code_device_code_unique", + "columns": ["device_code"], + "nullsNotDistinct": false + }, + "device_code_user_code_unique": { + "name": "device_code_user_code_unique", + "columns": ["user_code"], + "nullsNotDistinct": false + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.device_session": { + "name": "device_session", + "schema": "", + "columns": { + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": true, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "device_session_session_id_session_id_fk": { + "name": "device_session_session_id_session_id_fk", + "tableFrom": "device_session", + "columnsFrom": ["session_id"], + "tableTo": "session", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sb_ended_run": { + "name": "sb_ended_run", + "schema": "", + "columns": { + "run_id": { + "name": "run_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "notified": { + "name": "notified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "sb_ended_run_run_id_workflow_run_id_fk": { + "name": "sb_ended_run_run_id_workflow_run_id_fk", + "tableFrom": "sb_ended_run", + "columnsFrom": ["run_id"], + "tableTo": "workflow_run", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "sb_ended_run_project_id_project_id_fk": { + "name": "sb_ended_run_project_id_project_id_fk", + "tableFrom": "sb_ended_run", + "columnsFrom": ["project_id"], + "tableTo": "project", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sb_invitation": { + "name": "sb_invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role_sha256": { + "name": "role_sha256", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "invited_by": { + "name": "invited_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "idempotency_key": { + "name": "idempotency_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload_sha256": { + "name": "payload_sha256", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "accepted_at": { + "name": "accepted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "accepted_principal_id": { + "name": "accepted_principal_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "revoked_by": { + "name": "revoked_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "sb_invitation_recipient_idx": { + "name": "sb_invitation_recipient_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + } + }, + "foreignKeys": { + "sb_invitation_tenant_id_tenant_id_fk": { + "name": "sb_invitation_tenant_id_tenant_id_fk", + "tableFrom": "sb_invitation", + "columnsFrom": ["tenant_id"], + "tableTo": "tenant", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "sb_invitation_tenant_id_invited_by_idempotency_key_unique": { + "name": "sb_invitation_tenant_id_invited_by_idempotency_key_unique", + "columns": ["tenant_id", "invited_by", "idempotency_key"], + "nullsNotDistinct": false + } + }, + "policies": {}, + "checkConstraints": { + "sb_invitation_terminal_check": { + "name": "sb_invitation_terminal_check", + "value": "NOT (\"sb_invitation\".\"accepted_at\" IS NOT NULL AND \"sb_invitation\".\"revoked_at\" IS NOT NULL)" + }, + "sb_invitation_acceptance_check": { + "name": "sb_invitation_acceptance_check", + "value": "(\"sb_invitation\".\"accepted_at\" IS NULL) = (\"sb_invitation\".\"accepted_principal_id\" IS NULL)" + }, + "sb_invitation_revocation_check": { + "name": "sb_invitation_revocation_check", + "value": "(\"sb_invitation\".\"revoked_at\" IS NULL) = (\"sb_invitation\".\"revoked_by\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.mutation_receipt": { + "name": "mutation_receipt", + "schema": "", + "columns": { + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "actor_principal_id": { + "name": "actor_principal_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "idempotency_key": { + "name": "idempotency_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload_sha256": { + "name": "payload_sha256", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "result_body": { + "name": "result_body", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mutation_receipt_tenant_id_tenant_id_fk": { + "name": "mutation_receipt_tenant_id_tenant_id_fk", + "tableFrom": "mutation_receipt", + "columnsFrom": ["tenant_id"], + "tableTo": "tenant", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "mutation_receipt_actor_principal_id_principal_id_fk": { + "name": "mutation_receipt_actor_principal_id_principal_id_fk", + "tableFrom": "mutation_receipt", + "columnsFrom": ["actor_principal_id"], + "tableTo": "principal", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + } + }, + "compositePrimaryKeys": { + "mutation_receipt_tenant_id_actor_principal_id_command_idempotency_key_pk": { + "name": "mutation_receipt_tenant_id_actor_principal_id_command_idempotency_key_pk", + "columns": [ + "tenant_id", + "actor_principal_id", + "command", + "idempotency_key" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.outbox": { + "name": "outbox", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "event_type": { + "name": "event_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "occurred_at": { + "name": "occurred_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "published_at": { + "name": "published_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "sb_outbox_project_time_id_idx": { + "name": "sb_outbox_project_time_id_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "occurred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + } + }, + "foreignKeys": { + "outbox_project_id_project_id_fk": { + "name": "outbox_project_id_project_id_fk", + "tableFrom": "outbox", + "columnsFrom": ["project_id"], + "tableTo": "project", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.project": { + "name": "project", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "version_of_project_id": { + "name": "version_of_project_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shipped_at": { + "name": "shipped_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "project_tenant_id_tenant_id_fk": { + "name": "project_tenant_id_tenant_id_fk", + "tableFrom": "project", + "columnsFrom": ["tenant_id"], + "tableTo": "tenant", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "project_version_of_project_id_project_id_fk": { + "name": "project_version_of_project_id_project_id_fk", + "tableFrom": "project", + "columnsFrom": ["version_of_project_id"], + "tableTo": "project", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "project_tenant_id_unique": { + "name": "project_tenant_id_unique", + "columns": ["tenant_id"], + "nullsNotDistinct": false + } + }, + "policies": {}, + "checkConstraints": { + "project_status_check": { + "name": "project_status_check", + "value": "\"project\".\"status\" in ('active', 'archived')" + } + }, + "isRLSEnabled": false + }, + "public.project_coordinator": { + "name": "project_coordinator", + "schema": "", + "columns": { + "run_id": { + "name": "run_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "registered_by": { + "name": "registered_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "project_coordinator_active_project_idx": { + "name": "project_coordinator_active_project_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "with": {}, + "method": "btree", + "where": "\"project_coordinator\".\"active\"", + "concurrently": false + } + }, + "foreignKeys": { + "project_coordinator_run_id_workflow_run_id_fk": { + "name": "project_coordinator_run_id_workflow_run_id_fk", + "tableFrom": "project_coordinator", + "columnsFrom": ["run_id"], + "tableTo": "workflow_run", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "project_coordinator_project_id_project_id_fk": { + "name": "project_coordinator_project_id_project_id_fk", + "tableFrom": "project_coordinator", + "columnsFrom": ["project_id"], + "tableTo": "project", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "project_coordinator_registered_by_principal_id_fk": { + "name": "project_coordinator_registered_by_principal_id_fk", + "tableFrom": "project_coordinator", + "columnsFrom": ["registered_by"], + "tableTo": "principal", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sb_settings": { + "name": "sb_settings", + "schema": "", + "columns": { + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scope_key": { + "name": "scope_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fields": { + "name": "fields", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "sb_settings_tenant_id_tenant_id_fk": { + "name": "sb_settings_tenant_id_tenant_id_fk", + "tableFrom": "sb_settings", + "columnsFrom": ["tenant_id"], + "tableTo": "tenant", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + }, + "sb_settings_project_id_project_id_fk": { + "name": "sb_settings_project_id_project_id_fk", + "tableFrom": "sb_settings", + "columnsFrom": ["project_id"], + "tableTo": "project", + "columnsTo": ["id"], + "onUpdate": "no action", + "onDelete": "no action" + } + }, + "compositePrimaryKeys": { + "sb_settings_tenant_id_scope_key_pk": { + "name": "sb_settings_tenant_id_scope_key_pk", + "columns": ["tenant_id", "scope_key"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "views": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/apps/hub/src/db/migrations/meta/_journal.json b/apps/hub/src/db/migrations/meta/_journal.json index 73edb033..a0718599 100644 --- a/apps/hub/src/db/migrations/meta/_journal.json +++ b/apps/hub/src/db/migrations/meta/_journal.json @@ -267,6 +267,13 @@ "when": 1793596830302, "tag": "0037_approval_round", "breakpoints": true + }, + { + "idx": 38, + "version": "7", + "when": 1794100000000, + "tag": "0038_approval_round_reapply", + "breakpoints": true } ] }