@opengeni/db 0.9.3 → 0.12.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 (54) hide show
  1. package/dist/{chunk-4LG5NBTC.js → chunk-VUKRIBO5.js} +577 -12
  2. package/dist/chunk-VUKRIBO5.js.map +1 -0
  3. package/dist/{chunk-KW526IJA.js → chunk-Y5WZZVQK.js} +80 -4
  4. package/dist/chunk-Y5WZZVQK.js.map +1 -0
  5. package/dist/index.d.ts +4 -2
  6. package/dist/index.js +6372 -2189
  7. package/dist/index.js.map +1 -1
  8. package/dist/migrate.d.ts +6 -3
  9. package/dist/migrate.js +1 -1
  10. package/dist/provision-roles.d.ts +1122 -91
  11. package/dist/{schema-CdPGTHlD.d.ts → schema-CnpD6BcX.d.ts} +5908 -3626
  12. package/dist/schema.d.ts +1 -1
  13. package/dist/schema.js +19 -1
  14. package/drizzle/0053_codex_credential_leases.sql +2 -2
  15. package/drizzle/0057_durable_queue_control.sql +1 -1
  16. package/drizzle/0061_session_workflow_wake_outbox.sql +1 -1
  17. package/drizzle/0062_session_list_snapshot_reaper.sql +1 -1
  18. package/drizzle/0063_session_control_mega_foundation.sql +1 -1
  19. package/drizzle/0064_rotation_strategy_sharded_backfill.sql +1 -1
  20. package/drizzle/0065_codex_subscription_overview.sql +168 -0
  21. package/drizzle/0065_session_tool_policy.sql +38 -0
  22. package/drizzle/0067_session_event_payload_bounds.sql +2 -2
  23. package/drizzle/0068_workspace_control_event_bounds.sql +2 -2
  24. package/drizzle/0069_session_event_history_backfill.sql +2 -2
  25. package/drizzle/0074_session_activity_revisions.sql +2 -2
  26. package/drizzle/0106_session_attempt_mcp_approval_policies.sql +29 -0
  27. package/drizzle/0107_host_export_lineage_contract.sql +381 -0
  28. package/drizzle/0108_fence_invalidated_warming_epochs.sql +76 -0
  29. package/drizzle/0109_nested_agent_depth_expand.sql +42 -0
  30. package/drizzle/0110_nested_agent_depth_boundary.sql +480 -0
  31. package/drizzle/0111_nested_agent_depth_backfill.sql +49 -0
  32. package/drizzle/0112_nested_agent_depth_contract.sql +38 -0
  33. package/drizzle/0113_nested_agent_depth_validate.sql +13 -0
  34. package/drizzle/0114_nested_agent_depth_contract.sql +49 -0
  35. package/drizzle/0115_nested_agent_depth_validate.sql +11 -0
  36. package/drizzle/0116_nested_agent_depth_index.sql +4 -0
  37. package/drizzle/0117_sandbox_recovery_generations.sql +699 -0
  38. package/drizzle/0118_new_session_drafts.sql +59 -0
  39. package/drizzle/0119_pending_tool_output_policy.sql +5 -0
  40. package/drizzle/0120_durable_goal_wake.sql +360 -0
  41. package/drizzle/0121_goal_update_idempotency.sql +11 -0
  42. package/package.json +5 -4
  43. package/src/codex-token-resolver.ts +175 -14
  44. package/src/connection-token-resolver.ts +143 -120
  45. package/src/event-payload-sanitizer.ts +32 -2
  46. package/src/index.ts +7734 -1330
  47. package/src/migrate.ts +131 -2
  48. package/src/new-session-drafts.ts +144 -0
  49. package/src/schema.ts +626 -16
  50. package/src/session-control.ts +44 -18
  51. package/src/session-queue-commands.ts +94 -21
  52. package/src/session-tool-call-settlement.ts +6 -1
  53. package/dist/chunk-4LG5NBTC.js.map +0 -1
  54. package/dist/chunk-KW526IJA.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 { n as agentRunStates, o as apiKeys, p as auditEvents, q as billingCustomers, r as capabilityCatalogItems, t as capabilityInstallations, u as codexCapacityWaiters, v as codexCredentialLeases, x as codexRotationSettings, y as codexSubscriptionCredentials, d as composerDrafts, z as connections, A as creditLedgerEntries, B as deviceEnrollmentRequests, h as deviceEnrollmentStatusValues, C as documentBases, D as documentChunks, E as documents, g as enrollmentExposureValues, f as enrollmentOsValues, i as enrollmentStatusValues, F as enrollments, G as fileUploads, H as files, I as githubInstallationRepositories, J as githubInstallations, K as hostExportConfig, L as hostExportConsumers, M as hostExportCursorState, N as hostExportDeadLetters, O as hostExportOutbox, P as importBatches, Q as integrationOauthClients, R as integrationOauthStateNonces, S as knowledgeMemories, T as machineMetricsLatest, U as machineMetricsSeries, V as managedAccounts, W as packInstallations, X as rigChanges, Y as rigVersions, Z as rigs, j as sandboxKindValues, _ as sandboxLeaseHolders, $ as sandboxLeaseLivenessValues, a0 as sandboxLeases, a1 as sandboxPtySessions, a2 as sandboxSessionEnvelopes, a3 as sandboxes, a4 as scheduledTaskRuns, a5 as scheduledTasks, a6 as sessionAttemptInterruptions, s as sessionCommandReceipts, a7 as sessionEvents, a8 as sessionGoals, a9 as sessionHistoryItems, aa as sessionHumanInputRequests, ab as sessionListSnapshots, ac as sessionMcpServers, ad as sessionPendingToolCalls, ae as sessionPins, k as sessionRecordingCodecValues, l as sessionRecordingModeValues, m as sessionRecordingStateValues, af as sessionRecordings, ag as sessionSystemUpdateOutbox, ah as sessionSystemUpdates, c as sessionTurnAttempts, b as sessionTurns, ai as sessionWorkflowWakeOutbox, a as sessions, aj as socialConnections, ak as socialPosts, al as stripeWebhookEvents, am as usageEvents, an as workspaceCaptures, ao as workspaceControlEvents, ap as workspaceInferenceControls, aq as workspaceMemberships, ar as workspaceModelPolicies, as as workspacePacks, at as workspaceSessionActivityRevisions, au as workspaceVariableSetVariables, av as workspaceVariableSets, w as workspaces } from './schema-CdPGTHlD.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 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-CnpD6BcX.js';
package/dist/schema.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  capabilityInstallations,
8
8
  codexCapacityWaiters,
9
9
  codexCredentialLeases,
10
+ codexResetRedemptionAttempts,
10
11
  codexRotationSettings,
11
12
  codexSubscriptionCredentials,
12
13
  composerDrafts,
@@ -37,6 +38,8 @@ import {
37
38
  machineMetricsLatest,
38
39
  machineMetricsSeries,
39
40
  managedAccounts,
41
+ nestedAgentDepthConfiguration,
42
+ newSessionDrafts,
40
43
  packInstallations,
41
44
  rigChanges,
42
45
  rigVersions,
@@ -46,7 +49,12 @@ import {
46
49
  sandboxLeaseLivenessValues,
47
50
  sandboxLeases,
48
51
  sandboxPtySessions,
52
+ sandboxRetainedProcessStateValues,
53
+ sandboxRetainedProcesses,
49
54
  sandboxSessionEnvelopes,
55
+ sandboxWorkspaceMutationActorKindValues,
56
+ sandboxWorkspaceMutationAdmissions,
57
+ sandboxWorkspaceMutationHolderKindValues,
50
58
  sandboxes,
51
59
  scheduledTaskRuns,
52
60
  scheduledTasks,
@@ -64,6 +72,7 @@ import {
64
72
  sessionRecordingModeValues,
65
73
  sessionRecordingStateValues,
66
74
  sessionRecordings,
75
+ sessionSpawnDenials,
67
76
  sessionSystemUpdateOutbox,
68
77
  sessionSystemUpdates,
69
78
  sessionTurnAttempts,
@@ -84,7 +93,7 @@ import {
84
93
  workspaceVariableSetVariables,
85
94
  workspaceVariableSets,
86
95
  workspaces
87
- } from "./chunk-4LG5NBTC.js";
96
+ } from "./chunk-VUKRIBO5.js";
88
97
  import "./chunk-PZ5AY32C.js";
89
98
  export {
90
99
  agentRunStates,
@@ -95,6 +104,7 @@ export {
95
104
  capabilityInstallations,
96
105
  codexCapacityWaiters,
97
106
  codexCredentialLeases,
107
+ codexResetRedemptionAttempts,
98
108
  codexRotationSettings,
99
109
  codexSubscriptionCredentials,
100
110
  composerDrafts,
@@ -125,6 +135,8 @@ export {
125
135
  machineMetricsLatest,
126
136
  machineMetricsSeries,
127
137
  managedAccounts,
138
+ nestedAgentDepthConfiguration,
139
+ newSessionDrafts,
128
140
  packInstallations,
129
141
  rigChanges,
130
142
  rigVersions,
@@ -134,7 +146,12 @@ export {
134
146
  sandboxLeaseLivenessValues,
135
147
  sandboxLeases,
136
148
  sandboxPtySessions,
149
+ sandboxRetainedProcessStateValues,
150
+ sandboxRetainedProcesses,
137
151
  sandboxSessionEnvelopes,
152
+ sandboxWorkspaceMutationActorKindValues,
153
+ sandboxWorkspaceMutationAdmissions,
154
+ sandboxWorkspaceMutationHolderKindValues,
138
155
  sandboxes,
139
156
  scheduledTaskRuns,
140
157
  scheduledTasks,
@@ -152,6 +169,7 @@ export {
152
169
  sessionRecordingModeValues,
153
170
  sessionRecordingStateValues,
154
171
  sessionRecordings,
172
+ sessionSpawnDenials,
155
173
  sessionSystemUpdateOutbox,
156
174
  sessionSystemUpdates,
157
175
  sessionTurnAttempts,
@@ -1,5 +1,5 @@
1
1
  -- 0053_codex_credential_leases.sql
2
- -- OPE-21: fair, atomic Codex subscription selection across worker replicas.
2
+ -- tracking-21: fair, atomic Codex subscription selection across worker replicas.
3
3
  --
4
4
  -- Every field in this migration is workspace-local. In particular, the same
5
5
  -- external ChatGPT subscription connected in two workspaces is intentionally
@@ -227,4 +227,4 @@ BEGIN
227
227
  app_role
228
228
  );
229
229
  END IF;
230
- END $$;
230
+ END $$;
@@ -1,4 +1,4 @@
1
- -- OPE-18/OPE-21/OPE-22: one prompt queue, one current inference, portable
1
+ -- tracking-18/tracking-21/tracking-22: one prompt queue, one current inference, portable
2
2
  -- compaction, attempt-fenced publication, coalesced internal updates, and
3
3
  -- session/workspace Pause.
4
4
  --
@@ -1,4 +1,4 @@
1
- -- OPE-50: replace the blind periodic scan of "enrollable" sessions with a
1
+ -- tracking-50: replace the blind periodic scan of "enrollable" sessions with a
2
2
  -- transactional, revisioned, coalescing delivery ledger. Postgres is the
3
3
  -- durable work source; a Temporal signal is an idempotent nudge.
4
4
 
@@ -1,4 +1,4 @@
1
- -- OPE-44: session list reads are serializable and subject-scoped. Performing a
1
+ -- tracking-44: session list reads are serializable and subject-scoped. Performing a
2
2
  -- global expired-row delete inside every read makes concurrent API replicas
3
3
  -- conflict on the same rows. Move TTL cleanup to one bounded SKIP LOCKED
4
4
  -- reaper operation and keep the request transaction strictly request-local.
@@ -1,5 +1,5 @@
1
1
  -- deployment-mode: maintenance
2
- -- OPE-18/OPE-54: one-way queue/control maintenance cutover. Old workers are
2
+ -- tracking-18/tracking-54: one-way queue/control maintenance cutover. Old workers are
3
3
  -- drained before this migration; obsolete columns are removed in this same
4
4
  -- transaction so no mixed runtime architecture can survive deployment.
5
5
 
@@ -1,5 +1,5 @@
1
1
  -- deployment-mode: rolling
2
- -- OPE-36: the strategy picker is gone — rotation-enabled always behaves as
2
+ -- tracking-36: the strategy picker is gone — rotation-enabled always behaves as
3
3
  -- sticky-sharded (worker-side effectiveRotationStrategy normalizes every read).
4
4
  -- Backfill stored legacy values so the column tells the truth going forward.
5
5
  -- The column itself is KEPT (old-binary rollback safety): an old worker reading
@@ -0,0 +1,168 @@
1
+ -- deployment-mode: maintenance
2
+ -- Codex quota: trustworthy Codex subscription overview, allocator OCC/audit, and
3
+ -- owning-human reset-credit redemption.
4
+ --
5
+ -- Old API binaries do not write connected_by_subject_id and do not fence
6
+ -- disconnect/reconnect against unresolved provider attempts. Drain every old
7
+ -- API replica before applying this migration, then start only this revision;
8
+ -- mixed-version writers would invalidate the owning-human redemption boundary.
9
+ --
10
+ -- tracking-21 exclusively owns allocator_enabled in migration 0053. This migration
11
+ -- only adds the independent OCC/audit fields, provider summary cache, connecting
12
+ -- human attribution, and the durable ambiguity-safe redemption state machine.
13
+
14
+ ALTER TABLE "codex_subscription_credentials"
15
+ ADD COLUMN IF NOT EXISTS "allocator_version" integer NOT NULL DEFAULT 1,
16
+ ADD COLUMN IF NOT EXISTS "allocator_updated_by_subject_id" text,
17
+ ADD COLUMN IF NOT EXISTS "allocator_updated_at" timestamptz,
18
+ ADD COLUMN IF NOT EXISTS "reset_credit_available_count" integer,
19
+ ADD COLUMN IF NOT EXISTS "reset_credits_checked_at" timestamptz,
20
+ ADD COLUMN IF NOT EXISTS "connected_by_subject_id" text;
21
+
22
+ DO $$
23
+ BEGIN
24
+ IF NOT EXISTS (
25
+ SELECT 1 FROM pg_constraint
26
+ WHERE conname = 'codex_subscription_credentials_allocator_version_check'
27
+ AND conrelid = 'codex_subscription_credentials'::regclass
28
+ ) THEN
29
+ ALTER TABLE "codex_subscription_credentials"
30
+ ADD CONSTRAINT "codex_subscription_credentials_allocator_version_check"
31
+ CHECK (allocator_version > 0) NOT VALID;
32
+ END IF;
33
+ IF NOT EXISTS (
34
+ SELECT 1 FROM pg_constraint
35
+ WHERE conname = 'codex_subscription_credentials_reset_count_check'
36
+ AND conrelid = 'codex_subscription_credentials'::regclass
37
+ ) THEN
38
+ ALTER TABLE "codex_subscription_credentials"
39
+ ADD CONSTRAINT "codex_subscription_credentials_reset_count_check"
40
+ CHECK (reset_credit_available_count IS NULL OR reset_credit_available_count >= 0) NOT VALID;
41
+ END IF;
42
+ IF NOT EXISTS (
43
+ SELECT 1 FROM pg_constraint
44
+ WHERE conname = 'codex_subscription_credentials_human_owner_check'
45
+ AND conrelid = 'codex_subscription_credentials'::regclass
46
+ ) THEN
47
+ ALTER TABLE "codex_subscription_credentials"
48
+ ADD CONSTRAINT "codex_subscription_credentials_human_owner_check"
49
+ CHECK (connected_by_subject_id IS NULL OR connected_by_subject_id LIKE 'user:_%') NOT VALID;
50
+ END IF;
51
+ END $$;
52
+
53
+ ALTER TABLE "codex_subscription_credentials"
54
+ VALIDATE CONSTRAINT "codex_subscription_credentials_allocator_version_check";
55
+ ALTER TABLE "codex_subscription_credentials"
56
+ VALIDATE CONSTRAINT "codex_subscription_credentials_reset_count_check";
57
+ ALTER TABLE "codex_subscription_credentials"
58
+ VALIDATE CONSTRAINT "codex_subscription_credentials_human_owner_check";
59
+
60
+ CREATE TABLE IF NOT EXISTS "codex_reset_redemption_attempts" (
61
+ -- Browser-generated logical id. Reusing it is what prevents one ambiguous
62
+ -- click/reload/retry from becoming a second logical redemption.
63
+ "id" uuid PRIMARY KEY NOT NULL,
64
+ "account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
65
+ "workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
66
+ "credential_id" uuid NOT NULL,
67
+ "subject_id" text NOT NULL,
68
+ -- SHA-256 of the Better Auth session id. The raw session id and cookies never
69
+ -- enter product tables, logs, audit metadata, or browser responses.
70
+ "browser_session_hash" text NOT NULL,
71
+ -- Required for an ambiguity retry. It is intentionally absent from audit and
72
+ -- event metadata; provider opaque ids are not observability dimensions.
73
+ "credit_id" text NOT NULL,
74
+ -- Generated once by the server and reused for every upstream retry.
75
+ "upstream_idempotency_key" uuid NOT NULL DEFAULT gen_random_uuid(),
76
+ "status" text NOT NULL DEFAULT 'processing',
77
+ "outcome" text,
78
+ "claim_holder_id" uuid,
79
+ "claim_expires_at" timestamptz,
80
+ "confirmation_expires_at" timestamptz NOT NULL,
81
+ "provider_started_at" timestamptz,
82
+ "completed_at" timestamptz,
83
+ "last_failure_kind" text,
84
+ "retry_count" integer NOT NULL DEFAULT 0,
85
+ "created_at" timestamptz NOT NULL DEFAULT now(),
86
+ "updated_at" timestamptz NOT NULL DEFAULT now(),
87
+ CONSTRAINT "codex_reset_redemption_workspace_account_fk"
88
+ FOREIGN KEY ("workspace_id", "account_id")
89
+ REFERENCES "workspaces"("id", "account_id")
90
+ ON DELETE CASCADE,
91
+ -- Deliberately no credential FK: a disconnect must never cascade-delete the
92
+ -- only durable upstream redeem_request_id after provider work may have begun.
93
+ -- Accessors validate and lock the workspace credential before every send;
94
+ -- completed history may outlive a later safe credential disconnect.
95
+ CONSTRAINT "codex_reset_redemption_status_check"
96
+ CHECK (status IN ('processing', 'provider_started', 'completed')),
97
+ CONSTRAINT "codex_reset_redemption_outcome_check"
98
+ CHECK (outcome IS NULL OR outcome IN ('reset', 'nothingToReset', 'noCredit', 'alreadyRedeemed')),
99
+ CONSTRAINT "codex_reset_redemption_completed_check"
100
+ CHECK ((status = 'completed') = (outcome IS NOT NULL AND completed_at IS NOT NULL)),
101
+ CONSTRAINT "codex_reset_redemption_retry_count_check"
102
+ CHECK (retry_count >= 0),
103
+ CONSTRAINT "codex_reset_redemption_human_subject_check"
104
+ CHECK (subject_id LIKE 'user:_%')
105
+ );
106
+
107
+ -- Keep this additive/idempotent for forward recovery from a previously completed
108
+ -- equivalent schema state.
109
+ DO $$
110
+ BEGIN
111
+ IF NOT EXISTS (
112
+ SELECT 1 FROM pg_constraint
113
+ WHERE conname = 'codex_reset_redemption_human_subject_check'
114
+ AND conrelid = 'codex_reset_redemption_attempts'::regclass
115
+ ) THEN
116
+ ALTER TABLE "codex_reset_redemption_attempts"
117
+ ADD CONSTRAINT "codex_reset_redemption_human_subject_check"
118
+ CHECK (subject_id LIKE 'user:_%') NOT VALID;
119
+ END IF;
120
+ END $$;
121
+ ALTER TABLE "codex_reset_redemption_attempts"
122
+ VALIDATE CONSTRAINT "codex_reset_redemption_human_subject_check";
123
+
124
+ CREATE UNIQUE INDEX IF NOT EXISTS "codex_reset_redemption_upstream_key_idx"
125
+ ON "codex_reset_redemption_attempts" ("upstream_idempotency_key");
126
+ -- A provider credit can have only one active or successfully consumed logical
127
+ -- attempt. Provider outcomes nothingToReset/noCredit are explicitly non-success
128
+ -- outcomes and must not permanently prevent a later, newly confirmed attempt.
129
+ CREATE UNIQUE INDEX IF NOT EXISTS "codex_reset_redemption_credential_credit_idx"
130
+ ON "codex_reset_redemption_attempts" ("workspace_id", "credential_id", "credit_id")
131
+ WHERE status <> 'completed' OR outcome IN ('reset', 'alreadyRedeemed');
132
+ CREATE INDEX IF NOT EXISTS "codex_reset_redemption_workspace_credential_idx"
133
+ ON "codex_reset_redemption_attempts" ("workspace_id", "credential_id", "created_at" DESC);
134
+ CREATE INDEX IF NOT EXISTS "codex_reset_redemption_claim_expiry_idx"
135
+ ON "codex_reset_redemption_attempts" ("claim_expires_at")
136
+ WHERE status <> 'completed';
137
+
138
+ ALTER TABLE "codex_reset_redemption_attempts" ENABLE ROW LEVEL SECURITY;
139
+ ALTER TABLE "codex_reset_redemption_attempts" FORCE ROW LEVEL SECURITY;
140
+ DO $$
141
+ BEGIN
142
+ IF EXISTS (
143
+ SELECT 1 FROM pg_policies
144
+ WHERE schemaname = current_schema()
145
+ AND tablename = 'codex_reset_redemption_attempts'
146
+ AND policyname = 'workspace_isolation'
147
+ ) THEN
148
+ DROP POLICY workspace_isolation ON "codex_reset_redemption_attempts";
149
+ END IF;
150
+ END $$;
151
+
152
+ CREATE POLICY workspace_isolation ON "codex_reset_redemption_attempts"
153
+ USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
154
+ WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
155
+
156
+ DO $$
157
+ DECLARE
158
+ target_schema text := current_schema();
159
+ app_role text := 'opengeni_app';
160
+ BEGIN
161
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = app_role) THEN
162
+ EXECUTE format(
163
+ 'GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA %I TO %I',
164
+ target_schema,
165
+ app_role
166
+ );
167
+ END IF;
168
+ END $$;
@@ -0,0 +1,38 @@
1
+ -- deployment-mode: rolling
2
+ -- Persist the origin of a session's tool allow-list. NULL is a
3
+ -- deliberate legacy marker for rows created before policy provenance existed.
4
+ ALTER TABLE "sessions"
5
+ ADD COLUMN IF NOT EXISTS "tool_policy" jsonb;
6
+
7
+ ALTER TABLE "sessions"
8
+ DROP CONSTRAINT IF EXISTS "sessions_tool_policy_shape_check";
9
+
10
+ ALTER TABLE "sessions"
11
+ ADD CONSTRAINT "sessions_tool_policy_shape_check"
12
+ CHECK (
13
+ "tool_policy" IS NULL
14
+ OR (
15
+ jsonb_typeof("tool_policy") = 'object'
16
+ AND "tool_policy" ? 'mode'
17
+ AND ("tool_policy" ->> 'mode') IN ('workspace_default', 'explicit', 'inherited', 'legacy')
18
+ AND "tool_policy" ? 'inheritedFromSessionId'
19
+ AND (
20
+ ("tool_policy" ->> 'inheritedFromSessionId') IS NULL
21
+ OR ("tool_policy" ->> 'inheritedFromSessionId') ~ '^[0-9a-fA-F-]{36}$'
22
+ )
23
+ )
24
+ ) NOT VALID;
25
+
26
+ -- Follow-up turns also need provenance: an omitted tools key inherits the
27
+ -- session policy, while an explicit array replaces it for that turn (subject
28
+ -- to the session subset fence). Existing turns used merge semantics and their
29
+ -- selected refs are already materialized on sessions.tools, so false preserves
30
+ -- their effective allow-list during the rolling upgrade.
31
+ ALTER TABLE "session_turns"
32
+ ADD COLUMN IF NOT EXISTS "tools_provided" boolean NOT NULL DEFAULT false;
33
+
34
+ -- Human composer drafts need the same provenance across reloads. Without this,
35
+ -- [] cannot distinguish "inherit the session policy" from an intentional
36
+ -- per-turn empty selection.
37
+ ALTER TABLE "composer_drafts"
38
+ ADD COLUMN IF NOT EXISTS "tools_provided" boolean NOT NULL DEFAULT false;
@@ -1,5 +1,5 @@
1
1
  -- deployment-mode: rolling
2
- -- OPE-64: session_events is the lossy human/audit projection, not a blob store.
2
+ -- tracking-64: session_events is the lossy human/audit projection, not a blob store.
3
3
  -- Install the BEFORE trigger before the NOT VALID check so an older pod in the
4
4
  -- same rolling deployment is normalized instead of having an oversized write
5
5
  -- rejected. Historical oversized rows stay readable and can be defensively
@@ -206,4 +206,4 @@ ALTER TABLE session_events
206
206
  NOT VALID,
207
207
  ADD CONSTRAINT session_events_duplicate_reason_bytes_check
208
208
  CHECK (duplicate_reason IS NULL OR octet_length(duplicate_reason) <= 4096)
209
- NOT VALID;
209
+ NOT VALID;
@@ -1,5 +1,5 @@
1
1
  -- deployment-mode: rolling
2
- -- OPE-64: workspace-control rows are compact invalidations, not evidence blobs.
2
+ -- tracking-64: workspace-control rows are compact invalidations, not evidence blobs.
3
3
  -- Preserve exact source byte counts while bounding the two free-form fields so
4
4
  -- old binaries and direct writers cannot create a durable replay poison row.
5
5
 
@@ -131,4 +131,4 @@ ALTER TABLE workspace_control_events
131
131
  VALIDATE CONSTRAINT workspace_control_events_reason_bytes_check,
132
132
  VALIDATE CONSTRAINT workspace_control_events_actor_bytes_check,
133
133
  VALIDATE CONSTRAINT workspace_control_events_original_bytes_check,
134
- VALIDATE CONSTRAINT workspace_control_events_actor_original_bytes_check;
134
+ VALIDATE CONSTRAINT workspace_control_events_actor_original_bytes_check;
@@ -1,5 +1,5 @@
1
1
  -- deployment-mode: rolling
2
- -- OPE-64: finish the 0067 expand/contract sequence. The trigger has bounded
2
+ -- tracking-64: finish the 0067 expand/contract sequence. The trigger has bounded
3
3
  -- every new/updated row since 0067; now rewrite only legacy violations through
4
4
  -- that trigger and validate the durable storage invariant.
5
5
 
@@ -29,4 +29,4 @@ ALTER TABLE session_events
29
29
  VALIDATE CONSTRAINT session_events_client_event_id_bytes_check,
30
30
  VALIDATE CONSTRAINT session_events_producer_id_bytes_check,
31
31
  VALIDATE CONSTRAINT session_events_turn_association_bytes_check,
32
- VALIDATE CONSTRAINT session_events_duplicate_reason_bytes_check;
32
+ VALIDATE CONSTRAINT session_events_duplicate_reason_bytes_check;
@@ -1,5 +1,5 @@
1
1
  -- deployment-mode: rolling
2
- -- OPE-65: transactional workspace revisions make updated-order discovery and
2
+ -- tracking-65: transactional workspace revisions make updated-order discovery and
3
3
  -- its next incremental scan one gap-free handoff independent of application
4
4
  -- clocks. Existing sessions remain revision zero until their next activity.
5
5
 
@@ -69,4 +69,4 @@ BEGIN
69
69
  END $grants$;
70
70
 
71
71
  RESET statement_timeout;
72
- RESET lock_timeout;
72
+ RESET lock_timeout;
@@ -0,0 +1,29 @@
1
+ -- deployment-mode: maintenance
2
+ -- Workers are drained before this migration so no executable attempt can cross
3
+ -- the boundary without an immutable approval-policy snapshot. Closed attempts
4
+ -- are historical evidence only and receive an inert empty snapshot.
5
+ SET lock_timeout = '5s';
6
+ SET statement_timeout = '5min';
7
+
8
+ DO $$
9
+ BEGIN
10
+ IF EXISTS (
11
+ SELECT 1
12
+ FROM "session_turn_attempts"
13
+ WHERE "state" <> 'closed'
14
+ LIMIT 1
15
+ ) THEN
16
+ RAISE EXCEPTION
17
+ 'live session turn attempts must be drained before the MCP approval-policy cutover';
18
+ END IF;
19
+ END
20
+ $$;
21
+
22
+ ALTER TABLE "session_turn_attempts"
23
+ ADD COLUMN "mcp_approval_policies" jsonb NOT NULL DEFAULT '{}'::jsonb;
24
+
25
+ -- PostgreSQL installs a constant default without rewriting the historical
26
+ -- table. Remove the default immediately: every new attempt must provide its
27
+ -- claim-time snapshot explicitly.
28
+ ALTER TABLE "session_turn_attempts"
29
+ ALTER COLUMN "mcp_approval_policies" DROP DEFAULT;