@opengeni/db 1.3.0 → 1.4.2

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 (91) hide show
  1. package/dist/canonical-human-identities.js +3 -3
  2. package/dist/capability-reconciliation.js +2 -2
  3. package/dist/{chunk-7QWWTVYH.js → chunk-5ROHLEN6.js} +29 -4
  4. package/dist/chunk-5ROHLEN6.js.map +1 -0
  5. package/dist/{chunk-AQMH2ZEH.js → chunk-A4J7EECR.js} +2 -2
  6. package/dist/{chunk-VQX54TK3.js → chunk-B5C5SBSI.js} +3 -3
  7. package/dist/{chunk-OI6YZXTU.js → chunk-DKFEUGM4.js} +2 -2
  8. package/dist/{chunk-HYBQABBJ.js → chunk-HUKBIZGH.js} +2 -2
  9. package/dist/{chunk-LRSIODCQ.js → chunk-IT3EYY2C.js} +6 -4
  10. package/dist/{chunk-LRSIODCQ.js.map → chunk-IT3EYY2C.js.map} +1 -1
  11. package/dist/{chunk-DSNEIW5E.js → chunk-JL6TBB76.js} +2 -1
  12. package/dist/chunk-JL6TBB76.js.map +1 -0
  13. package/dist/{chunk-OEFNTGR3.js → chunk-JWBEE4CL.js} +4 -4
  14. package/dist/{chunk-BRVBLQAL.js → chunk-K5MTNKJU.js} +4 -4
  15. package/dist/{chunk-6UKNJ43T.js → chunk-NZ2SP55O.js} +2 -2
  16. package/dist/{chunk-3XHC5KC5.js → chunk-OKCBARX6.js} +2 -2
  17. package/dist/{chunk-PNWWNEDM.js → chunk-OV5AUIBA.js} +2 -2
  18. package/dist/{chunk-BID3CNN3.js → chunk-TODVDGMO.js} +36 -18
  19. package/dist/{chunk-BID3CNN3.js.map → chunk-TODVDGMO.js.map} +1 -1
  20. package/dist/{chunk-6S5T6FSP.js → chunk-W75DRYG3.js} +5 -5
  21. package/dist/{chunk-7S3O33NM.js → chunk-Y72DP3JF.js} +2 -2
  22. package/dist/codemode-approvals.d.ts +7 -1
  23. package/dist/connect-attempts.js +3 -3
  24. package/dist/connection-metadata.d.ts +416 -0
  25. package/dist/credit-balances.d.ts +25 -4
  26. package/dist/database.d.ts +7 -1
  27. package/dist/editable-artifact-durable-export.js +2 -2
  28. package/dist/editable-artifacts.js +3 -3
  29. package/dist/index.d.ts +51 -8
  30. package/dist/index.js +10826 -10129
  31. package/dist/index.js.map +1 -1
  32. package/dist/legacy-tool-action-reviews.d.ts +75 -0
  33. package/dist/managed-auth-session-sets.js +3 -3
  34. package/dist/mcp-operations.js +2 -2
  35. package/dist/modal-native-live-origin.d.ts +75 -0
  36. package/dist/organization-integration-policy.js +3 -3
  37. package/dist/organization-slack-bots.d.ts +1 -1
  38. package/dist/provision-roles.js +1 -1
  39. package/dist/retained-provider-commands.d.ts +21 -21
  40. package/dist/retained-provider-commands.js +6 -6
  41. package/dist/runtime-posture.d.ts +1 -1
  42. package/dist/sandbox-interaction-idle.d.ts +22 -0
  43. package/dist/schema.js +1 -1
  44. package/dist/session-background-commands.js +4 -4
  45. package/dist/session-command-output.js +5 -5
  46. package/dist/session-event-slices.js +3 -3
  47. package/dist/session-mcp-credential-rotation.js +5 -5
  48. package/dist/session-realtime-billing.d.ts +48 -0
  49. package/dist/session-realtime.d.ts +8 -2
  50. package/dist/session-tenancy.js +3 -3
  51. package/dist/video-generation.js +3 -3
  52. package/dist/voice-transcription-settlement.d.ts +36 -0
  53. package/dist/workspace-tool-defaults.js +4 -4
  54. package/drizzle/0623_voice_transcription_attribution.sql +128 -0
  55. package/drizzle/0624_azure_live_realtime_model.sql +30 -0
  56. package/drizzle/0625_transcription_billing_refusal_codes.sql +29 -0
  57. package/drizzle/0632_modal_native_live_origin.sql +239 -0
  58. package/package.json +7 -7
  59. package/src/codemode-approvals.ts +52 -22
  60. package/src/codemode-operations.ts +198 -181
  61. package/src/connection-metadata.ts +166 -0
  62. package/src/credit-balances.ts +58 -17
  63. package/src/database.ts +9 -0
  64. package/src/index.ts +540 -412
  65. package/src/insights-unified.ts +2 -1
  66. package/src/legacy-tool-action-reviews.ts +242 -0
  67. package/src/modal-native-live-origin.ts +148 -0
  68. package/src/organization-slack-bots.ts +1 -1
  69. package/src/provision-roles.ts +12 -0
  70. package/src/runtime-posture.ts +32 -3
  71. package/src/sandbox-interaction-idle.ts +91 -0
  72. package/src/schema.ts +1 -0
  73. package/src/session-realtime-billing.ts +135 -0
  74. package/src/session-realtime-ledger.ts +9 -4
  75. package/src/session-realtime.ts +20 -2
  76. package/src/tool-action-reviews.ts +129 -18
  77. package/src/transcription-recordings.ts +3 -1
  78. package/src/voice-transcription-settlement.ts +94 -0
  79. package/dist/chunk-7QWWTVYH.js.map +0 -1
  80. package/dist/chunk-DSNEIW5E.js.map +0 -1
  81. /package/dist/{chunk-AQMH2ZEH.js.map → chunk-A4J7EECR.js.map} +0 -0
  82. /package/dist/{chunk-VQX54TK3.js.map → chunk-B5C5SBSI.js.map} +0 -0
  83. /package/dist/{chunk-OI6YZXTU.js.map → chunk-DKFEUGM4.js.map} +0 -0
  84. /package/dist/{chunk-HYBQABBJ.js.map → chunk-HUKBIZGH.js.map} +0 -0
  85. /package/dist/{chunk-OEFNTGR3.js.map → chunk-JWBEE4CL.js.map} +0 -0
  86. /package/dist/{chunk-BRVBLQAL.js.map → chunk-K5MTNKJU.js.map} +0 -0
  87. /package/dist/{chunk-6UKNJ43T.js.map → chunk-NZ2SP55O.js.map} +0 -0
  88. /package/dist/{chunk-3XHC5KC5.js.map → chunk-OKCBARX6.js.map} +0 -0
  89. /package/dist/{chunk-PNWWNEDM.js.map → chunk-OV5AUIBA.js.map} +0 -0
  90. /package/dist/{chunk-6S5T6FSP.js.map → chunk-W75DRYG3.js.map} +0 -0
  91. /package/dist/{chunk-7S3O33NM.js.map → chunk-Y72DP3JF.js.map} +0 -0
@@ -0,0 +1,128 @@
1
+ -- deployment-mode: rolling
2
+ -- Retain exact transcription payer receipts for member allowance attribution.
3
+ -- The API freezes the authenticated payer; ledger metadata alone is not proof.
4
+ DO $constraints$
5
+ DECLARE item record;
6
+ BEGIN
7
+ FOR item IN SELECT conname, pg_get_constraintdef(oid) AS definition FROM pg_constraint
8
+ WHERE conrelid='opengeni_private.usage_allowance_attribution_receipts'::regclass AND contype='c'
9
+ LOOP
10
+ IF (item.definition LIKE '%source_kind%' AND item.definition LIKE '%knowledge_query%') THEN
11
+ EXECUTE format('ALTER TABLE opengeni_private.usage_allowance_attribution_receipts DROP CONSTRAINT %I',item.conname);
12
+ END IF;
13
+ END LOOP;
14
+ END $constraints$;
15
+ ALTER TABLE opengeni_private.usage_allowance_attribution_receipts
16
+ ADD CONSTRAINT usage_attribution_source_kind CHECK (source_kind IN ('turn','schedule','knowledge_query','voice_transcription')),
17
+ ADD CONSTRAINT usage_attribution_source_shape CHECK (coalesce(
18
+ (source_kind='knowledge_query' AND session_id IS NULL AND quantity IS NOT NULL
19
+ AND idempotency_key='knowledge.query_cost:'||source_id)
20
+ OR (source_kind='voice_transcription' AND session_id IS NULL AND quantity IS NOT NULL
21
+ AND idempotency_key='voice.transcription_cost:'||source_id)
22
+ OR (source_kind IN ('turn','schedule') AND quantity IS NULL AND idempotency_key IS NULL),false));
23
+
24
+ CREATE OR REPLACE FUNCTION capture_usage_allowance_attribution()
25
+ RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path FROM CURRENT AS $$
26
+ DECLARE
27
+ v_source_kind text; v_source_id text; v_session_id uuid; v_attribution jsonb;
28
+ v_quantity bigint; v_idempotency_key text; opened integer;
29
+ BEGIN
30
+ IF TG_TABLE_NAME='session_turns' THEN
31
+ IF TG_OP='UPDATE' AND (NEW.id IS DISTINCT FROM OLD.id
32
+ OR NEW.account_id IS DISTINCT FROM OLD.account_id OR NEW.workspace_id IS DISTINCT FROM OLD.workspace_id
33
+ OR NEW.session_id IS DISTINCT FROM OLD.session_id
34
+ OR NEW.initiating_human_subject_id IS DISTINCT FROM OLD.initiating_human_subject_id) THEN
35
+ RAISE EXCEPTION 'Allowance turn attribution is immutable' USING ERRCODE='23514';
36
+ END IF;
37
+ v_source_kind:='turn'; v_source_id:=NEW.id::text; v_session_id:=NEW.session_id;
38
+ v_attribution:=jsonb_build_object('kind','turn','turnId',NEW.id,
39
+ 'initiatingHumanSubjectId',NEW.initiating_human_subject_id);
40
+ ELSIF TG_TABLE_NAME='scheduled_task_runs' THEN
41
+ IF TG_OP='UPDATE' AND (NEW.id IS DISTINCT FROM OLD.id
42
+ OR NEW.account_id IS DISTINCT FROM OLD.account_id OR NEW.workspace_id IS DISTINCT FROM OLD.workspace_id
43
+ OR NEW.accepted_execution_snapshot->'causalHumanSubjectId' IS DISTINCT FROM
44
+ OLD.accepted_execution_snapshot->'causalHumanSubjectId') THEN
45
+ RAISE EXCEPTION 'Allowance scheduled attribution is immutable' USING ERRCODE='23514';
46
+ END IF;
47
+ v_source_kind:='schedule'; v_source_id:=NEW.id::text;
48
+ v_attribution:=CASE WHEN NOT coalesce(NEW.accepted_execution_snapshot ? 'causalHumanSubjectId',false)
49
+ THEN '{"kind":"unknown"}'::jsonb
50
+ WHEN NEW.accepted_execution_snapshot->>'causalHumanSubjectId' IS NULL THEN '{"kind":"service"}'::jsonb
51
+ ELSE jsonb_build_object('kind','human',
52
+ 'initiatingHumanSubjectId',NEW.accepted_execution_snapshot->>'causalHumanSubjectId') END;
53
+ ELSIF TG_TABLE_NAME='usage_events' THEN
54
+ IF TG_OP='UPDATE' THEN
55
+ IF ((OLD.source_resource_type='knowledge_query' AND OLD.event_type='document.query_embedding_cost')
56
+ OR (OLD.source_resource_type='voice_transcription' AND OLD.event_type='model.cost'))
57
+ AND (NEW.account_id IS DISTINCT FROM OLD.account_id OR NEW.workspace_id IS DISTINCT FROM OLD.workspace_id
58
+ OR NEW.source_resource_type IS DISTINCT FROM OLD.source_resource_type
59
+ OR NEW.source_resource_id IS DISTINCT FROM OLD.source_resource_id
60
+ OR NEW.event_type IS DISTINCT FROM OLD.event_type OR NEW.quantity IS DISTINCT FROM OLD.quantity
61
+ OR NEW.idempotency_key IS DISTINCT FROM OLD.idempotency_key
62
+ OR NEW.initiator_context->'creditDebitAttribution' IS DISTINCT FROM
63
+ OLD.initiator_context->'creditDebitAttribution') THEN
64
+ RAISE EXCEPTION 'Allowance query attribution is immutable' USING ERRCODE='23514';
65
+ END IF;
66
+ RETURN NEW;
67
+ END IF;
68
+ IF NEW.workspace_id IS NULL OR NEW.source_resource_id IS NULL THEN RETURN NEW; END IF;
69
+ IF NEW.source_resource_type='knowledge_query' AND NEW.event_type='document.query_embedding_cost'
70
+ AND NEW.idempotency_key='knowledge.query_cost:'||NEW.source_resource_id THEN
71
+ v_source_kind:='knowledge_query';
72
+ ELSIF NEW.source_resource_type='voice_transcription' AND NEW.event_type='model.cost'
73
+ AND NEW.idempotency_key='voice.transcription_cost:'||NEW.source_resource_id THEN
74
+ v_source_kind:='voice_transcription';
75
+ ELSE RETURN NEW;
76
+ END IF;
77
+ v_source_id:=NEW.source_resource_id;
78
+ v_quantity:=NEW.quantity; v_idempotency_key:=NEW.idempotency_key;
79
+ -- Copy only attribution fields, never the initiator envelope/query/content.
80
+ v_attribution:=NEW.initiator_context->'creditDebitAttribution';
81
+ v_attribution:=CASE v_attribution->>'kind'
82
+ WHEN 'human' THEN jsonb_build_object('kind','human',
83
+ 'initiatingHumanSubjectId',v_attribution->'initiatingHumanSubjectId')
84
+ WHEN 'turn' THEN jsonb_build_object('kind','turn','turnId',v_attribution->'turnId',
85
+ 'initiatingHumanSubjectId',v_attribution->'initiatingHumanSubjectId')
86
+ WHEN 'service' THEN '{"kind":"service"}'::jsonb
87
+ ELSE '{"kind":"unknown"}'::jsonb END;
88
+ ELSE
89
+ RAISE EXCEPTION 'Unknown allowance attribution source' USING ERRCODE='55000';
90
+ END IF;
91
+ IF TG_OP='UPDATE' THEN RETURN NEW; END IF;
92
+ INSERT INTO opengeni_private.usage_allowance_capabilities VALUES
93
+ (pg_backend_pid(),pg_current_xact_id(),TG_TABLE_SCHEMA,NEW.account_id,NEW.workspace_id)
94
+ ON CONFLICT DO NOTHING;
95
+ GET DIAGNOSTICS opened=ROW_COUNT;
96
+ INSERT INTO opengeni_private.usage_allowance_attribution_receipts
97
+ (account_id,workspace_id,source_kind,source_id,session_id,attribution,quantity,idempotency_key)
98
+ VALUES(NEW.account_id,NEW.workspace_id,v_source_kind,v_source_id,v_session_id,v_attribution,v_quantity,v_idempotency_key);
99
+ IF opened=1 THEN
100
+ DELETE FROM opengeni_private.usage_allowance_capabilities
101
+ WHERE backend_pid=pg_backend_pid() AND transaction_id=pg_current_xact_id_if_assigned()
102
+ AND data_schema=TG_TABLE_SCHEMA AND account_id=NEW.account_id AND workspace_id=NEW.workspace_id;
103
+ END IF;
104
+ RETURN NEW;
105
+ END $$;
106
+
107
+ DO $debit$
108
+ DECLARE definition text:=pg_get_functiondef('count_workspace_allowance_debit()'::regprocedure);
109
+ anchor text:=$anchor$IF NEW.source_type='knowledge_query' THEN$anchor$;
110
+ replacement text:=$replacement$IF NEW.source_type='voice_transcription' THEN
111
+ SELECT receipt.attribution INTO attribution FROM opengeni_private.usage_allowance_attribution_receipts receipt
112
+ WHERE receipt.account_id=NEW.account_id AND receipt.workspace_id=NEW.workspace_id
113
+ AND receipt.source_kind='voice_transcription' AND receipt.source_id=NEW.source_id
114
+ AND receipt.idempotency_key='voice.transcription_cost:'||NEW.source_id
115
+ AND receipt.quantity=amount AND NEW.type='voice_transcription_debit';
116
+ attribution:=coalesce(attribution,'{"kind":"unknown"}'::jsonb);
117
+ ELSIF NEW.source_type='knowledge_query' THEN$replacement$;
118
+ BEGIN
119
+ IF strpos(definition,anchor)=0 OR strpos(substr(definition,strpos(definition,anchor)+length(anchor)),anchor)>0 THEN
120
+ RAISE EXCEPTION 'Unexpected allowance debit source branch' USING ERRCODE='55000';
121
+ END IF;
122
+ EXECUTE replace(definition,anchor,replacement);
123
+ END $debit$;
124
+
125
+ DO $harden$
126
+ BEGIN
127
+ EXECUTE format('ALTER FUNCTION %I.capture_usage_allowance_attribution() SET search_path=pg_catalog,%I,pg_temp', current_schema(), current_schema());
128
+ END $harden$;
@@ -0,0 +1,30 @@
1
+ -- deployment-mode: rolling
2
+ -- Admit configured Azure GPT Live WebRTC sessions.
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
+ 'opengeni-azure/gpt-live-1',
15
+ 'gpt-live-1-boulder-alpha',
16
+ 'supergrok/grok-voice-think-fast-2.0',
17
+ 'opengeni-gateway/openai/gpt-realtime-2.1',
18
+ 'opengeni-gateway/openai/gpt-realtime-mini',
19
+ 'opengeni-gateway/xai/grok-voice-think-fast-2.0',
20
+ 'workspace-gateway/openai/gpt-realtime-2.1',
21
+ 'workspace-gateway/openai/gpt-realtime-mini',
22
+ 'workspace-gateway/xai/grok-voice-think-fast-2.0'
23
+ )
24
+ ) NOT VALID;
25
+
26
+ ALTER TABLE "session_realtime_modes"
27
+ VALIDATE CONSTRAINT "session_realtime_modes_model_check";
28
+
29
+ RESET statement_timeout;
30
+ RESET lock_timeout;
@@ -0,0 +1,29 @@
1
+ -- deployment-mode: rolling
2
+ -- Persist the exact credit/allowance refusal on a resumable recording and its
3
+ -- segment, so a reloaded recording still explains why it stopped. Widening an
4
+ -- allowed-value CHECK only; no row is rewritten.
5
+
6
+ SET lock_timeout = '5s';
7
+ SET statement_timeout = '10min';
8
+
9
+ ALTER TABLE "transcription_recordings"
10
+ DROP CONSTRAINT "transcription_recordings_error_code_check";
11
+
12
+ ALTER TABLE "transcription_recordings"
13
+ ADD CONSTRAINT "transcription_recordings_error_code_check"
14
+ CHECK ("error_code" IS NULL OR "error_code" IN (
15
+ 'permission_denied', 'not_supported', 'network', 'provider', 'policy_blocked',
16
+ 'timeout', 'cancelled', 'unavailable', 'too_large', 'invalid_audio', 'unknown',
17
+ 'insufficient_credits', 'allowance_exhausted', 'monthly_model_cost_limit'
18
+ ));
19
+
20
+ ALTER TABLE "transcription_recording_segments"
21
+ DROP CONSTRAINT "transcription_recording_segments_error_code_check";
22
+
23
+ ALTER TABLE "transcription_recording_segments"
24
+ ADD CONSTRAINT "transcription_recording_segments_error_code_check"
25
+ CHECK ("error_code" IS NULL OR "error_code" IN (
26
+ 'permission_denied', 'not_supported', 'network', 'provider', 'policy_blocked',
27
+ 'timeout', 'cancelled', 'unavailable', 'too_large', 'invalid_audio', 'unknown',
28
+ 'insufficient_credits', 'allowance_exhausted', 'monthly_model_cost_limit'
29
+ ));
@@ -0,0 +1,239 @@
1
+ -- deployment-mode: rolling
2
+ -- Inert exact-origin projection. Trusted-server SQL privilege is NOT host
3
+ -- authentication. No grant, lease, provider operation, wake or custody is minted.
4
+ SET LOCAL lock_timeout = '5s';
5
+ SET LOCAL statement_timeout = '5min';
6
+
7
+ CREATE TABLE IF NOT EXISTS opengeni_private.modal_native_origin_read_capabilities (
8
+ capability_id uuid PRIMARY KEY,
9
+ data_schema oid NOT NULL,
10
+ backend_pid integer NOT NULL,
11
+ transaction_id xid8 NOT NULL,
12
+ account_id uuid NOT NULL,
13
+ workspace_id uuid NOT NULL,
14
+ session_id uuid NOT NULL,
15
+ turn_id uuid NOT NULL,
16
+ attempt_id uuid NOT NULL,
17
+ execution_generation integer NOT NULL CHECK (execution_generation > 0),
18
+ initiating_human_subject_id text NOT NULL
19
+ );
20
+ ALTER TABLE opengeni_private.modal_native_origin_read_capabilities ENABLE ROW LEVEL SECURITY;
21
+ ALTER TABLE opengeni_private.modal_native_origin_read_capabilities FORCE ROW LEVEL SECURITY;
22
+ REVOKE ALL ON TABLE opengeni_private.modal_native_origin_read_capabilities FROM PUBLIC;
23
+
24
+ DO $install$
25
+ DECLARE
26
+ target_schema text := current_schema();
27
+ target_oid oid := current_schema()::regnamespace;
28
+ owner_name text := current_user;
29
+ role_name text;
30
+ BEGIN
31
+ IF NOT EXISTS (SELECT 1 FROM pg_class WHERE oid='opengeni_private.modal_native_origin_read_capabilities'::regclass
32
+ AND relowner=current_user::regrole) THEN
33
+ RAISE EXCEPTION 'native origin capability owner mismatch' USING ERRCODE='55000';
34
+ END IF;
35
+ -- Remove hostile owner defaults; no runtime or PUBLIC table/column access.
36
+ FOR role_name IN SELECT DISTINCT r.rolname FROM pg_class c
37
+ CROSS JOIN LATERAL aclexplode(coalesce(c.relacl,acldefault('r',c.relowner))) a
38
+ JOIN pg_roles r ON r.oid=a.grantee
39
+ WHERE c.oid='opengeni_private.modal_native_origin_read_capabilities'::regclass
40
+ AND a.grantee<>c.relowner
41
+ LOOP
42
+ EXECUTE format('REVOKE ALL ON TABLE opengeni_private.modal_native_origin_read_capabilities FROM %I',role_name);
43
+ END LOOP;
44
+ IF NOT EXISTS (SELECT 1 FROM pg_policy WHERE polrelid='opengeni_private.modal_native_origin_read_capabilities'::regclass
45
+ AND polname='owner_only') THEN
46
+ EXECUTE format('CREATE POLICY owner_only ON opengeni_private.modal_native_origin_read_capabilities
47
+ USING (current_user=%L) WITH CHECK (current_user=%L)',owner_name,owner_name);
48
+ END IF;
49
+
50
+ EXECUTE format($ddl$
51
+ CREATE FUNCTION %1$I.modal_native_origin_member_read_active(p_account uuid,p_subject text)
52
+ RETURNS boolean LANGUAGE sql STABLE SECURITY DEFINER SET search_path=pg_catalog AS $body$
53
+ SELECT EXISTS (SELECT 1 FROM opengeni_private.modal_native_origin_read_capabilities c
54
+ WHERE c.data_schema=%2$s::oid AND c.backend_pid=pg_backend_pid()
55
+ AND c.transaction_id=pg_current_xact_id_if_assigned()
56
+ AND c.account_id=p_account AND c.initiating_human_subject_id=p_subject)
57
+ $body$;
58
+ REVOKE ALL ON FUNCTION %1$I.modal_native_origin_member_read_active(uuid,text) FROM PUBLIC;
59
+ CREATE POLICY modal_native_origin_member_read ON %1$I.organization_memberships FOR SELECT
60
+ USING (current_user=%3$L AND %1$I.modal_native_origin_member_read_active(account_id,subject_id));
61
+ $ddl$,target_schema,target_oid,owner_name);
62
+
63
+ EXECUTE format($ddl$
64
+ CREATE FUNCTION %1$I.lock_live_native_original_origin_v2(p_scope jsonb)
65
+ RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER
66
+ SET search_path=pg_catalog,%1$I,pg_temp AS $body$
67
+ DECLARE
68
+ s sessions%%ROWTYPE; t session_turns%%ROWTYPE; a session_turn_attempts%%ROWTYPE;
69
+ m organization_memberships%%ROWTYPE; control workspace_inference_controls%%ROWTYPE;
70
+ ancestor sessions%%ROWTYPE;
71
+ account_value uuid; workspace_value uuid; session_value uuid; turn_value uuid; attempt_value uuid;
72
+ generation_value integer; route_value integer; member_key bigint; tenancy_key bigint;
73
+ fenced_cap uuid; member_cap uuid; parent_value uuid; visited uuid[]; override_value bigint:=0;
74
+ count_value integer:=0; count_json jsonb; basis text; key_name text;
75
+ result jsonb:='{"kind":"fenced"}'::jsonb;
76
+ keys constant text[]:=ARRAY['version','declarationId','planId','creatorId','accountId','workspaceId',
77
+ 'sessionId','turnId','attemptId','executionGeneration','triggerEventId','sandboxGroupId',
78
+ 'routeKind','routeTargetId','routeEpoch'];
79
+ BEGIN
80
+ IF jsonb_typeof(p_scope) IS DISTINCT FROM 'object' OR NOT p_scope ?& keys
81
+ OR p_scope-keys<>'{}'::jsonb OR p_scope->'version'<>'2'::jsonb
82
+ OR p_scope->'routeKind'<>'"home"'::jsonb OR p_scope->'routeTargetId'<>'null'::jsonb
83
+ THEN RETURN '{"kind":"unsupported","reason":"invalid_scope"}'::jsonb; END IF;
84
+ FOREACH key_name IN ARRAY ARRAY['declarationId','planId','creatorId','accountId','workspaceId',
85
+ 'sessionId','turnId','attemptId','triggerEventId','sandboxGroupId'] LOOP
86
+ IF jsonb_typeof(p_scope->key_name)<>'string' OR (p_scope->>key_name) !~
87
+ '^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
88
+ THEN RETURN '{"kind":"unsupported","reason":"invalid_scope"}'::jsonb; END IF;
89
+ END LOOP;
90
+ FOREACH key_name IN ARRAY ARRAY['executionGeneration','routeEpoch'] LOOP
91
+ IF jsonb_typeof(p_scope->key_name)<>'number' OR
92
+ (p_scope->>key_name)::numeric<>trunc((p_scope->>key_name)::numeric) OR
93
+ (p_scope->>key_name)::numeric NOT BETWEEN 0 AND 2147483647
94
+ THEN RETURN '{"kind":"unsupported","reason":"invalid_scope"}'::jsonb; END IF;
95
+ END LOOP;
96
+ IF (p_scope->>'executionGeneration')::integer=0 OR p_scope->>'creatorId'=p_scope->>'attemptId'
97
+ OR p_scope->>'creatorId'=p_scope->>'planId'
98
+ THEN RETURN '{"kind":"unsupported","reason":"invalid_scope"}'::jsonb; END IF;
99
+ account_value:=(p_scope->>'accountId')::uuid; workspace_value:=(p_scope->>'workspaceId')::uuid;
100
+ session_value:=(p_scope->>'sessionId')::uuid; turn_value:=(p_scope->>'turnId')::uuid;
101
+ attempt_value:=(p_scope->>'attemptId')::uuid;
102
+ generation_value:=(p_scope->>'executionGeneration')::integer; route_value:=(p_scope->>'routeEpoch')::integer;
103
+ IF account_value IS DISTINCT FROM opengeni_private.current_account_id()
104
+ OR workspace_value IS DISTINCT FROM opengeni_private.current_workspace_id()
105
+ OR nullif(current_setting('opengeni.subject_id',true),'') IS NULL
106
+ THEN RETURN result; END IF;
107
+ member_key:=hashtextextended('organization-membership:'||account_value::text,0);
108
+ tenancy_key:=hashtextextended('session-tenancy:'||workspace_value::text,0);
109
+ IF EXISTS (SELECT 1 FROM pg_locks l WHERE l.pid=pg_backend_pid() AND l.locktype='advisory'
110
+ AND l.granted AND l.classid=((tenancy_key>>32)&4294967295)::oid
111
+ AND l.objid=(tenancy_key&4294967295)::oid AND l.objsubid=1)
112
+ AND NOT EXISTS (SELECT 1 FROM pg_locks l WHERE l.pid=pg_backend_pid() AND l.locktype='advisory'
113
+ AND l.granted AND l.mode='ExclusiveLock' AND l.classid=((member_key>>32)&4294967295)::oid
114
+ AND l.objid=(member_key&4294967295)::oid AND l.objsubid=1)
115
+ THEN RAISE EXCEPTION 'native origin requires membership-before-tenancy entry' USING ERRCODE='25001'; END IF;
116
+ PERFORM pg_advisory_xact_lock(member_key);
117
+ PERFORM acquire_session_tenancy_fence(workspace_value);
118
+ fenced_cap:=opengeni_private.open_session_tenancy_fenced_access(%2$s::oid);
119
+ <<projection>>
120
+ BEGIN
121
+ PERFORM pg_advisory_xact_lock_shared(hashtextextended('workspace-control:'||workspace_value::text,0));
122
+ SELECT * INTO control FROM workspace_inference_controls WHERE workspace_id=workspace_value
123
+ AND account_id=account_value FOR SHARE;
124
+ IF NOT FOUND THEN EXIT projection; END IF;
125
+ PERFORM 1 FROM workspaces WHERE id=workspace_value AND account_id=account_value FOR KEY SHARE;
126
+ IF NOT FOUND THEN EXIT projection; END IF;
127
+ SELECT * INTO s FROM sessions WHERE id=session_value AND workspace_id=workspace_value
128
+ AND account_id=account_value FOR NO KEY UPDATE;
129
+ IF NOT FOUND THEN EXIT projection; END IF;
130
+ PERFORM 1 FROM session_event_cursors WHERE workspace_id=workspace_value AND session_id=session_value FOR UPDATE;
131
+ IF NOT FOUND THEN EXIT projection; END IF;
132
+ SELECT * INTO t FROM session_turns WHERE id=turn_value AND workspace_id=workspace_value
133
+ AND account_id=account_value AND session_id=session_value FOR UPDATE;
134
+ IF NOT FOUND THEN EXIT projection; END IF;
135
+ SELECT * INTO a FROM session_turn_attempts WHERE id=attempt_value AND workspace_id=workspace_value
136
+ AND account_id=account_value AND session_id=session_value AND turn_id=turn_value FOR UPDATE;
137
+ IF NOT FOUND THEN EXIT projection; END IF;
138
+ IF s.status<>'running' OR s.admission_block IS NOT NULL OR s.active_turn_id IS DISTINCT FROM turn_value
139
+ OR t.status<>'running' OR t.active_attempt_id IS DISTINCT FROM attempt_value
140
+ OR t.execution_generation<>generation_value OR a.execution_generation<>generation_value
141
+ OR t.trigger_event_id<>(p_scope->>'triggerEventId')::uuid
142
+ OR s.sandbox_group_id<>(p_scope->>'sandboxGroupId')::uuid
143
+ OR s.active_sandbox_id IS NOT NULL OR s.active_epoch<>route_value
144
+ OR a.state NOT IN ('claimed','running') OR a.outcome IS NOT NULL
145
+ OR a.closed_at IS NOT NULL OR a.quiesced_at IS NOT NULL
146
+ OR a.authority_epoch IS NULL OR a.authority_visibility IS NULL
147
+ OR a.authority_epoch NOT BETWEEN s.execution_authority_epoch AND s.authority_epoch
148
+ OR NOT (a.authority_visibility=s.visibility OR (a.authority_visibility='user_private'
149
+ AND s.visibility='workspace_shared' AND a.authority_epoch<s.authority_epoch))
150
+ OR a.authority_owner_organization_membership_id IS DISTINCT FROM s.owner_organization_membership_id
151
+ OR (a.authority_visibility='user_private' AND a.authority_owner_organization_membership_id IS NULL)
152
+ OR EXISTS (SELECT 1 FROM session_attempt_interruptions i WHERE i.workspace_id=workspace_value
153
+ AND i.session_id=session_value AND i.attempt_id=attempt_value AND i.state IN ('pending','delivered','acknowledged'))
154
+ THEN EXIT projection; END IF;
155
+ -- Same override ordering as projectEffectiveControl; control SHARE
156
+ -- serializes all ancestry control writes, including Pause/Resume/Cancel.
157
+ ancestor:=s; visited:=ARRAY[]::uuid[];
158
+ LOOP
159
+ IF ancestor.id=ANY(visited) OR cardinality(visited)>10000 THEN EXIT projection; END IF;
160
+ visited:=array_append(visited,ancestor.id);
161
+ IF ancestor.direct_control_state='paused' AND
162
+ (ancestor.direct_pause_revision IS NULL OR override_value<=ancestor.direct_pause_revision)
163
+ THEN EXIT projection; END IF;
164
+ override_value:=greatest(override_value,coalesce(ancestor.subtree_run_override_revision,0));
165
+ parent_value:=ancestor.parent_session_id;
166
+ EXIT WHEN parent_value IS NULL;
167
+ SELECT * INTO ancestor FROM sessions WHERE id=parent_value AND workspace_id=workspace_value AND account_id=account_value;
168
+ IF NOT FOUND THEN EXIT projection; END IF;
169
+ END LOOP;
170
+ IF control.workspace_state='paused' AND
171
+ (control.workspace_pause_revision IS NULL OR override_value<=control.workspace_pause_revision)
172
+ THEN EXIT projection; END IF;
173
+ IF EXISTS (SELECT 1 FROM session_pending_tool_calls WHERE workspace_id=workspace_value AND session_id=session_value)
174
+ OR EXISTS (SELECT 1 FROM agent_run_states WHERE workspace_id=workspace_value AND session_id=session_value AND turn_id=turn_value)
175
+ -- claimTurnAttempt publishes turn.started before establishTurnSandbox.
176
+ -- It is lifecycle truth, not evidence that a model was dispatched.
177
+ OR EXISTS (SELECT 1 FROM session_events WHERE workspace_id=workspace_value AND session_id=session_value
178
+ AND turn_id=turn_value AND type='agent.model.request')
179
+ THEN result:='{"kind":"unsupported","reason":"not_premodel"}'::jsonb; EXIT projection; END IF;
180
+ IF t.initiating_human_subject_id IS NULL OR t.initiator_subject_id='unattributed-legacy'
181
+ OR t.initiating_human_subject_id NOT LIKE 'user:%%'
182
+ THEN result:='{"kind":"unsupported","reason":"human_unavailable"}'::jsonb; EXIT projection; END IF;
183
+ IF EXISTS (SELECT 1 FROM external_link_turn_authorities WHERE account_id=account_value
184
+ AND workspace_id=workspace_value AND turn_id=turn_value)
185
+ THEN result:='{"kind":"unsupported","reason":"external_authority"}'::jsonb; EXIT projection; END IF;
186
+ IF jsonb_typeof(t.metadata) IS DISTINCT FROM 'object' THEN EXIT projection; END IF;
187
+ IF t.metadata ? 'providerRecoveryCount' THEN
188
+ count_json:=t.metadata->'providerRecoveryCount';
189
+ IF jsonb_typeof(count_json) IS DISTINCT FROM 'number' THEN EXIT projection; END IF;
190
+ IF count_json::numeric<>trunc(count_json::numeric) OR count_json::numeric NOT BETWEEN 0 AND 5
191
+ THEN EXIT projection; END IF;
192
+ count_value:=count_json::integer;
193
+ END IF;
194
+ member_cap:=gen_random_uuid();
195
+ INSERT INTO opengeni_private.modal_native_origin_read_capabilities VALUES
196
+ (member_cap,%2$s::oid,pg_backend_pid(),pg_current_xact_id(),account_value,workspace_value,
197
+ session_value,turn_value,attempt_value,generation_value,t.initiating_human_subject_id);
198
+ SELECT * INTO m FROM organization_memberships WHERE account_id=account_value
199
+ AND subject_id=t.initiating_human_subject_id AND status='active' AND revoked_at IS NULL;
200
+ IF NOT FOUND THEN EXIT projection; END IF;
201
+ IF m.personal_workspace_id=workspace_value THEN basis:='personal_workspace';
202
+ ELSIF EXISTS (SELECT 1 FROM workspace_memberships WHERE account_id=account_value
203
+ AND workspace_id=workspace_value AND subject_id=t.initiating_human_subject_id)
204
+ THEN basis:='workspace_membership'; ELSE EXIT projection; END IF;
205
+ IF s.visibility='user_private' AND (s.owner_subject_id IS DISTINCT FROM t.initiating_human_subject_id
206
+ OR s.owner_organization_membership_id IS DISTINCT FROM m.id) THEN EXIT projection; END IF;
207
+ result:=jsonb_build_object('kind','live','projection',jsonb_build_object(
208
+ 'version',1,'scope',p_scope,
209
+ 'initiator',jsonb_build_object('kind',t.initiator_kind,'subjectId',t.initiator_subject_id,
210
+ 'initiatingHumanSubjectId',t.initiating_human_subject_id),
211
+ 'membership',jsonb_build_object('id',m.id,'authorizationRevision',m.authorization_revision::text,'basis',basis),
212
+ 'acceptedAuthority',jsonb_build_object('epoch',a.authority_epoch,'visibility',a.authority_visibility,
213
+ 'ownerOrganizationMembershipId',a.authority_owner_organization_membership_id),
214
+ 'currentAuthority',jsonb_build_object('epoch',s.authority_epoch,'executionEpoch',s.execution_authority_epoch,
215
+ 'visibility',s.visibility,'ownerSubjectId',s.owner_subject_id,'ownerOrganizationMembershipId',s.owner_organization_membership_id),
216
+ 'control',jsonb_build_object('workspaceRevision',control.revision::text,'sessionVersion',s.control_version::text),
217
+ 'execution',jsonb_build_object('workflowId',a.temporal_workflow_id,'workflowRunId',a.temporal_workflow_run_id,
218
+ 'activityId',a.temporal_activity_id),
219
+ 'providerRecoveryCount',count_value,'checkedAt',clock_timestamp()));
220
+ END projection;
221
+ DELETE FROM opengeni_private.modal_native_origin_read_capabilities WHERE capability_id=member_cap;
222
+ PERFORM opengeni_private.close_session_tenancy_fenced_access(fenced_cap);
223
+ RETURN result;
224
+ EXCEPTION WHEN OTHERS THEN
225
+ -- The function's exception subtransaction rolls back its own capabilities
226
+ -- and locks. Preserve any earlier caller capability; propagate uncertainty.
227
+ RAISE;
228
+ END
229
+ $body$;
230
+ REVOKE ALL ON FUNCTION %1$I.lock_live_native_original_origin_v2(jsonb) FROM PUBLIC;
231
+ $ddl$,target_schema,target_oid);
232
+ FOR role_name IN SELECT jsonb_array_elements_text(coalesce(nullif(
233
+ current_setting('opengeni.migration_application_roles',true),'')::jsonb,'[]'::jsonb)) LOOP
234
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname=role_name) THEN
235
+ EXECUTE format('GRANT EXECUTE ON FUNCTION %I.lock_live_native_original_origin_v2(jsonb) TO %I',target_schema,role_name);
236
+ END IF;
237
+ END LOOP;
238
+ END
239
+ $install$;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/db",
3
- "version": "1.3.0",
3
+ "version": "1.4.2",
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": {
@@ -115,12 +115,12 @@
115
115
  "prepublishOnly": "bash ../../scripts/prepublish-guard"
116
116
  },
117
117
  "dependencies": {
118
- "@opengeni/codemode": "1.3.0",
119
- "@opengeni/codex": "1.3.0",
120
- "@opengeni/config": "1.3.0",
121
- "@opengeni/contracts": "1.3.0",
122
- "@opengeni/network": "1.3.0",
123
- "@opengeni/observability": "1.3.0",
118
+ "@opengeni/codemode": "1.4.2",
119
+ "@opengeni/codex": "1.4.2",
120
+ "@opengeni/config": "1.4.2",
121
+ "@opengeni/contracts": "1.4.2",
122
+ "@opengeni/network": "1.4.2",
123
+ "@opengeni/observability": "1.4.2",
124
124
  "drizzle-orm": "^0.45.2",
125
125
  "postgres": "^3.4.7"
126
126
  },
@@ -277,7 +277,13 @@ export async function adoptCodemodeApproval(
277
277
  );
278
278
  }
279
279
 
280
- /** Read a handle with the current exact attempt and same original caller; old bearer authority is insufficient. */
280
+ /**
281
+ * Read a handle with the current exact attempt and same original caller; old
282
+ * bearer authority is insufficient. This is a status read polled while a
283
+ * caller waits, so it is one plain snapshot select: it proves the exact live
284
+ * attempt in the same statement but takes no session/turn/attempt row locks
285
+ * and is not refused by a pending Pause/Steer, which owns the write fence only.
286
+ */
281
287
  export async function readTurnCodemodeOperation(
282
288
  db: Database,
283
289
  input: CodemodeContinuationScope & {
@@ -285,27 +291,51 @@ export async function readTurnCodemodeOperation(
285
291
  callerSubjectId: string;
286
292
  },
287
293
  ): Promise<CodemodeOperation | null> {
288
- return await withRlsContext(
289
- db,
290
- input,
291
- async (scoped) =>
292
- await scoped.transaction(async (tx) => {
293
- await lockActiveTurn(tx as unknown as Database, input);
294
- const [row] = await tx
295
- .select()
296
- .from(schema.sessionAttemptCodemodeCalls)
297
- .where(
298
- and(
299
- eq(schema.sessionAttemptCodemodeCalls.workspaceId, input.workspaceId),
300
- eq(schema.sessionAttemptCodemodeCalls.sessionId, input.sessionId),
301
- eq(schema.sessionAttemptCodemodeCalls.turnId, input.turnId),
302
- eq(schema.sessionAttemptCodemodeCalls.operationId, input.operationId),
303
- ),
304
- )
305
- .limit(1);
306
- return row && codemodeCallerCanContinue(row, input) ? mapCodemodeOperation(row) : null;
307
- }),
308
- );
294
+ return await withRlsContext(db, input, async (scoped) => {
295
+ const [live] = await scoped
296
+ .select({ attemptId: schema.sessionTurnAttempts.id })
297
+ .from(schema.sessionTurns)
298
+ .innerJoin(
299
+ schema.sessionTurnAttempts,
300
+ and(
301
+ eq(schema.sessionTurnAttempts.id, schema.sessionTurns.activeAttemptId),
302
+ eq(schema.sessionTurnAttempts.turnId, schema.sessionTurns.id),
303
+ eq(schema.sessionTurnAttempts.sessionId, schema.sessionTurns.sessionId),
304
+ eq(schema.sessionTurnAttempts.accountId, schema.sessionTurns.accountId),
305
+ eq(
306
+ schema.sessionTurnAttempts.executionGeneration,
307
+ schema.sessionTurns.executionGeneration,
308
+ ),
309
+ ),
310
+ )
311
+ .where(
312
+ and(
313
+ eq(schema.sessionTurns.id, input.turnId),
314
+ eq(schema.sessionTurns.accountId, input.accountId),
315
+ eq(schema.sessionTurns.workspaceId, input.workspaceId),
316
+ eq(schema.sessionTurns.sessionId, input.sessionId),
317
+ eq(schema.sessionTurns.status, "running"),
318
+ eq(schema.sessionTurns.activeAttemptId, input.attemptId),
319
+ eq(schema.sessionTurns.executionGeneration, input.executionGeneration),
320
+ inArray(schema.sessionTurnAttempts.state, ["claimed", "running"]),
321
+ ),
322
+ )
323
+ .limit(1);
324
+ if (!live) throw new CodemodeOperationNotExecutableError();
325
+ const [row] = await scoped
326
+ .select()
327
+ .from(schema.sessionAttemptCodemodeCalls)
328
+ .where(
329
+ and(
330
+ eq(schema.sessionAttemptCodemodeCalls.workspaceId, input.workspaceId),
331
+ eq(schema.sessionAttemptCodemodeCalls.sessionId, input.sessionId),
332
+ eq(schema.sessionAttemptCodemodeCalls.turnId, input.turnId),
333
+ eq(schema.sessionAttemptCodemodeCalls.operationId, input.operationId),
334
+ ),
335
+ )
336
+ .limit(1);
337
+ return row && codemodeCallerCanContinue(row, input) ? mapCodemodeOperation(row) : null;
338
+ });
309
339
  }
310
340
 
311
341
  /** Signed sandbox subjects are attempt-bound; only the same owning turn can use this mapping. */