@opengeni/db 0.6.1 → 0.7.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.
Files changed (53) hide show
  1. package/dist/{chunk-OGCE6O2X.js → chunk-7LDU7F5P.js} +31 -3
  2. package/dist/chunk-7LDU7F5P.js.map +1 -0
  3. package/dist/chunk-B22X3IEZ.js +2634 -0
  4. package/dist/chunk-B22X3IEZ.js.map +1 -0
  5. package/dist/{chunk-57MLICFR.js → chunk-YFQ7SGE4.js} +18 -6
  6. package/dist/chunk-YFQ7SGE4.js.map +1 -0
  7. package/dist/index.d.ts +2 -2
  8. package/dist/index.js +16571 -5018
  9. package/dist/index.js.map +1 -1
  10. package/dist/migrate.js +1 -1
  11. package/dist/provision-roles.d.ts +2121 -248
  12. package/dist/provision-roles.js +1 -1
  13. package/dist/{schema-BUbuMteO.d.ts → schema-BN5mB9xZ.d.ts} +8716 -3432
  14. package/dist/schema.d.ts +1 -1
  15. package/dist/schema.js +43 -5
  16. package/drizzle/0044_reap_dead_turn_holders.sql +104 -0
  17. package/drizzle/0045_workspace_captures.sql +83 -0
  18. package/drizzle/0045_workspace_memory_v1.sql +71 -0
  19. package/drizzle/0046_variable_sets_rename.sql +56 -0
  20. package/drizzle/0047_rigs.sql +151 -0
  21. package/drizzle/0048_rig_runtime.sql +9 -0
  22. package/drizzle/0049_enrollment_went_offline.sql +28 -0
  23. package/drizzle/0050_enrollment_op_stream.sql +1 -0
  24. package/drizzle/0051_codex_pin_source.sql +48 -0
  25. package/drizzle/0052_file_upload_cleanup.sql +91 -0
  26. package/drizzle/0053_codex_credential_leases.sql +230 -0
  27. package/drizzle/0054_session_pins.sql +85 -0
  28. package/drizzle/0055_session_list_snapshots.sql +73 -0
  29. package/drizzle/0056_workspace_model_policies.sql +48 -0
  30. package/drizzle/0057_durable_queue_control.sql +536 -0
  31. package/drizzle/0058_turn_admission_usage_enrollment.sql +158 -0
  32. package/drizzle/0059_workspace_pause_control_kind.sql +12 -0
  33. package/drizzle/0060_session_system_update_deferral.sql +10 -0
  34. package/drizzle/0061_session_workflow_wake_outbox.sql +157 -0
  35. package/drizzle/0062_session_list_snapshot_reaper.sql +48 -0
  36. package/drizzle/0063_session_control_mega_foundation.sql +1324 -0
  37. package/package.json +13 -13
  38. package/src/codex-token-resolver.ts +58 -23
  39. package/src/connection-token-resolver.ts +146 -57
  40. package/src/environment-crypto.ts +5 -1
  41. package/src/event-payload-sanitizer.ts +29 -1
  42. package/src/index.ts +20990 -6465
  43. package/src/memory-domain.ts +218 -0
  44. package/src/migrate.ts +58 -3
  45. package/src/provision-roles.ts +46 -17
  46. package/src/schema.ts +2888 -1121
  47. package/src/session-control.ts +1759 -0
  48. package/src/session-queue-commands.ts +1753 -0
  49. package/src/session-tool-call-settlement.ts +269 -0
  50. package/dist/chunk-57MLICFR.js.map +0 -1
  51. package/dist/chunk-OGCE6O2X.js.map +0 -1
  52. package/dist/chunk-ZIUCA2IO.js +0 -1268
  53. package/dist/chunk-ZIUCA2IO.js.map +0 -1
@@ -0,0 +1,158 @@
1
+ -- One-way production remediation after the 0057 session-control cutover.
2
+ --
3
+ -- 1. Provider response usage has exactly one authoritative current event. SDK
4
+ -- wrapper duplicates stay in the audit log with an explicit association.
5
+ -- 2. Workflow repair enrolls every durable state that needs a session workflow,
6
+ -- including approval/capacity waits and pending control settlement.
7
+
8
+ ALTER TABLE "session_events"
9
+ DROP CONSTRAINT "session_events_turn_association_check";
10
+
11
+ ALTER TABLE "session_events"
12
+ ADD COLUMN "duplicate_of_event_id" uuid,
13
+ ADD COLUMN "duplicate_reason" text;
14
+
15
+ ALTER TABLE "session_events"
16
+ ADD CONSTRAINT "session_events_duplicate_of_event_fk"
17
+ FOREIGN KEY ("duplicate_of_event_id")
18
+ REFERENCES "session_events"("id") ON DELETE RESTRICT;
19
+
20
+ ALTER TABLE "session_events"
21
+ ADD CONSTRAINT "session_events_turn_association_check"
22
+ CHECK (
23
+ "turn_association" IS NULL
24
+ OR "turn_association" IN ('current', 'late_rejected', 'duplicate')
25
+ );
26
+
27
+ -- Keep the earliest event as the authoritative observation. Every later event
28
+ -- for the same turn/provider-response source remains queryable and points to
29
+ -- that canonical row; nothing is deleted or disguised as a late attempt write.
30
+ WITH ranked AS (
31
+ SELECT
32
+ e."id",
33
+ first_value(e."id") OVER (
34
+ PARTITION BY
35
+ e."workspace_id",
36
+ e."session_id",
37
+ e."turn_id",
38
+ e."payload" ->> 'sourceKey'
39
+ ORDER BY e."sequence", e."id"
40
+ ) AS "canonical_id",
41
+ row_number() OVER (
42
+ PARTITION BY
43
+ e."workspace_id",
44
+ e."session_id",
45
+ e."turn_id",
46
+ e."payload" ->> 'sourceKey'
47
+ ORDER BY e."sequence", e."id"
48
+ ) AS "ordinal"
49
+ FROM "session_events" e
50
+ WHERE e."type" = 'agent.model.usage'
51
+ AND e."turn_association" = 'current'
52
+ AND e."turn_id" IS NOT NULL
53
+ AND nullif(e."payload" ->> 'sourceKey', '') IS NOT NULL
54
+ )
55
+ UPDATE "session_events" e
56
+ SET "turn_association" = 'duplicate',
57
+ "duplicate_of_event_id" = ranked."canonical_id",
58
+ "duplicate_reason" = 'duplicate_provider_response_usage'
59
+ FROM ranked
60
+ WHERE e."id" = ranked."id"
61
+ AND ranked."ordinal" > 1;
62
+
63
+ ALTER TABLE "session_events"
64
+ ADD CONSTRAINT "session_events_duplicate_classification_check"
65
+ CHECK (
66
+ (
67
+ "turn_association" = 'duplicate'
68
+ AND "type" = 'agent.model.usage'
69
+ AND "duplicate_of_event_id" IS NOT NULL
70
+ AND "duplicate_of_event_id" <> "id"
71
+ AND nullif("duplicate_reason", '') IS NOT NULL
72
+ )
73
+ OR (
74
+ "turn_association" IS DISTINCT FROM 'duplicate'
75
+ AND "duplicate_of_event_id" IS NULL
76
+ AND "duplicate_reason" IS NULL
77
+ )
78
+ );
79
+
80
+ CREATE UNIQUE INDEX "session_events_current_model_usage_source_uq"
81
+ ON "session_events" (
82
+ "workspace_id",
83
+ "session_id",
84
+ "turn_id",
85
+ (("payload" ->> 'sourceKey'))
86
+ )
87
+ WHERE "type" = 'agent.model.usage'
88
+ AND "turn_association" = 'current'
89
+ AND "turn_id" IS NOT NULL
90
+ AND nullif("payload" ->> 'sourceKey', '') IS NOT NULL;
91
+
92
+ -- The old name described database claimability, not the actual operational
93
+ -- contract. A workflow must also be enrolled while it waits for approval or
94
+ -- capacity, and any pending Pause/Steer control needs a workflow to settle it.
95
+ DROP FUNCTION opengeni_private.list_claimable_sessions(integer);
96
+
97
+ CREATE FUNCTION opengeni_private.list_enrollable_sessions(p_limit integer)
98
+ RETURNS TABLE (
99
+ account_id uuid,
100
+ workspace_id uuid,
101
+ session_id uuid,
102
+ temporal_workflow_id text
103
+ )
104
+ LANGUAGE sql
105
+ SECURITY DEFINER
106
+ AS $$
107
+ SELECT DISTINCT
108
+ s.account_id,
109
+ s.workspace_id,
110
+ s.id,
111
+ coalesce(s.temporal_workflow_id, 'session-' || s.id::text)
112
+ FROM sessions s
113
+ JOIN workspaces w ON w.id = s.workspace_id
114
+ WHERE
115
+ -- Controls are durable intent. Even a closed inference gate must enroll a
116
+ -- workflow long enough to settle the pending Pause/Steer fence.
117
+ s.pending_control_event_id IS NOT NULL
118
+ OR (
119
+ s.control_state = 'active'
120
+ AND (
121
+ w.inference_state = 'active'
122
+ OR s.workspace_run_exception_generation = w.inference_generation
123
+ )
124
+ AND (
125
+ EXISTS (
126
+ SELECT 1 FROM session_turns t
127
+ WHERE t.workspace_id = s.workspace_id
128
+ AND t.session_id = s.id
129
+ AND t.status IN ('queued', 'recovering', 'waiting_capacity', 'requires_action')
130
+ )
131
+ OR EXISTS (
132
+ SELECT 1 FROM session_system_updates u
133
+ WHERE u.workspace_id = s.workspace_id
134
+ AND u.session_id = s.id
135
+ AND u.state = 'pending'
136
+ )
137
+ OR EXISTS (
138
+ SELECT 1 FROM session_goals g
139
+ WHERE g.workspace_id = s.workspace_id
140
+ AND g.session_id = s.id
141
+ AND g.status = 'active'
142
+ )
143
+ )
144
+ )
145
+ ORDER BY s.id
146
+ LIMIT greatest(1, least(coalesce(p_limit, 1000), 10000));
147
+ $$;
148
+
149
+ REVOKE ALL ON FUNCTION opengeni_private.list_enrollable_sessions(integer) FROM PUBLIC;
150
+
151
+ DO $$
152
+ DECLARE target_schema text := current_schema();
153
+ BEGIN
154
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
155
+ GRANT EXECUTE ON FUNCTION opengeni_private.list_enrollable_sessions(integer)
156
+ TO opengeni_app;
157
+ END IF;
158
+ END $$;
@@ -0,0 +1,12 @@
1
+ -- Workspace Pause is a first-class durable control kind. The 0057 constraint
2
+ -- predates that control path and must match the canonical runtime state machine.
3
+
4
+ ALTER TABLE "sessions"
5
+ DROP CONSTRAINT "sessions_pending_control_kind_check";
6
+
7
+ ALTER TABLE "sessions"
8
+ ADD CONSTRAINT "sessions_pending_control_kind_check"
9
+ CHECK (
10
+ "pending_control_kind" IS NULL
11
+ OR "pending_control_kind" IN ('pause', 'workspace_pause', 'steer')
12
+ );
@@ -0,0 +1,10 @@
1
+ -- A failed internal-only inference preserves ordinary internal updates without
2
+ -- making them independently runnable again. They become eligible when a real
3
+ -- prompt or a genuinely new pending internal update starts the next inference.
4
+
5
+ ALTER TABLE "session_system_updates"
6
+ DROP CONSTRAINT "system_updates_state_check";
7
+
8
+ ALTER TABLE "session_system_updates"
9
+ ADD CONSTRAINT "system_updates_state_check"
10
+ CHECK ("state" IN ('pending', 'deferred', 'delivered', 'cancelled', 'failed'));
@@ -0,0 +1,157 @@
1
+ -- OPE-50: replace the blind periodic scan of "enrollable" sessions with a
2
+ -- transactional, revisioned, coalescing delivery ledger. Postgres is the
3
+ -- durable work source; a Temporal signal is an idempotent nudge.
4
+
5
+ CREATE TABLE "session_workflow_wake_outbox" (
6
+ "session_id" uuid PRIMARY KEY,
7
+ "account_id" uuid NOT NULL,
8
+ "workspace_id" uuid NOT NULL,
9
+ "temporal_workflow_id" text NOT NULL,
10
+ "wake_revision" bigint NOT NULL DEFAULT 1,
11
+ "delivered_revision" bigint NOT NULL DEFAULT 0,
12
+ "reason" text NOT NULL,
13
+ "attempts" integer NOT NULL DEFAULT 0,
14
+ "next_attempt_at" timestamptz NOT NULL DEFAULT now(),
15
+ "last_error" text,
16
+ "created_at" timestamptz NOT NULL DEFAULT now(),
17
+ "updated_at" timestamptz NOT NULL DEFAULT now(),
18
+ CONSTRAINT "session_workflow_wake_outbox_revision_check"
19
+ CHECK ("wake_revision" > 0 AND "delivered_revision" >= 0
20
+ AND "delivered_revision" <= "wake_revision"),
21
+ CONSTRAINT "session_workflow_wake_outbox_workspace_account_fk"
22
+ FOREIGN KEY ("workspace_id", "account_id")
23
+ REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
24
+ CONSTRAINT "session_workflow_wake_outbox_workspace_session_fk"
25
+ FOREIGN KEY ("workspace_id", "session_id")
26
+ REFERENCES "sessions"("workspace_id", "id") ON DELETE CASCADE
27
+ );
28
+
29
+ CREATE UNIQUE INDEX "session_workflow_wake_outbox_workspace_session_uq"
30
+ ON "session_workflow_wake_outbox" ("workspace_id", "session_id");
31
+ CREATE INDEX "session_workflow_wake_outbox_pending_idx"
32
+ ON "session_workflow_wake_outbox" ("next_attempt_at", "updated_at", "session_id")
33
+ WHERE "wake_revision" > "delivered_revision";
34
+
35
+ ALTER TABLE "session_workflow_wake_outbox" ENABLE ROW LEVEL SECURITY;
36
+ ALTER TABLE "session_workflow_wake_outbox" FORCE ROW LEVEL SECURITY;
37
+ CREATE POLICY workspace_isolation ON "session_workflow_wake_outbox"
38
+ USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
39
+ WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
40
+
41
+ -- Workspace control retries now persist the exact control deliveries they own.
42
+ -- Canonicalize pre-cutover receipts once so runtime code has one result shape;
43
+ -- any still-pending historical control is independently seeded below.
44
+ UPDATE "runtime_control_operations"
45
+ SET "result" = jsonb_set("result", '{controls}', '[]'::jsonb, true)
46
+ WHERE "scope" = 'workspace'
47
+ AND jsonb_typeof("result") = 'object'
48
+ AND NOT ("result" ? 'controls');
49
+
50
+ -- Claim only committed revisions that still need delivery. The due timestamp
51
+ -- is advanced before delivery, so a process death becomes retryable after the
52
+ -- bounded backoff. Acknowledgements are revision-scoped: an old delivery can
53
+ -- never hide a newer committed wake.
54
+ DO $migration$
55
+ DECLARE target_schema text := current_schema();
56
+ BEGIN
57
+ EXECUTE format($create$
58
+ CREATE FUNCTION opengeni_private.claim_session_workflow_wakes(p_limit integer)
59
+ RETURNS TABLE (
60
+ account_id uuid,
61
+ workspace_id uuid,
62
+ session_id uuid,
63
+ temporal_workflow_id text,
64
+ wake_revision bigint,
65
+ control_event_id uuid
66
+ )
67
+ LANGUAGE plpgsql
68
+ SECURITY DEFINER
69
+ SET search_path = pg_catalog
70
+ AS $function$
71
+ BEGIN
72
+ RETURN QUERY
73
+ WITH due AS (
74
+ SELECT o.session_id
75
+ FROM %1$I.session_workflow_wake_outbox o
76
+ WHERE o.wake_revision > o.delivered_revision
77
+ AND o.next_attempt_at <= now()
78
+ ORDER BY o.next_attempt_at, o.updated_at, o.session_id
79
+ FOR UPDATE SKIP LOCKED
80
+ LIMIT greatest(1, least(coalesce(p_limit, 100), 1000))
81
+ )
82
+ UPDATE %1$I.session_workflow_wake_outbox o
83
+ SET attempts = o.attempts + 1,
84
+ next_attempt_at = now() + make_interval(
85
+ secs => least(300, greatest(1, power(2, least(o.attempts, 8))::integer))
86
+ ),
87
+ updated_at = now()
88
+ FROM due
89
+ WHERE o.session_id = due.session_id
90
+ RETURNING o.account_id, o.workspace_id, o.session_id,
91
+ o.temporal_workflow_id, o.wake_revision,
92
+ (SELECT s.pending_control_event_id FROM %1$I.sessions s WHERE s.id = o.session_id)
93
+ AS control_event_id;
94
+ END $function$;
95
+ $create$, target_schema);
96
+ END $migration$;
97
+ REVOKE ALL ON FUNCTION opengeni_private.claim_session_workflow_wakes(integer) FROM PUBLIC;
98
+
99
+ -- One-time cutover seed. This is intentionally the final use of an eligibility
100
+ -- scan: it converts already-committed pre-outbox work into explicit revisions.
101
+ -- Runtime repair after this migration reads only the outbox.
102
+ INSERT INTO "session_workflow_wake_outbox" (
103
+ "session_id", "account_id", "workspace_id", "temporal_workflow_id", "reason"
104
+ )
105
+ SELECT DISTINCT
106
+ s."id",
107
+ s."account_id",
108
+ s."workspace_id",
109
+ coalesce(s."temporal_workflow_id", 'session-' || s."id"::text),
110
+ 'cutover_seed'
111
+ FROM "sessions" s
112
+ JOIN "workspaces" w ON w."id" = s."workspace_id"
113
+ WHERE
114
+ s."pending_control_event_id" IS NOT NULL
115
+ OR (
116
+ s."control_state" = 'active'
117
+ AND (
118
+ w."inference_state" = 'active'
119
+ OR s."workspace_run_exception_generation" = w."inference_generation"
120
+ )
121
+ AND (
122
+ EXISTS (
123
+ SELECT 1 FROM "session_turns" t
124
+ WHERE t."workspace_id" = s."workspace_id"
125
+ AND t."session_id" = s."id"
126
+ AND t."status" IN ('queued', 'recovering', 'waiting_capacity', 'requires_action')
127
+ )
128
+ OR EXISTS (
129
+ SELECT 1 FROM "session_system_updates" u
130
+ WHERE u."workspace_id" = s."workspace_id"
131
+ AND u."session_id" = s."id"
132
+ AND u."state" = 'pending'
133
+ )
134
+ OR EXISTS (
135
+ SELECT 1 FROM "session_goals" g
136
+ WHERE g."workspace_id" = s."workspace_id"
137
+ AND g."session_id" = s."id"
138
+ AND g."status" = 'active'
139
+ )
140
+ OR s."compact_requested" = true
141
+ )
142
+ );
143
+
144
+ DROP FUNCTION opengeni_private.list_enrollable_sessions(integer);
145
+
146
+ DO $$
147
+ DECLARE target_schema text := current_schema();
148
+ BEGIN
149
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
150
+ EXECUTE format(
151
+ 'GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE %I.session_workflow_wake_outbox TO opengeni_app',
152
+ target_schema
153
+ );
154
+ GRANT EXECUTE ON FUNCTION opengeni_private.claim_session_workflow_wakes(integer)
155
+ TO opengeni_app;
156
+ END IF;
157
+ END $$;
@@ -0,0 +1,48 @@
1
+ -- OPE-44: session list reads are serializable and subject-scoped. Performing a
2
+ -- global expired-row delete inside every read makes concurrent API replicas
3
+ -- conflict on the same rows. Move TTL cleanup to one bounded SKIP LOCKED
4
+ -- reaper operation and keep the request transaction strictly request-local.
5
+
6
+ CREATE INDEX "session_list_snapshots_expiry_reaper_idx"
7
+ ON "session_list_snapshots" ("expires_at", "id");
8
+
9
+ DO $migration$
10
+ DECLARE target_schema text := current_schema();
11
+ BEGIN
12
+ EXECUTE format($create$
13
+ CREATE FUNCTION opengeni_private.reap_expired_session_list_snapshots(p_limit integer)
14
+ RETURNS integer
15
+ LANGUAGE plpgsql
16
+ SECURITY DEFINER
17
+ SET search_path = pg_catalog
18
+ AS $function$
19
+ DECLARE deleted_count integer;
20
+ BEGIN
21
+ WITH victims AS (
22
+ SELECT s.id
23
+ FROM %1$I.session_list_snapshots s
24
+ WHERE s.expires_at < now()
25
+ ORDER BY s.expires_at, s.id
26
+ FOR UPDATE SKIP LOCKED
27
+ LIMIT greatest(1, least(coalesce(p_limit, 500), 5000))
28
+ ), deleted AS (
29
+ DELETE FROM %1$I.session_list_snapshots s
30
+ USING victims
31
+ WHERE s.id = victims.id
32
+ RETURNING s.id
33
+ )
34
+ SELECT count(*)::integer INTO deleted_count FROM deleted;
35
+ RETURN deleted_count;
36
+ END $function$;
37
+ $create$, target_schema);
38
+ END $migration$;
39
+
40
+ REVOKE ALL ON FUNCTION opengeni_private.reap_expired_session_list_snapshots(integer) FROM PUBLIC;
41
+
42
+ DO $$
43
+ BEGIN
44
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
45
+ GRANT EXECUTE ON FUNCTION opengeni_private.reap_expired_session_list_snapshots(integer)
46
+ TO opengeni_app;
47
+ END IF;
48
+ END $$;