@opengeni/db 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/chunk-ELMUCYZF.js +906 -0
  2. package/dist/chunk-ELMUCYZF.js.map +1 -0
  3. package/dist/chunk-N4WTE6SB.js +4033 -0
  4. package/dist/chunk-N4WTE6SB.js.map +1 -0
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.js +3594 -2059
  7. package/dist/index.js.map +1 -1
  8. package/dist/provision-roles.d.ts +472 -43
  9. package/dist/provision-roles.js +1 -1
  10. package/dist/{schema-BejThLcd.d.ts → schema-Bh1Hr7xY.d.ts} +2507 -970
  11. package/dist/schema.d.ts +1 -1
  12. package/dist/schema.js +9 -1
  13. package/drizzle/0122_codex_capacity_same_turn.sql +59 -0
  14. package/drizzle/0123_session_tool_policy_version.sql +14 -0
  15. package/drizzle/0124_session_event_duplicate_lookup.sql +4 -0
  16. package/drizzle/0125_document_drops_visibility.sql +29 -0
  17. package/drizzle/0126_document_access_constraints.sql +138 -0
  18. package/drizzle/0127_document_default_base_index.sql +5 -0
  19. package/drizzle/0128_github_installation_authority.sql +69 -0
  20. package/drizzle/0129_retained_process_reconciliation.sql +356 -0
  21. package/drizzle/0130_workspace_instruction_policies.sql +330 -0
  22. package/drizzle/0131_slack_bot_install_and_post_idempotency.sql +133 -0
  23. package/package.json +4 -3
  24. package/src/event-payload-sanitizer.ts +167 -55
  25. package/src/index.ts +1850 -264
  26. package/src/new-session-drafts.ts +127 -6
  27. package/src/provision-roles.ts +184 -2
  28. package/src/runtime-posture-cli.ts +57 -0
  29. package/src/runtime-posture.ts +770 -0
  30. package/src/schema.ts +243 -3
  31. package/src/session-control.ts +1 -0
  32. package/src/workspace-instruction-policies-schema.ts +140 -0
  33. package/src/workspace-instruction-policies.ts +624 -0
  34. package/dist/chunk-BMFDXFPA.js +0 -155
  35. package/dist/chunk-BMFDXFPA.js.map +0 -1
  36. package/dist/chunk-VUKRIBO5.js +0 -3679
  37. package/dist/chunk-VUKRIBO5.js.map +0 -1
package/dist/schema.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import 'drizzle-orm';
2
2
  import 'drizzle-orm/pg-core';
3
- export { o as agentRunStates, p as apiKeys, q as auditEvents, r as billingCustomers, t as capabilityCatalogItems, u as capabilityInstallations, v as codexCapacityWaiters, x as codexCredentialLeases, y as codexResetRedemptionAttempts, z as codexRotationSettings, A as codexSubscriptionCredentials, d as composerDrafts, B as connections, C as creditLedgerEntries, D as deviceEnrollmentRequests, h as deviceEnrollmentStatusValues, E as documentBases, F as documentChunks, G as documents, g as enrollmentExposureValues, f as enrollmentOsValues, i as enrollmentStatusValues, H as enrollments, I as fileUploads, J as files, K as githubInstallationRepositories, L as githubInstallations, M as hostExportConfig, N as hostExportConsumers, O as hostExportCursorState, P as hostExportDeadLetters, Q as hostExportOutbox, R as importBatches, S as integrationOauthClients, T as integrationOauthStateNonces, U as knowledgeMemories, V as machineMetricsLatest, W as machineMetricsSeries, X as managedAccounts, Y as nestedAgentDepthConfiguration, n as newSessionDrafts, Z as packInstallations, _ as rigChanges, $ as rigVersions, a0 as rigs, j as sandboxKindValues, a1 as sandboxLeaseHolders, a2 as sandboxLeaseLivenessValues, a3 as sandboxLeases, a4 as sandboxPtySessions, a5 as sandboxRetainedProcessStateValues, a6 as sandboxRetainedProcesses, a7 as sandboxSessionEnvelopes, a8 as sandboxWorkspaceMutationActorKindValues, a9 as sandboxWorkspaceMutationAdmissions, aa as sandboxWorkspaceMutationHolderKindValues, ab as sandboxes, ac as scheduledTaskRuns, ad as scheduledTasks, ae as sessionAttemptInterruptions, s as sessionCommandReceipts, af as sessionEvents, ag as sessionGoals, ah as sessionHistoryItems, ai as sessionHumanInputRequests, aj as sessionListSnapshots, ak as sessionMcpServers, al as sessionPendingToolCalls, am as sessionPins, k as sessionRecordingCodecValues, l as sessionRecordingModeValues, m as sessionRecordingStateValues, an as sessionRecordings, ao as sessionSpawnDenials, ap as sessionSystemUpdateOutbox, aq as sessionSystemUpdates, c as sessionTurnAttempts, b as sessionTurns, ar as sessionWorkflowWakeOutbox, a as sessions, as as socialConnections, at as socialPosts, au as stripeWebhookEvents, av as usageEvents, aw as workspaceCaptures, ax as workspaceControlEvents, ay as workspaceInferenceControls, az as workspaceMemberships, aA as workspaceModelPolicies, aB as workspacePacks, aC as workspaceSessionActivityRevisions, aD as workspaceVariableSetVariables, aE as workspaceVariableSets, w as workspaces } from './schema-BejThLcd.js';
3
+ export { o as agentRunStates, p as apiKeys, q as auditEvents, r as billingCustomers, t as capabilityCatalogItems, u as capabilityInstallations, v as codexCapacityWaiters, x as codexCredentialLeases, y as codexResetRedemptionAttempts, z as codexRotationSettings, A as codexSubscriptionCredentials, d as composerDrafts, B as connections, C as creditLedgerEntries, D as deviceEnrollmentRequests, h as deviceEnrollmentStatusValues, E as documentBases, F as documentChunks, G as documents, g as enrollmentExposureValues, f as enrollmentOsValues, i as enrollmentStatusValues, H as enrollments, I as fileUploads, J as files, K as githubInstallationRepositories, L as githubInstallations, M as hostExportConfig, N as hostExportConsumers, O as hostExportCursorState, P as hostExportDeadLetters, Q as hostExportOutbox, R as importBatches, S as integrationOauthClients, T as integrationOauthStateNonces, U as knowledgeMemories, V as machineMetricsLatest, W as machineMetricsSeries, X as managedAccounts, Y as nestedAgentDepthConfiguration, n as newSessionDrafts, Z as packInstallations, _ as rigChanges, $ as rigVersions, a0 as rigs, j as sandboxKindValues, a1 as sandboxLeaseHolders, a2 as sandboxLeaseLivenessValues, a3 as sandboxLeases, a4 as sandboxPtySessions, a5 as sandboxRetainedProcessStateValues, a6 as sandboxRetainedProcesses, a7 as sandboxSessionEnvelopes, a8 as sandboxWorkspaceMutationActorKindValues, a9 as sandboxWorkspaceMutationAdmissions, aa as sandboxWorkspaceMutationHolderKindValues, ab as sandboxes, ac as scheduledTaskRuns, ad as scheduledTasks, ae as sessionAttemptInterruptions, s as sessionCommandReceipts, af as sessionEvents, ag as sessionGoals, ah as sessionHistoryItems, ai as sessionHumanInputRequests, aj as sessionListSnapshots, ak as sessionMcpServers, al as sessionPendingToolCalls, am as sessionPins, k as sessionRecordingCodecValues, l as sessionRecordingModeValues, m as sessionRecordingStateValues, an as sessionRecordings, ao as sessionSpawnDenials, ap as sessionSystemUpdateOutbox, aq as sessionSystemUpdates, c as sessionTurnAttempts, b as sessionTurns, ar as sessionWorkflowWakeOutbox, a as sessions, as as slackBotPostOperations, at as socialConnections, au as socialPosts, av as stripeWebhookEvents, aw as usageEvents, ax as workspaceCaptures, ay as workspaceControlEvents, az as workspaceInferenceControls, aA as workspaceInstructionPolicyActivationEvents, aB as workspaceInstructionPolicyHeads, aC as workspaceInstructionPolicyRevisions, aD as workspaceMemberships, aE as workspaceModelPolicies, aF as workspacePacks, aG as workspaceSessionActivityRevisions, aH as workspaceVariableSetVariables, aI as workspaceVariableSets, w as workspaces } from './schema-Bh1Hr7xY.js';
package/dist/schema.js CHANGED
@@ -79,6 +79,7 @@ import {
79
79
  sessionTurns,
80
80
  sessionWorkflowWakeOutbox,
81
81
  sessions,
82
+ slackBotPostOperations,
82
83
  socialConnections,
83
84
  socialPosts,
84
85
  stripeWebhookEvents,
@@ -86,6 +87,9 @@ import {
86
87
  workspaceCaptures,
87
88
  workspaceControlEvents,
88
89
  workspaceInferenceControls,
90
+ workspaceInstructionPolicyActivationEvents,
91
+ workspaceInstructionPolicyHeads,
92
+ workspaceInstructionPolicyRevisions,
89
93
  workspaceMemberships,
90
94
  workspaceModelPolicies,
91
95
  workspacePacks,
@@ -93,7 +97,7 @@ import {
93
97
  workspaceVariableSetVariables,
94
98
  workspaceVariableSets,
95
99
  workspaces
96
- } from "./chunk-VUKRIBO5.js";
100
+ } from "./chunk-N4WTE6SB.js";
97
101
  import "./chunk-PZ5AY32C.js";
98
102
  export {
99
103
  agentRunStates,
@@ -176,6 +180,7 @@ export {
176
180
  sessionTurns,
177
181
  sessionWorkflowWakeOutbox,
178
182
  sessions,
183
+ slackBotPostOperations,
179
184
  socialConnections,
180
185
  socialPosts,
181
186
  stripeWebhookEvents,
@@ -183,6 +188,9 @@ export {
183
188
  workspaceCaptures,
184
189
  workspaceControlEvents,
185
190
  workspaceInferenceControls,
191
+ workspaceInstructionPolicyActivationEvents,
192
+ workspaceInstructionPolicyHeads,
193
+ workspaceInstructionPolicyRevisions,
186
194
  workspaceMemberships,
187
195
  workspaceModelPolicies,
188
196
  workspacePacks,
@@ -0,0 +1,59 @@
1
+ -- deployment-mode: maintenance
2
+ -- This changes the waiter/worker contract in one no-overlap cutover: old
3
+ -- workers terminally settled capacity waits, while new workers preserve the
4
+ -- same logical turn. Do not run old and new workers concurrently.
5
+
6
+ ALTER TABLE "session_turn_attempts"
7
+ DROP CONSTRAINT "session_turn_attempts_outcome_check";
8
+ ALTER TABLE "session_turn_attempts"
9
+ ADD CONSTRAINT "session_turn_attempts_outcome_check"
10
+ CHECK (
11
+ "outcome" IS NULL OR "outcome" IN (
12
+ 'completed', 'failed', 'cancelled', 'superseded', 'requires_action',
13
+ 'waiting_capacity', 'interrupted_recoverable',
14
+ 'lease_lost_recoverable', 'pre_cutover_closed'
15
+ )
16
+ );
17
+
18
+ -- A waiter is turn-owned. Goal identity is only an optional generation fence,
19
+ -- so goal-less prompts can wait and goal deletion cannot cascade away the
20
+ -- durable ledger before reconciliation supersedes the blocked turn.
21
+ ALTER TABLE "codex_capacity_waiters"
22
+ DROP CONSTRAINT "codex_capacity_waiters_workspace_goal_fk";
23
+ ALTER TABLE "codex_capacity_waiters"
24
+ ALTER COLUMN "goal_id" DROP NOT NULL,
25
+ ALTER COLUMN "goal_version" DROP NOT NULL,
26
+ ADD COLUMN "blocked_turn_generation" integer;
27
+
28
+ UPDATE "codex_capacity_waiters" waiter
29
+ SET "blocked_turn_generation" = turn."execution_generation"
30
+ FROM "session_turns" turn
31
+ WHERE turn."workspace_id" = waiter."workspace_id"
32
+ AND turn."id" = waiter."blocked_turn_id";
33
+
34
+ DO $audit$
35
+ BEGIN
36
+ IF EXISTS (
37
+ SELECT 1
38
+ FROM "codex_capacity_waiters"
39
+ WHERE "blocked_turn_generation" IS NULL
40
+ OR "blocked_turn_generation" < 1
41
+ OR (("goal_id" IS NULL) <> ("goal_version" IS NULL))
42
+ OR ("goal_version" IS NOT NULL AND "goal_version" < 1)
43
+ ) THEN
44
+ RAISE EXCEPTION 'codex capacity same-turn backfill found an invalid waiter';
45
+ END IF;
46
+ END $audit$;
47
+
48
+ ALTER TABLE "codex_capacity_waiters"
49
+ ALTER COLUMN "blocked_turn_generation" SET NOT NULL,
50
+ DROP CONSTRAINT IF EXISTS "codex_capacity_waiters_generation_check",
51
+ ADD CONSTRAINT "codex_capacity_waiters_generation_check"
52
+ CHECK (
53
+ "generation" > 0
54
+ AND "blocked_turn_generation" > 0
55
+ AND (
56
+ ("goal_id" IS NULL AND "goal_version" IS NULL)
57
+ OR ("goal_id" IS NOT NULL AND "goal_version" > 0)
58
+ )
59
+ );
@@ -0,0 +1,14 @@
1
+ -- deployment-mode: rolling
2
+
3
+ -- A durable policy mutation is fenced independently from the global event
4
+ -- sequence. The default keeps old writers safe during the rolling upgrade;
5
+ -- the policy update command advances this value with a locked SQL CAS.
6
+ ALTER TABLE "sessions"
7
+ ADD COLUMN IF NOT EXISTS "tool_policy_version" integer NOT NULL DEFAULT 1;
8
+
9
+ ALTER TABLE "sessions"
10
+ DROP CONSTRAINT IF EXISTS "sessions_tool_policy_version_check";
11
+
12
+ ALTER TABLE "sessions"
13
+ ADD CONSTRAINT "sessions_tool_policy_version_check"
14
+ CHECK ("tool_policy_version" >= 1) NOT VALID;
@@ -0,0 +1,4 @@
1
+ -- deployment-mode: rolling
2
+ -- opengeni:concurrent-index lock-timeout=5s
3
+ CREATE INDEX CONCURRENTLY IF NOT EXISTS "session_events_duplicate_of_event_idx"
4
+ ON "session_events" ("duplicate_of_event_id");
@@ -0,0 +1,29 @@
1
+ -- deployment-mode: rolling
2
+ -- Knowledge drops: auto-curation + per-document visibility.
3
+ -- Follows 0041_knowledge_layer.sql conventions: IF NOT EXISTS column adds only.
4
+ -- NO policy changes (documents already has FORCE RLS + workspace_isolation from 0041).
5
+ --
6
+ -- visibility: 'workspace' (anyone in the workspace) | 'private' (creator only).
7
+ -- created_by: the access-grant subject id that created the document (text — subject
8
+ -- ids are labels like 'dev' or 'api_key:<uuid>', not uuids). NULL for pre-existing
9
+ -- rows, which stay workspace-visible.
10
+ -- agent_access: whether agent retrieval surfaces (docs MCP tools) may return the
11
+ -- document. Humans keep REST access regardless.
12
+ -- curation_status: 'none' (ordinary add, caller supplied metadata) | 'pending'
13
+ -- (dropped, awaiting auto-curation) | 'suggested' (curated; base move NOT applied)
14
+ -- | 'auto_filed' (curated and moved to the suggested base) | 'failed' (curation
15
+ -- errored; document still indexes).
16
+ -- curation: the curator output audit blob {suggestedBaseId, suggestedBaseName,
17
+ -- confidence, reason, originalTitle, model}.
18
+
19
+ ALTER TABLE "documents" ADD COLUMN IF NOT EXISTS "visibility" text NOT NULL DEFAULT 'workspace';
20
+ ALTER TABLE "documents" ADD COLUMN IF NOT EXISTS "created_by" text;
21
+ ALTER TABLE "documents" ADD COLUMN IF NOT EXISTS "agent_access" boolean NOT NULL DEFAULT true;
22
+ ALTER TABLE "documents" ADD COLUMN IF NOT EXISTS "summary" text;
23
+ ALTER TABLE "documents" ADD COLUMN IF NOT EXISTS "topics" jsonb NOT NULL DEFAULT '[]'::jsonb;
24
+ ALTER TABLE "documents" ADD COLUMN IF NOT EXISTS "curation_status" text NOT NULL DEFAULT 'none';
25
+ ALTER TABLE "documents" ADD COLUMN IF NOT EXISTS "curation" jsonb;
26
+
27
+ -- Drop review surface: list pending/suggested drops per workspace cheaply.
28
+ CREATE INDEX IF NOT EXISTS "documents_workspace_curation_status_idx"
29
+ ON "documents" ("workspace_id", "curation_status");
@@ -0,0 +1,138 @@
1
+ -- deployment-mode: rolling
2
+ -- Document access and knowledge-drop state hardening.
3
+ --
4
+ -- Existing raced Default rows are consolidated before the unique index is
5
+ -- installed by the following concurrent migration. This migration also
6
+ -- repairs legacy document state before adding validated checks, so an upgrade
7
+ -- cannot strand an otherwise readable database behind an invalid old value.
8
+
9
+ DO $$
10
+ DECLARE
11
+ duplicate RECORD;
12
+ BEGIN
13
+ FOR duplicate IN
14
+ SELECT workspace_id, min(id::text)::uuid AS keep_id
15
+ FROM document_bases
16
+ WHERE lower(btrim(name)) = 'default'
17
+ GROUP BY workspace_id
18
+ HAVING count(*) > 1
19
+ LOOP
20
+ -- A file can only occur once in a base. Keep the lexicographically first
21
+ -- Default row's document when an old race created the same file twice.
22
+ DELETE FROM documents duplicate_document
23
+ WHERE duplicate_document.workspace_id = duplicate.workspace_id
24
+ AND duplicate_document.base_id <> duplicate.keep_id
25
+ AND lower(btrim((SELECT name FROM document_bases WHERE id = duplicate_document.base_id))) = 'default'
26
+ AND EXISTS (
27
+ SELECT 1
28
+ FROM documents retained_document
29
+ WHERE retained_document.workspace_id = duplicate.workspace_id
30
+ AND retained_document.base_id = duplicate.keep_id
31
+ AND retained_document.file_id = duplicate_document.file_id
32
+ );
33
+
34
+ UPDATE documents
35
+ SET base_id = duplicate.keep_id,
36
+ updated_at = now()
37
+ WHERE workspace_id = duplicate.workspace_id
38
+ AND base_id <> duplicate.keep_id
39
+ AND lower(btrim((SELECT name FROM document_bases WHERE id = base_id))) = 'default';
40
+
41
+ UPDATE document_chunks chunk
42
+ SET base_id = duplicate.keep_id
43
+ WHERE chunk.workspace_id = duplicate.workspace_id
44
+ AND chunk.base_id <> duplicate.keep_id
45
+ AND EXISTS (
46
+ SELECT 1
47
+ FROM documents document
48
+ WHERE document.id = chunk.document_id
49
+ AND document.base_id = duplicate.keep_id
50
+ );
51
+
52
+ DELETE FROM document_bases base
53
+ WHERE base.workspace_id = duplicate.workspace_id
54
+ AND base.id <> duplicate.keep_id
55
+ AND lower(btrim(base.name)) = 'default';
56
+ END LOOP;
57
+ END
58
+ $$;
59
+
60
+ -- Rows written before these fields were governed may contain values outside
61
+ -- the new state machine. Preserve the document and its retrieval posture while
62
+ -- normalizing only states that have no safe interpretation.
63
+ UPDATE "documents"
64
+ SET "visibility" = 'workspace'
65
+ WHERE "visibility" IS NULL OR "visibility" NOT IN ('workspace', 'private');
66
+
67
+ UPDATE "documents"
68
+ SET "visibility" = 'workspace', "created_by" = NULL
69
+ WHERE "visibility" = 'private' AND NULLIF(btrim("created_by"), '') IS NULL;
70
+
71
+ UPDATE "documents"
72
+ SET "curation_status" = 'none'
73
+ WHERE "curation_status" IS NULL
74
+ OR "curation_status" NOT IN ('none', 'pending', 'suggested', 'auto_filed', 'failed');
75
+
76
+ UPDATE "documents"
77
+ SET "topics" = '[]'::jsonb
78
+ WHERE "topics" IS NULL OR jsonb_typeof("topics") <> 'array';
79
+
80
+ UPDATE "documents"
81
+ SET "curation" = NULL
82
+ WHERE "curation" IS NOT NULL AND jsonb_typeof("curation") <> 'object';
83
+
84
+ DO $$
85
+ BEGIN
86
+ IF NOT EXISTS (
87
+ SELECT 1 FROM pg_constraint
88
+ WHERE conname = 'documents_visibility_chk'
89
+ AND conrelid = 'documents'::regclass
90
+ ) THEN
91
+ ALTER TABLE "documents"
92
+ ADD CONSTRAINT "documents_visibility_chk"
93
+ CHECK ("visibility" IN ('workspace', 'private')) NOT VALID;
94
+ END IF;
95
+ IF NOT EXISTS (
96
+ SELECT 1 FROM pg_constraint
97
+ WHERE conname = 'documents_curation_status_chk'
98
+ AND conrelid = 'documents'::regclass
99
+ ) THEN
100
+ ALTER TABLE "documents"
101
+ ADD CONSTRAINT "documents_curation_status_chk"
102
+ CHECK ("curation_status" IN ('none', 'pending', 'suggested', 'auto_filed', 'failed')) NOT VALID;
103
+ END IF;
104
+ IF NOT EXISTS (
105
+ SELECT 1 FROM pg_constraint
106
+ WHERE conname = 'documents_private_creator_chk'
107
+ AND conrelid = 'documents'::regclass
108
+ ) THEN
109
+ ALTER TABLE "documents"
110
+ ADD CONSTRAINT "documents_private_creator_chk"
111
+ CHECK ("visibility" <> 'private' OR NULLIF(btrim("created_by"), '') IS NOT NULL) NOT VALID;
112
+ END IF;
113
+ IF NOT EXISTS (
114
+ SELECT 1 FROM pg_constraint
115
+ WHERE conname = 'documents_topics_array_chk'
116
+ AND conrelid = 'documents'::regclass
117
+ ) THEN
118
+ ALTER TABLE "documents"
119
+ ADD CONSTRAINT "documents_topics_array_chk"
120
+ CHECK (jsonb_typeof("topics") = 'array') NOT VALID;
121
+ END IF;
122
+ IF NOT EXISTS (
123
+ SELECT 1 FROM pg_constraint
124
+ WHERE conname = 'documents_curation_object_chk'
125
+ AND conrelid = 'documents'::regclass
126
+ ) THEN
127
+ ALTER TABLE "documents"
128
+ ADD CONSTRAINT "documents_curation_object_chk"
129
+ CHECK ("curation" IS NULL OR jsonb_typeof("curation") = 'object') NOT VALID;
130
+ END IF;
131
+ END
132
+ $$;
133
+
134
+ ALTER TABLE "documents" VALIDATE CONSTRAINT "documents_visibility_chk";
135
+ ALTER TABLE "documents" VALIDATE CONSTRAINT "documents_curation_status_chk";
136
+ ALTER TABLE "documents" VALIDATE CONSTRAINT "documents_private_creator_chk";
137
+ ALTER TABLE "documents" VALIDATE CONSTRAINT "documents_topics_array_chk";
138
+ ALTER TABLE "documents" VALIDATE CONSTRAINT "documents_curation_object_chk";
@@ -0,0 +1,5 @@
1
+ -- deployment-mode: rolling
2
+ -- opengeni:concurrent-index lock-timeout=5s
3
+ CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS "document_bases_workspace_default_name_uq"
4
+ ON "document_bases" ("workspace_id")
5
+ WHERE lower(btrim("name")) = 'default';
@@ -0,0 +1,69 @@
1
+ -- deployment-mode: rolling
2
+
3
+ ALTER TABLE "github_installations"
4
+ ADD COLUMN IF NOT EXISTS "github_account_id" bigint,
5
+ ADD COLUMN IF NOT EXISTS "github_actor_id" bigint,
6
+ ADD COLUMN IF NOT EXISTS "github_actor_login" text,
7
+ ADD COLUMN IF NOT EXISTS "authority_kind" text,
8
+ ADD COLUMN IF NOT EXISTS "authority_checked_at" timestamptz,
9
+ ADD COLUMN IF NOT EXISTS "authority_expires_at" timestamptz,
10
+ ADD COLUMN IF NOT EXISTS "authority_nonce" text;
11
+
12
+ DO $$
13
+ BEGIN
14
+ IF NOT EXISTS (
15
+ SELECT 1 FROM pg_constraint
16
+ WHERE conname = 'github_installations_authority_kind_check'
17
+ AND conrelid = 'github_installations'::regclass
18
+ ) THEN
19
+ ALTER TABLE "github_installations"
20
+ ADD CONSTRAINT "github_installations_authority_kind_check"
21
+ CHECK (
22
+ (
23
+ "github_account_id" IS NULL
24
+ AND "github_actor_id" IS NULL
25
+ AND "github_actor_login" IS NULL
26
+ AND "authority_kind" IS NULL
27
+ AND "authority_checked_at" IS NULL
28
+ AND "authority_expires_at" IS NULL
29
+ AND "authority_nonce" IS NULL
30
+ )
31
+ OR (
32
+ "github_account_id" IS NOT NULL
33
+ AND "github_account_id" > 0
34
+ AND "github_actor_id" IS NOT NULL
35
+ AND "github_actor_id" > 0
36
+ AND "github_actor_login" IS NOT NULL
37
+ AND length("github_actor_login") > 0
38
+ AND "account_login" IS NOT NULL
39
+ AND length("account_login") > 0
40
+ AND "account_type" IS NOT NULL
41
+ AND "linked_by_subject_id" IS NOT NULL
42
+ AND length("linked_by_subject_id") > 0
43
+ AND "authority_kind" IS NOT NULL
44
+ AND "authority_checked_at" IS NOT NULL
45
+ AND "authority_expires_at" IS NOT NULL
46
+ AND "authority_checked_at" < "authority_expires_at"
47
+ AND "authority_expires_at" <= "authority_checked_at" + interval '10 minutes'
48
+ AND "authority_nonce" IS NOT NULL
49
+ AND length("authority_nonce") > 0
50
+ AND "repository_scope" = 'selected'
51
+ AND (
52
+ (
53
+ "authority_kind" = 'personal_owner'
54
+ AND "account_type" = 'User'
55
+ AND "github_actor_id" = "github_account_id"
56
+ )
57
+ OR (
58
+ "authority_kind" = 'organization_owner'
59
+ AND "account_type" = 'Organization'
60
+ )
61
+ )
62
+ )
63
+ );
64
+ END IF;
65
+ END $$;
66
+
67
+ CREATE UNIQUE INDEX IF NOT EXISTS "github_installations_authority_nonce_uq"
68
+ ON "github_installations" ("authority_nonce")
69
+ WHERE "authority_nonce" IS NOT NULL;