@opengeni/db 0.27.9 → 0.28.1

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.
@@ -0,0 +1,86 @@
1
+ -- deployment-mode: maintenance
2
+ -- GitHub App installation credentials are host-owned run material. Retire the
3
+ -- model-visible github_token MCP tool from every durable session selection and
4
+ -- prevent an old writer from reintroducing it after the coordinated cutover.
5
+
6
+ UPDATE "sessions"
7
+ SET "first_party_mcp_tools" = "first_party_mcp_tools" - 'github_token'
8
+ WHERE "first_party_mcp_tools" ? 'github_token';
9
+
10
+ ALTER TABLE "sessions"
11
+ ALTER COLUMN "first_party_mcp_tools"
12
+ SET DEFAULT '[
13
+ "set_session_title",
14
+ "goal_set",
15
+ "goal_update",
16
+ "goal_complete",
17
+ "goal_pause",
18
+ "memory_search",
19
+ "memory_save",
20
+ "memory_correct",
21
+ "preference_registry_summary",
22
+ "preference_registry_get",
23
+ "sandboxes_list",
24
+ "sandbox_attach",
25
+ "sandbox_swap",
26
+ "run_on",
27
+ "sandbox_provision",
28
+ "rig_list",
29
+ "rig_get",
30
+ "rig_propose_change",
31
+ "rig_verify",
32
+ "rig_promote",
33
+ "sessions_list",
34
+ "session_get",
35
+ "session_events",
36
+ "session_create",
37
+ "session_send_message",
38
+ "session_pause",
39
+ "session_resume",
40
+ "session_steer",
41
+ "set_other_session_title",
42
+ "variable_set_list",
43
+ "environment_list",
44
+ "variable_set_set_variable",
45
+ "environment_set_variable",
46
+ "github_connect_link",
47
+ "github_repositories_list",
48
+ "social_connections_list",
49
+ "social_posts_recent",
50
+ "social_daily_analysis_context",
51
+ "social_search_live",
52
+ "social_mentions_live",
53
+ "social_thread_fetch",
54
+ "social_posts_sync",
55
+ "social_post_reply",
56
+ "scheduled_tasks_list",
57
+ "scheduled_tasks_get",
58
+ "scheduled_tasks_create",
59
+ "scheduled_tasks_update",
60
+ "scheduled_tasks_pause",
61
+ "scheduled_tasks_resume",
62
+ "scheduled_tasks_trigger",
63
+ "scheduled_tasks_delete",
64
+ "scheduled_task_runs_list",
65
+ "slack_bot_list_channels",
66
+ "slack_bot_channel_history",
67
+ "slack_bot_thread_replies",
68
+ "slack_bot_list_users",
69
+ "slack_bot_list_files",
70
+ "slack_bot_file_info",
71
+ "slack_bot_file_content",
72
+ "slack_bot_post_message",
73
+ "slack_bot_delete_message",
74
+ "artifacts_list",
75
+ "artifacts_get_source",
76
+ "artifacts_create",
77
+ "artifacts_publish",
78
+ "artifacts_rollback"
79
+ ]'::jsonb;
80
+
81
+ ALTER TABLE "sessions"
82
+ DROP CONSTRAINT IF EXISTS "sessions_first_party_mcp_tools_no_model_credentials_chk";
83
+
84
+ ALTER TABLE "sessions"
85
+ ADD CONSTRAINT "sessions_first_party_mcp_tools_no_model_credentials_chk"
86
+ CHECK (NOT ("first_party_mcp_tools" @> '["github_token"]'::jsonb));
@@ -0,0 +1,107 @@
1
+ -- deployment-mode: maintenance
2
+
3
+ SET LOCAL lock_timeout = '5s';
4
+ SET LOCAL statement_timeout = '10min';
5
+
6
+ -- Reject mixed-version writers before locking, then repeat after the locks to
7
+ -- close the connect-before-lock race. The deployment must keep API and workers
8
+ -- stopped until the new application version is active.
9
+ DO $codex_boundaries_writer_drain_before_lock$
10
+ BEGIN
11
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app')
12
+ AND EXISTS (
13
+ SELECT 1
14
+ FROM pg_stat_activity
15
+ WHERE datname = current_database()
16
+ AND usename = 'opengeni_app'
17
+ AND pid <> pg_backend_pid()
18
+ )
19
+ THEN
20
+ RAISE EXCEPTION
21
+ 'Codex authentication boundaries activation requires all opengeni_app sessions to be stopped'
22
+ USING ERRCODE = '55000';
23
+ END IF;
24
+ END
25
+ $codex_boundaries_writer_drain_before_lock$;
26
+
27
+ LOCK TABLE "codex_subscription_credentials" IN ACCESS EXCLUSIVE MODE;
28
+ LOCK TABLE "session_history_items" IN ACCESS EXCLUSIVE MODE;
29
+ LOCK TABLE "agent_run_states" IN ACCESS EXCLUSIVE MODE;
30
+
31
+ DO $codex_boundaries_writer_drain_after_lock$
32
+ BEGIN
33
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app')
34
+ AND EXISTS (
35
+ SELECT 1
36
+ FROM pg_stat_activity
37
+ WHERE datname = current_database()
38
+ AND usename = 'opengeni_app'
39
+ AND pid <> pg_backend_pid()
40
+ )
41
+ THEN
42
+ RAISE EXCEPTION
43
+ 'Codex authentication boundaries activation requires all opengeni_app sessions to be stopped'
44
+ USING ERRCODE = '55000';
45
+ END IF;
46
+ END
47
+ $codex_boundaries_writer_drain_after_lock$;
48
+
49
+ -- One optional workspace credential for ChatGPT connected Apps. This pointer is
50
+ -- intentionally separate from inference rotation and starts unset.
51
+ CREATE UNIQUE INDEX "codex_subscription_credentials_workspace_account_id_idx"
52
+ ON "codex_subscription_credentials" ("workspace_id", "account_id", "id");
53
+
54
+ CREATE TABLE "codex_apps_settings" (
55
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
56
+ "account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
57
+ "workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
58
+ "credential_id" uuid,
59
+ "version" integer NOT NULL DEFAULT 1,
60
+ "designated_at" timestamptz,
61
+ "updated_at" timestamptz NOT NULL DEFAULT now(),
62
+ CONSTRAINT "codex_apps_settings_workspace_account_fk"
63
+ FOREIGN KEY ("workspace_id", "account_id")
64
+ REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
65
+ CONSTRAINT "codex_apps_settings_credential_scope_fk"
66
+ FOREIGN KEY ("workspace_id", "account_id", "credential_id")
67
+ REFERENCES "codex_subscription_credentials"("workspace_id", "account_id", "id")
68
+ ON DELETE CASCADE,
69
+ CONSTRAINT "codex_apps_settings_designation_shape_chk" CHECK (
70
+ "version" > 0 AND (
71
+ ("credential_id" IS NULL AND "designated_at" IS NULL)
72
+ OR
73
+ ("credential_id" IS NOT NULL AND "designated_at" IS NOT NULL)
74
+ )
75
+ )
76
+ );
77
+
78
+ CREATE UNIQUE INDEX "codex_apps_settings_workspace_idx"
79
+ ON "codex_apps_settings" ("workspace_id");
80
+
81
+ ALTER TABLE "codex_apps_settings" ENABLE ROW LEVEL SECURITY;
82
+ ALTER TABLE "codex_apps_settings" FORCE ROW LEVEL SECURITY;
83
+ CREATE POLICY workspace_isolation ON "codex_apps_settings"
84
+ USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
85
+ WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
86
+
87
+ -- Remove the false credential/history relation and the obsolete
88
+ -- connector-aware inference cache. Provider rejection receipts remain.
89
+ ALTER TABLE "session_history_items"
90
+ DROP COLUMN "producer_codex_credential_id";
91
+ ALTER TABLE "agent_run_states"
92
+ DROP COLUMN "frozen_codex_credential_id";
93
+ ALTER TABLE "codex_subscription_credentials"
94
+ DROP COLUMN "connector_namespaces",
95
+ DROP COLUMN "connectors_checked_at";
96
+
97
+ DO $$
98
+ DECLARE
99
+ target_schema text := current_schema();
100
+ BEGIN
101
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
102
+ EXECUTE format(
103
+ 'GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE %I.codex_apps_settings TO opengeni_app',
104
+ target_schema
105
+ );
106
+ END IF;
107
+ END $$;
@@ -0,0 +1,80 @@
1
+ -- deployment-mode: rolling
2
+ -- Historical, fully quiesced interruptions are audit evidence, not live control work.
3
+
4
+ SET lock_timeout = '5s';
5
+ SET statement_timeout = '10min';
6
+
7
+ DROP FUNCTION opengeni_private.claim_session_workflow_wakes(integer);
8
+
9
+ DO $migration$
10
+ DECLARE target_schema text := current_schema();
11
+ BEGIN
12
+ EXECUTE format($create$
13
+ CREATE FUNCTION opengeni_private.claim_session_workflow_wakes(p_limit integer)
14
+ RETURNS TABLE (
15
+ account_id uuid,
16
+ workspace_id uuid,
17
+ session_id uuid,
18
+ temporal_workflow_id text,
19
+ wake_revision bigint,
20
+ interruption_requested boolean
21
+ )
22
+ LANGUAGE plpgsql
23
+ SECURITY DEFINER
24
+ SET search_path = pg_catalog
25
+ AS $function$
26
+ BEGIN
27
+ RETURN QUERY
28
+ WITH due AS (
29
+ SELECT o.session_id
30
+ FROM %1$I.session_workflow_wake_outbox o
31
+ WHERE o.wake_revision > o.delivered_revision
32
+ AND o.next_attempt_at <= now()
33
+ ORDER BY o.next_attempt_at, o.updated_at, o.session_id
34
+ FOR UPDATE SKIP LOCKED
35
+ LIMIT greatest(1, least(coalesce(p_limit, 100), 1000))
36
+ )
37
+ UPDATE %1$I.session_workflow_wake_outbox o
38
+ SET attempts = o.attempts + 1,
39
+ next_attempt_at = now() + make_interval(
40
+ secs => least(300, greatest(1, power(2, least(o.attempts, 8))::integer))
41
+ ),
42
+ updated_at = now()
43
+ FROM due
44
+ WHERE o.session_id = due.session_id
45
+ RETURNING o.account_id, o.workspace_id, o.session_id,
46
+ o.temporal_workflow_id, o.wake_revision,
47
+ o.control_revision > o.delivered_revision
48
+ OR EXISTS (
49
+ SELECT 1
50
+ FROM %1$I.session_attempt_interruptions interruption
51
+ JOIN %1$I.session_turn_attempts attempt
52
+ ON attempt.workspace_id = interruption.workspace_id
53
+ AND attempt.session_id = interruption.session_id
54
+ AND attempt.id = interruption.attempt_id
55
+ WHERE interruption.workspace_id = o.workspace_id
56
+ AND interruption.session_id = o.session_id
57
+ AND (
58
+ interruption.state IN ('pending', 'delivered', 'acknowledged')
59
+ OR (
60
+ interruption.state IN ('settled', 'rejected_stale')
61
+ AND attempt.quiesced_at IS NULL
62
+ )
63
+ )
64
+ ) AS interruption_requested;
65
+ END $function$;
66
+ $create$, target_schema);
67
+ END $migration$;
68
+
69
+ REVOKE ALL ON FUNCTION opengeni_private.claim_session_workflow_wakes(integer) FROM PUBLIC;
70
+
71
+ DO $$
72
+ BEGIN
73
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
74
+ GRANT EXECUTE ON FUNCTION opengeni_private.claim_session_workflow_wakes(integer)
75
+ TO opengeni_app;
76
+ END IF;
77
+ END $$;
78
+
79
+ RESET statement_timeout;
80
+ RESET lock_timeout;
@@ -0,0 +1,24 @@
1
+ -- deployment-mode: rolling
2
+
3
+ ALTER TABLE "transcription_recording_segments"
4
+ ADD COLUMN "attempt_deadline_at" timestamptz;
5
+
6
+ -- Rows already in flight when this migration rolls out retain the original
7
+ -- fifteen-minute reclaim fence. New attempts receive the shorter provider
8
+ -- deadline from the API claim path.
9
+ UPDATE "transcription_recording_segments"
10
+ SET "attempt_deadline_at" = "attempt_started_at" + interval '10 minutes'
11
+ WHERE "attempt_id" IS NOT NULL
12
+ AND "attempt_started_at" IS NOT NULL
13
+ AND "attempt_deadline_at" IS NULL;
14
+
15
+ ALTER TABLE "transcription_recording_segments"
16
+ ADD CONSTRAINT "transcription_recording_segments_attempt_deadline_check"
17
+ CHECK (
18
+ ("attempt_id" IS NULL AND "attempt_started_at" IS NULL AND "attempt_deadline_at" IS NULL)
19
+ OR (
20
+ "attempt_id" IS NOT NULL
21
+ AND "attempt_started_at" IS NOT NULL
22
+ AND "attempt_deadline_at" IS NOT NULL
23
+ )
24
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/db",
3
- "version": "0.27.9",
3
+ "version": "0.28.1",
4
4
  "description": "OpenGeni persistence: Drizzle schema, RLS-scoped query layer, the SQL migration runner, and role provisioning.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -50,9 +50,9 @@
50
50
  "prepublishOnly": "bash ../../scripts/prepublish-guard"
51
51
  },
52
52
  "dependencies": {
53
- "@opengeni/codex": "^0.2.10",
54
- "@opengeni/config": "^0.10.12",
55
- "@opengeni/contracts": "^0.38.2",
53
+ "@opengeni/codex": "^0.2.11",
54
+ "@opengeni/config": "^0.11.0",
55
+ "@opengeni/contracts": "^0.39.0",
56
56
  "@opengeni/network": "^0.2.0",
57
57
  "drizzle-orm": "^0.45.2",
58
58
  "postgres": "^3.4.7"