@opengeni/db 0.22.1 → 0.23.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 (48) hide show
  1. package/dist/{chunk-CYGFLLMN.js → chunk-3UCHDMKG.js} +656 -282
  2. package/dist/chunk-3UCHDMKG.js.map +1 -0
  3. package/dist/{chunk-BNGEN5QZ.js → chunk-L6ADMZHE.js} +24 -2
  4. package/dist/chunk-L6ADMZHE.js.map +1 -0
  5. package/dist/index.d.ts +42 -3
  6. package/dist/index.js +6919 -3760
  7. package/dist/index.js.map +1 -1
  8. package/dist/provision-roles.js +1 -1
  9. package/dist/runtime-posture.d.ts +3 -3
  10. package/dist/schema.d.ts +1416 -92
  11. package/dist/schema.js +11 -1
  12. package/dist/session-control.d.ts +7 -1
  13. package/dist/session-queue-commands.d.ts +8 -0
  14. package/dist/session-realtime-context.d.ts +56 -0
  15. package/dist/session-realtime-ledger.d.ts +188 -0
  16. package/dist/session-realtime-mirror.d.ts +30 -0
  17. package/dist/session-realtime-state.d.ts +2 -0
  18. package/dist/session-realtime-terminal.d.ts +40 -0
  19. package/dist/session-realtime.d.ts +59 -0
  20. package/dist/workspace-instruction-policies-schema.d.ts +239 -0
  21. package/dist/workspace-instruction-policies.d.ts +44 -0
  22. package/drizzle/0156_slack_reaction_trigger.sql +49 -0
  23. package/drizzle/0157_session_policy_role_snapshots.sql +1146 -0
  24. package/drizzle/0158_session_realtime_mode.sql +88 -0
  25. package/drizzle/0159_session_realtime_ledger.sql +198 -0
  26. package/drizzle/0160_session_realtime_delegation_terminal.sql +38 -0
  27. package/drizzle/0161_session_realtime_context_projection.sql +82 -0
  28. package/drizzle/0162_session_realtime_connection_promotion.sql +53 -0
  29. package/drizzle/0163_session_realtime_delegation_progress.sql +35 -0
  30. package/drizzle/0164_session_realtime_models.sql +28 -0
  31. package/package.json +4 -4
  32. package/src/index.ts +670 -79
  33. package/src/preference-registry.ts +11 -6
  34. package/src/provision-roles.ts +12 -0
  35. package/src/runtime-posture.ts +10 -0
  36. package/src/schema.ts +400 -43
  37. package/src/session-control.ts +596 -21
  38. package/src/session-queue-commands.ts +76 -7
  39. package/src/session-realtime-context.ts +393 -0
  40. package/src/session-realtime-ledger.ts +1790 -0
  41. package/src/session-realtime-mirror.ts +160 -0
  42. package/src/session-realtime-state.ts +25 -0
  43. package/src/session-realtime-terminal.ts +306 -0
  44. package/src/session-realtime.ts +611 -0
  45. package/src/workspace-instruction-policies-schema.ts +41 -0
  46. package/src/workspace-instruction-policies.ts +131 -2
  47. package/dist/chunk-BNGEN5QZ.js.map +0 -1
  48. package/dist/chunk-CYGFLLMN.js.map +0 -1
@@ -0,0 +1,88 @@
1
+ -- deployment-mode: rolling
2
+ -- Rebased after the current main migration ledger.
3
+ -- Durable per-session ownership for the temporary normal -> realtime -> normal mode.
4
+
5
+ SET lock_timeout = '5s';
6
+ SET statement_timeout = '10min';
7
+
8
+ CREATE TABLE "session_realtime_modes" (
9
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
10
+ "account_id" uuid NOT NULL,
11
+ "workspace_id" uuid NOT NULL,
12
+ "session_id" uuid NOT NULL,
13
+ "operation_id" uuid NOT NULL,
14
+ "owner_subject_id" text NOT NULL,
15
+ "browser_instance_id" text NOT NULL,
16
+ "owner_key_hash" text NOT NULL,
17
+ "model" text NOT NULL,
18
+ "state" text DEFAULT 'active' NOT NULL,
19
+ "version" integer DEFAULT 1 NOT NULL,
20
+ "connection_epoch" integer DEFAULT 1 NOT NULL,
21
+ "lease_expires_at" timestamptz NOT NULL,
22
+ "last_heartbeat_at" timestamptz NOT NULL,
23
+ "started_at" timestamptz DEFAULT now() NOT NULL,
24
+ "ended_at" timestamptz,
25
+ "end_reason" text,
26
+ "created_at" timestamptz DEFAULT now() NOT NULL,
27
+ "updated_at" timestamptz DEFAULT now() NOT NULL,
28
+ CONSTRAINT "session_realtime_modes_workspace_account_fk"
29
+ FOREIGN KEY ("workspace_id", "account_id")
30
+ REFERENCES "workspaces" ("id", "account_id") ON DELETE CASCADE,
31
+ CONSTRAINT "session_realtime_modes_workspace_session_fk"
32
+ FOREIGN KEY ("workspace_id", "session_id")
33
+ REFERENCES "sessions" ("workspace_id", "id") ON DELETE CASCADE,
34
+ CONSTRAINT "session_realtime_modes_state_check"
35
+ CHECK ("state" IN ('active', 'ended')),
36
+ CONSTRAINT "session_realtime_modes_model_check"
37
+ CHECK ("model" = 'gpt-live-1-boulder-alpha'),
38
+ CONSTRAINT "session_realtime_modes_end_reason_check"
39
+ CHECK ("end_reason" IS NULL OR "end_reason" IN ('user_stop', 'browser_unload', 'lease_expired')),
40
+ CONSTRAINT "session_realtime_modes_version_check" CHECK ("version" >= 1),
41
+ CONSTRAINT "session_realtime_modes_epoch_check" CHECK ("connection_epoch" >= 1),
42
+ CONSTRAINT "session_realtime_modes_owner_subject_check"
43
+ CHECK (octet_length("owner_subject_id") BETWEEN 1 AND 1024),
44
+ CONSTRAINT "session_realtime_modes_browser_instance_check"
45
+ CHECK (octet_length("browser_instance_id") BETWEEN 1 AND 256),
46
+ CONSTRAINT "session_realtime_modes_owner_key_hash_check"
47
+ CHECK ("owner_key_hash" ~ '^[0-9a-f]{64}$'),
48
+ CONSTRAINT "session_realtime_modes_lease_check"
49
+ CHECK ("lease_expires_at" > "last_heartbeat_at"),
50
+ CONSTRAINT "session_realtime_modes_terminal_check"
51
+ CHECK (
52
+ ("state" = 'active' AND "ended_at" IS NULL AND "end_reason" IS NULL)
53
+ OR
54
+ ("state" = 'ended' AND "ended_at" IS NOT NULL AND "end_reason" IS NOT NULL)
55
+ )
56
+ );
57
+
58
+ CREATE UNIQUE INDEX "session_realtime_modes_operation_uq"
59
+ ON "session_realtime_modes" ("workspace_id", "session_id", "operation_id");
60
+
61
+ CREATE UNIQUE INDEX "session_realtime_modes_one_active_uq"
62
+ ON "session_realtime_modes" ("workspace_id", "session_id")
63
+ WHERE "state" = 'active';
64
+
65
+ CREATE INDEX "session_realtime_modes_active_lease_idx"
66
+ ON "session_realtime_modes" ("lease_expires_at", "workspace_id", "session_id")
67
+ WHERE "state" = 'active';
68
+
69
+ ALTER TABLE "session_realtime_modes" ENABLE ROW LEVEL SECURITY;
70
+ ALTER TABLE "session_realtime_modes" FORCE ROW LEVEL SECURITY;
71
+
72
+ CREATE POLICY workspace_isolation ON "session_realtime_modes"
73
+ USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
74
+ WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
75
+
76
+ DO $grants$
77
+ DECLARE target_schema text := current_schema();
78
+ BEGIN
79
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
80
+ EXECUTE format(
81
+ 'GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE %I.session_realtime_modes TO opengeni_app',
82
+ target_schema
83
+ );
84
+ END IF;
85
+ END $grants$;
86
+
87
+ RESET statement_timeout;
88
+ RESET lock_timeout;
@@ -0,0 +1,198 @@
1
+ -- deployment-mode: rolling
2
+ -- Rebased after the current main migration ledger.
3
+ -- Durable GPT-Live connection rotation and compact transcript/update/ACK ledger.
4
+
5
+ SET lock_timeout = '5s';
6
+ SET statement_timeout = '10min';
7
+
8
+ CREATE TABLE "session_realtime_connections" (
9
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
10
+ "account_id" uuid NOT NULL,
11
+ "workspace_id" uuid NOT NULL,
12
+ "session_id" uuid NOT NULL,
13
+ "realtime_id" uuid NOT NULL,
14
+ "operation_id" uuid NOT NULL,
15
+ "connection_epoch" integer NOT NULL,
16
+ "startup_fence_sequence" integer DEFAULT 0 NOT NULL,
17
+ "state" text DEFAULT 'negotiating' NOT NULL,
18
+ "sdp_answer" text,
19
+ "failure_code" text,
20
+ "provider_session_id" text,
21
+ "startup_event_id" text,
22
+ "startup_acknowledged_at" timestamptz,
23
+ "negotiated_at" timestamptz,
24
+ "closed_at" timestamptz,
25
+ "created_at" timestamptz DEFAULT now() NOT NULL,
26
+ "updated_at" timestamptz DEFAULT now() NOT NULL,
27
+ CONSTRAINT "session_realtime_connections_workspace_account_fk"
28
+ FOREIGN KEY ("workspace_id", "account_id")
29
+ REFERENCES "workspaces" ("id", "account_id") ON DELETE CASCADE,
30
+ CONSTRAINT "session_realtime_connections_workspace_session_fk"
31
+ FOREIGN KEY ("workspace_id", "session_id")
32
+ REFERENCES "sessions" ("workspace_id", "id") ON DELETE CASCADE,
33
+ CONSTRAINT "session_realtime_connections_realtime_fk"
34
+ FOREIGN KEY ("realtime_id")
35
+ REFERENCES "session_realtime_modes" ("id") ON DELETE CASCADE,
36
+ CONSTRAINT "session_realtime_connections_epoch_check"
37
+ CHECK ("connection_epoch" >= 1),
38
+ CONSTRAINT "session_realtime_connections_startup_fence_check"
39
+ CHECK ("startup_fence_sequence" >= 0),
40
+ CONSTRAINT "session_realtime_connections_state_check"
41
+ CHECK ("state" IN ('negotiating', 'active', 'failed', 'closed')),
42
+ CONSTRAINT "session_realtime_connections_sdp_check"
43
+ CHECK ("sdp_answer" IS NULL OR octet_length("sdp_answer") BETWEEN 1 AND 1048576),
44
+ CONSTRAINT "session_realtime_connections_failure_check"
45
+ CHECK ("failure_code" IS NULL OR octet_length("failure_code") BETWEEN 1 AND 128),
46
+ CONSTRAINT "session_realtime_connections_provider_session_check"
47
+ CHECK ("provider_session_id" IS NULL OR octet_length("provider_session_id") BETWEEN 1 AND 1024),
48
+ CONSTRAINT "session_realtime_connections_startup_event_check"
49
+ CHECK ("startup_event_id" IS NULL OR octet_length("startup_event_id") BETWEEN 1 AND 1024),
50
+ CONSTRAINT "session_realtime_connections_startup_ack_check"
51
+ CHECK (
52
+ ("startup_acknowledged_at" IS NULL AND "provider_session_id" IS NULL AND "startup_event_id" IS NULL)
53
+ OR
54
+ ("startup_acknowledged_at" IS NOT NULL AND "provider_session_id" IS NOT NULL)
55
+ ),
56
+ CONSTRAINT "session_realtime_connections_terminal_check"
57
+ CHECK (
58
+ ("state" = 'negotiating' AND "sdp_answer" IS NULL AND "failure_code" IS NULL AND "negotiated_at" IS NULL AND "closed_at" IS NULL)
59
+ OR
60
+ ("state" = 'active' AND "sdp_answer" IS NOT NULL AND "failure_code" IS NULL AND "negotiated_at" IS NOT NULL AND "closed_at" IS NULL)
61
+ OR
62
+ ("state" = 'failed' AND "sdp_answer" IS NULL AND "failure_code" IS NOT NULL AND "closed_at" IS NOT NULL)
63
+ OR
64
+ ("state" = 'closed' AND "closed_at" IS NOT NULL)
65
+ )
66
+ );
67
+
68
+ CREATE UNIQUE INDEX "session_realtime_connections_operation_uq"
69
+ ON "session_realtime_connections" ("realtime_id", "operation_id");
70
+ CREATE UNIQUE INDEX "session_realtime_connections_epoch_uq"
71
+ ON "session_realtime_connections" ("realtime_id", "connection_epoch");
72
+ CREATE UNIQUE INDEX "session_realtime_connections_one_open_uq"
73
+ ON "session_realtime_connections" ("realtime_id")
74
+ WHERE "state" IN ('negotiating', 'active');
75
+
76
+ CREATE TABLE "session_realtime_entries" (
77
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
78
+ "account_id" uuid NOT NULL,
79
+ "workspace_id" uuid NOT NULL,
80
+ "session_id" uuid NOT NULL,
81
+ "realtime_id" uuid NOT NULL,
82
+ "operation_id" uuid NOT NULL,
83
+ "connection_epoch" integer NOT NULL,
84
+ "sequence" integer NOT NULL,
85
+ "direction" text NOT NULL,
86
+ "kind" text NOT NULL,
87
+ "role" text,
88
+ "provider_event_id" text,
89
+ "delegation_item_id" text,
90
+ "source_update_id" uuid,
91
+ "history_item_id" uuid,
92
+ "turn_id" uuid,
93
+ "text" text,
94
+ "payload" jsonb DEFAULT '{}'::jsonb NOT NULL,
95
+ "client_acked_at" timestamptz,
96
+ "provider_acked_at" timestamptz,
97
+ "created_at" timestamptz DEFAULT now() NOT NULL,
98
+ "updated_at" timestamptz DEFAULT now() NOT NULL,
99
+ CONSTRAINT "session_realtime_entries_workspace_account_fk"
100
+ FOREIGN KEY ("workspace_id", "account_id")
101
+ REFERENCES "workspaces" ("id", "account_id") ON DELETE CASCADE,
102
+ CONSTRAINT "session_realtime_entries_workspace_session_fk"
103
+ FOREIGN KEY ("workspace_id", "session_id")
104
+ REFERENCES "sessions" ("workspace_id", "id") ON DELETE CASCADE,
105
+ CONSTRAINT "session_realtime_entries_realtime_fk"
106
+ FOREIGN KEY ("realtime_id")
107
+ REFERENCES "session_realtime_modes" ("id") ON DELETE CASCADE,
108
+ CONSTRAINT "session_realtime_entries_source_update_fk"
109
+ FOREIGN KEY ("source_update_id")
110
+ REFERENCES "session_system_updates" ("id") ON DELETE SET NULL,
111
+ CONSTRAINT "session_realtime_entries_history_item_fk"
112
+ FOREIGN KEY ("history_item_id")
113
+ REFERENCES "session_history_items" ("id") ON DELETE SET NULL,
114
+ CONSTRAINT "session_realtime_entries_turn_fk"
115
+ FOREIGN KEY ("turn_id")
116
+ REFERENCES "session_turns" ("id") ON DELETE SET NULL,
117
+ CONSTRAINT "session_realtime_entries_epoch_check"
118
+ CHECK ("connection_epoch" >= 1),
119
+ CONSTRAINT "session_realtime_entries_sequence_check"
120
+ CHECK ("sequence" >= 1),
121
+ CONSTRAINT "session_realtime_entries_direction_check"
122
+ CHECK ("direction" IN ('provider_in', 'provider_out')),
123
+ CONSTRAINT "session_realtime_entries_kind_check"
124
+ CHECK ("kind" IN (
125
+ 'user_transcript',
126
+ 'assistant_transcript',
127
+ 'delegation_call',
128
+ 'delegation_result',
129
+ 'interruption',
130
+ 'session_update',
131
+ 'error'
132
+ )),
133
+ CONSTRAINT "session_realtime_entries_role_check"
134
+ CHECK ("role" IS NULL OR "role" IN ('user', 'assistant')),
135
+ CONSTRAINT "session_realtime_entries_provider_event_check"
136
+ CHECK ("provider_event_id" IS NULL OR octet_length("provider_event_id") BETWEEN 1 AND 1024),
137
+ CONSTRAINT "session_realtime_entries_delegation_item_check"
138
+ CHECK ("delegation_item_id" IS NULL OR octet_length("delegation_item_id") BETWEEN 1 AND 1024),
139
+ CONSTRAINT "session_realtime_entries_text_check"
140
+ CHECK ("text" IS NULL OR octet_length("text") <= 131072),
141
+ CONSTRAINT "session_realtime_entries_payload_check"
142
+ CHECK (octet_length("payload"::text) <= 131072),
143
+ CONSTRAINT "session_realtime_entries_turn_check"
144
+ CHECK ("turn_id" IS NULL OR "kind" = 'delegation_call'),
145
+ CONSTRAINT "session_realtime_entries_transcript_check"
146
+ CHECK (
147
+ ("kind" = 'user_transcript' AND "role" = 'user' AND "text" IS NOT NULL)
148
+ OR
149
+ ("kind" = 'assistant_transcript' AND "role" = 'assistant' AND "text" IS NOT NULL)
150
+ OR
151
+ ("kind" NOT IN ('user_transcript', 'assistant_transcript') AND "role" IS NULL)
152
+ )
153
+ );
154
+
155
+ CREATE UNIQUE INDEX "session_realtime_entries_operation_uq"
156
+ ON "session_realtime_entries" ("realtime_id", "operation_id");
157
+ CREATE UNIQUE INDEX "session_realtime_entries_sequence_uq"
158
+ ON "session_realtime_entries" ("realtime_id", "sequence");
159
+ CREATE UNIQUE INDEX "session_realtime_entries_source_update_uq"
160
+ ON "session_realtime_entries" ("realtime_id", "source_update_id")
161
+ WHERE "source_update_id" IS NOT NULL;
162
+ CREATE UNIQUE INDEX "session_realtime_entries_delegation_turn_uq"
163
+ ON "session_realtime_entries" ("turn_id")
164
+ WHERE "turn_id" IS NOT NULL;
165
+ CREATE UNIQUE INDEX "session_realtime_entries_delegation_call_uq"
166
+ ON "session_realtime_entries" ("realtime_id", "delegation_item_id")
167
+ WHERE "kind" = 'delegation_call' AND "delegation_item_id" IS NOT NULL;
168
+ CREATE INDEX "session_realtime_entries_outbound_pending_idx"
169
+ ON "session_realtime_entries" ("realtime_id", "sequence")
170
+ WHERE "direction" = 'provider_out'
171
+ AND ("client_acked_at" IS NULL OR "provider_acked_at" IS NULL);
172
+
173
+ ALTER TABLE "session_realtime_connections" ENABLE ROW LEVEL SECURITY;
174
+ ALTER TABLE "session_realtime_connections" FORCE ROW LEVEL SECURITY;
175
+ ALTER TABLE "session_realtime_entries" ENABLE ROW LEVEL SECURITY;
176
+ ALTER TABLE "session_realtime_entries" FORCE ROW LEVEL SECURITY;
177
+
178
+ CREATE POLICY workspace_isolation ON "session_realtime_connections"
179
+ USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
180
+ WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
181
+ CREATE POLICY workspace_isolation ON "session_realtime_entries"
182
+ USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
183
+ WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
184
+
185
+ DO $grants$
186
+ DECLARE target_schema text := current_schema();
187
+ BEGIN
188
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
189
+ EXECUTE format(
190
+ 'GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE %I.session_realtime_connections, %I.session_realtime_entries TO opengeni_app',
191
+ target_schema,
192
+ target_schema
193
+ );
194
+ END IF;
195
+ END $grants$;
196
+
197
+ RESET statement_timeout;
198
+ RESET lock_timeout;
@@ -0,0 +1,38 @@
1
+ -- deployment-mode: rolling
2
+ -- Rebased after the current main migration ledger.
3
+ -- Link one terminal delegation result/error to the accepted ordinary turn.
4
+
5
+ SET lock_timeout = '5s';
6
+ SET statement_timeout = '10min';
7
+
8
+ ALTER TABLE "session_realtime_entries"
9
+ DROP CONSTRAINT "session_realtime_entries_turn_check";
10
+
11
+ ALTER TABLE "session_realtime_entries"
12
+ ADD CONSTRAINT "session_realtime_entries_turn_check"
13
+ CHECK (
14
+ "turn_id" IS NULL
15
+ OR ("kind" = 'delegation_call' AND "direction" = 'provider_in')
16
+ OR ("kind" IN ('delegation_result', 'error') AND "direction" = 'provider_out')
17
+ );
18
+
19
+ DROP INDEX "session_realtime_entries_delegation_turn_uq";
20
+
21
+ CREATE UNIQUE INDEX "session_realtime_entries_delegation_turn_uq"
22
+ ON "session_realtime_entries" ("turn_id")
23
+ WHERE "kind" = 'delegation_call' AND "turn_id" IS NOT NULL;
24
+
25
+ CREATE UNIQUE INDEX "session_realtime_entries_delegation_terminal_uq"
26
+ ON "session_realtime_entries" ("turn_id")
27
+ WHERE "direction" = 'provider_out'
28
+ AND "kind" IN ('delegation_result', 'error')
29
+ AND "turn_id" IS NOT NULL;
30
+
31
+ DROP INDEX "session_realtime_entries_outbound_pending_idx";
32
+
33
+ CREATE INDEX "session_realtime_entries_outbound_pending_idx"
34
+ ON "session_realtime_entries" ("realtime_id", "sequence")
35
+ WHERE "direction" = 'provider_out' AND "provider_acked_at" IS NULL;
36
+
37
+ RESET statement_timeout;
38
+ RESET lock_timeout;
@@ -0,0 +1,82 @@
1
+ -- deployment-mode: rolling
2
+ -- Rebased after the current main migration ledger.
3
+ -- Exactly-once audit/idempotency projection for the canonical transcript-tail Steer turn.
4
+
5
+ SET lock_timeout = '5s';
6
+ SET statement_timeout = '10min';
7
+
8
+ CREATE TABLE "session_realtime_context_projections" (
9
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
10
+ "account_id" uuid NOT NULL,
11
+ "workspace_id" uuid NOT NULL,
12
+ "session_id" uuid NOT NULL,
13
+ "turn_id" uuid NOT NULL,
14
+ "context" text,
15
+ "source_mode_count" integer NOT NULL,
16
+ "source_entry_count" integer NOT NULL,
17
+ "included_entry_count" integer NOT NULL,
18
+ "omitted_entry_count" integer NOT NULL,
19
+ "created_at" timestamptz DEFAULT now() NOT NULL,
20
+ CONSTRAINT "session_realtime_context_projections_workspace_account_fk"
21
+ FOREIGN KEY ("workspace_id", "account_id")
22
+ REFERENCES "workspaces" ("id", "account_id") ON DELETE CASCADE,
23
+ CONSTRAINT "session_realtime_context_projections_workspace_session_fk"
24
+ FOREIGN KEY ("workspace_id", "session_id")
25
+ REFERENCES "sessions" ("workspace_id", "id") ON DELETE CASCADE,
26
+ CONSTRAINT "session_realtime_context_projections_workspace_turn_fk"
27
+ FOREIGN KEY ("workspace_id", "turn_id")
28
+ REFERENCES "session_turns" ("workspace_id", "id") ON DELETE CASCADE,
29
+ CONSTRAINT "session_realtime_context_projections_context_check"
30
+ CHECK ("context" IS NULL OR octet_length("context") BETWEEN 1 AND 65536),
31
+ CONSTRAINT "session_realtime_context_projections_counts_check"
32
+ CHECK (
33
+ "source_mode_count" >= 1
34
+ AND "source_entry_count" >= 0
35
+ AND "included_entry_count" >= 0
36
+ AND "omitted_entry_count" >= 0
37
+ AND "included_entry_count" + "omitted_entry_count" = "source_entry_count"
38
+ AND (("source_entry_count" = 0 AND "context" IS NULL)
39
+ OR ("source_entry_count" > 0 AND "context" IS NOT NULL))
40
+ )
41
+ );
42
+
43
+ CREATE UNIQUE INDEX "session_realtime_context_projections_turn_uq"
44
+ ON "session_realtime_context_projections" ("workspace_id", "session_id", "turn_id");
45
+
46
+ ALTER TABLE "session_realtime_context_projections" ENABLE ROW LEVEL SECURITY;
47
+ ALTER TABLE "session_realtime_context_projections" FORCE ROW LEVEL SECURITY;
48
+
49
+ CREATE POLICY workspace_isolation ON "session_realtime_context_projections"
50
+ USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
51
+ WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
52
+
53
+ ALTER TABLE "session_realtime_modes"
54
+ ADD COLUMN "context_projection_id" uuid,
55
+ ADD COLUMN "context_projected_at" timestamptz,
56
+ ADD CONSTRAINT "session_realtime_modes_context_projection_fk"
57
+ FOREIGN KEY ("context_projection_id")
58
+ REFERENCES "session_realtime_context_projections" ("id") ON DELETE RESTRICT,
59
+ ADD CONSTRAINT "session_realtime_modes_context_projection_check"
60
+ CHECK (
61
+ ("context_projection_id" IS NULL AND "context_projected_at" IS NULL)
62
+ OR
63
+ ("context_projection_id" IS NOT NULL AND "context_projected_at" IS NOT NULL AND "state" = 'ended')
64
+ );
65
+
66
+ CREATE INDEX "session_realtime_modes_pending_context_idx"
67
+ ON "session_realtime_modes" ("workspace_id", "session_id", "ended_at", "id")
68
+ WHERE "state" = 'ended' AND "context_projection_id" IS NULL;
69
+
70
+ DO $grants$
71
+ DECLARE target_schema text := current_schema();
72
+ BEGIN
73
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
74
+ EXECUTE format(
75
+ 'GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE %I.session_realtime_context_projections TO opengeni_app',
76
+ target_schema
77
+ );
78
+ END IF;
79
+ END $grants$;
80
+
81
+ RESET statement_timeout;
82
+ RESET lock_timeout;
@@ -0,0 +1,53 @@
1
+ -- deployment-mode: rolling
2
+ -- Rebased after the current main migration ledger.
3
+ -- Stage one replacement beside the active GPT-Live connection until the browser
4
+ -- proves its data channel is ready, then promote it transactionally.
5
+
6
+ SET lock_timeout = '5s';
7
+ SET statement_timeout = '10min';
8
+
9
+ ALTER TABLE "session_realtime_connections"
10
+ ADD COLUMN "promotion_mode" text DEFAULT 'legacy' NOT NULL,
11
+ ADD CONSTRAINT "session_realtime_connections_promotion_mode_check"
12
+ CHECK ("promotion_mode" IN ('legacy', 'staged'));
13
+
14
+ CREATE UNIQUE INDEX "session_realtime_connections_one_active_uq"
15
+ ON "session_realtime_connections" ("realtime_id")
16
+ WHERE (
17
+ ("promotion_mode" = 'legacy' AND "state" IN ('negotiating', 'ready', 'active'))
18
+ OR
19
+ ("promotion_mode" = 'staged' AND "state" = 'active')
20
+ );
21
+
22
+ CREATE UNIQUE INDEX "session_realtime_connections_one_preparing_uq"
23
+ ON "session_realtime_connections" ("realtime_id")
24
+ WHERE (
25
+ ("promotion_mode" = 'legacy' AND "state" IN ('negotiating', 'ready', 'active'))
26
+ OR
27
+ ("promotion_mode" = 'staged' AND "state" IN ('negotiating', 'ready'))
28
+ );
29
+
30
+ ALTER TABLE "session_realtime_connections"
31
+ DROP CONSTRAINT "session_realtime_connections_state_check",
32
+ ADD CONSTRAINT "session_realtime_connections_state_check"
33
+ CHECK ("state" IN ('negotiating', 'ready', 'active', 'failed', 'closed'));
34
+
35
+ ALTER TABLE "session_realtime_connections"
36
+ DROP CONSTRAINT "session_realtime_connections_terminal_check",
37
+ ADD CONSTRAINT "session_realtime_connections_terminal_check"
38
+ CHECK (
39
+ ("state" = 'negotiating' AND "sdp_answer" IS NULL AND "failure_code" IS NULL AND "negotiated_at" IS NULL AND "closed_at" IS NULL)
40
+ OR
41
+ ("state" = 'ready' AND "sdp_answer" IS NOT NULL AND "failure_code" IS NULL AND "negotiated_at" IS NOT NULL AND "closed_at" IS NULL)
42
+ OR
43
+ ("state" = 'active' AND "sdp_answer" IS NOT NULL AND "failure_code" IS NULL AND "negotiated_at" IS NOT NULL AND "closed_at" IS NULL)
44
+ OR
45
+ ("state" = 'failed' AND "sdp_answer" IS NULL AND "failure_code" IS NOT NULL AND "closed_at" IS NOT NULL)
46
+ OR
47
+ ("state" = 'closed' AND "closed_at" IS NOT NULL)
48
+ );
49
+
50
+ DROP INDEX "session_realtime_connections_one_open_uq";
51
+
52
+ RESET statement_timeout;
53
+ RESET lock_timeout;
@@ -0,0 +1,35 @@
1
+ -- deployment-mode: rolling
2
+ -- Stream durable ordinary-turn assistant deltas back to their active V3 delegation.
3
+
4
+ SET lock_timeout = '5s';
5
+ SET statement_timeout = '10min';
6
+
7
+ ALTER TABLE "session_realtime_entries"
8
+ DROP CONSTRAINT "session_realtime_entries_kind_check";
9
+
10
+ ALTER TABLE "session_realtime_entries"
11
+ ADD CONSTRAINT "session_realtime_entries_kind_check"
12
+ CHECK ("kind" IN (
13
+ 'user_transcript',
14
+ 'assistant_transcript',
15
+ 'delegation_call',
16
+ 'delegation_progress',
17
+ 'delegation_result',
18
+ 'interruption',
19
+ 'session_update',
20
+ 'error'
21
+ ));
22
+
23
+ ALTER TABLE "session_realtime_entries"
24
+ DROP CONSTRAINT "session_realtime_entries_turn_check";
25
+
26
+ ALTER TABLE "session_realtime_entries"
27
+ ADD CONSTRAINT "session_realtime_entries_turn_check"
28
+ CHECK (
29
+ "turn_id" IS NULL
30
+ OR ("kind" = 'delegation_call' AND "direction" = 'provider_in')
31
+ OR ("kind" IN ('delegation_progress', 'delegation_result', 'error') AND "direction" = 'provider_out')
32
+ );
33
+
34
+ RESET statement_timeout;
35
+ RESET lock_timeout;
@@ -0,0 +1,28 @@
1
+ -- deployment-mode: rolling
2
+ -- Add provider-qualified AI Gateway voice models without changing lifecycle semantics.
3
+
4
+ SET lock_timeout = '5s';
5
+ SET statement_timeout = '10min';
6
+
7
+ ALTER TABLE "session_realtime_modes"
8
+ DROP CONSTRAINT "session_realtime_modes_model_check";
9
+
10
+ ALTER TABLE "session_realtime_modes"
11
+ ADD CONSTRAINT "session_realtime_modes_model_check"
12
+ CHECK (
13
+ "model" IN (
14
+ 'gpt-live-1-boulder-alpha',
15
+ 'opengeni-gateway/openai/gpt-realtime-2.1',
16
+ 'opengeni-gateway/openai/gpt-realtime-mini',
17
+ 'opengeni-gateway/xai/grok-voice-think-fast-2.0',
18
+ 'workspace-gateway/openai/gpt-realtime-2.1',
19
+ 'workspace-gateway/openai/gpt-realtime-mini',
20
+ 'workspace-gateway/xai/grok-voice-think-fast-2.0'
21
+ )
22
+ ) NOT VALID;
23
+
24
+ ALTER TABLE "session_realtime_modes"
25
+ VALIDATE CONSTRAINT "session_realtime_modes_model_check";
26
+
27
+ RESET statement_timeout;
28
+ RESET lock_timeout;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/db",
3
- "version": "0.22.1",
3
+ "version": "0.23.0",
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.9",
54
- "@opengeni/config": "^0.10.0",
55
- "@opengeni/contracts": "^0.31.0",
53
+ "@opengeni/codex": "^0.2.10",
54
+ "@opengeni/config": "^0.10.3",
55
+ "@opengeni/contracts": "^0.32.0",
56
56
  "@opengeni/network": "^0.1.1",
57
57
  "drizzle-orm": "^0.45.2",
58
58
  "postgres": "^3.4.7"