@opengeni/db 1.0.1 → 3.1.0-canary.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.
- package/dist/attached-browser-devices.d.ts +7 -0
- package/dist/automations.d.ts +154 -0
- package/dist/canonical-human-identities.js +3 -3
- package/dist/capability-integrations.d.ts +13 -0
- package/dist/child-lifecycle-notices.d.ts +68 -0
- package/dist/{chunk-LTG3S6ZY.js → chunk-EULAN2NP.js} +2 -2
- package/dist/{chunk-CUPM3FGB.js → chunk-NJVZPWXY.js} +3 -3
- package/dist/{chunk-4SR4HKKA.js → chunk-NMUBV7Z5.js} +19 -11
- package/dist/chunk-NMUBV7Z5.js.map +1 -0
- package/dist/chunk-OF5OBB76.js +4457 -0
- package/dist/chunk-OF5OBB76.js.map +1 -0
- package/dist/{chunk-6ZYKCRFO.js → chunk-PR2WMLOQ.js} +7580 -4417
- package/dist/chunk-PR2WMLOQ.js.map +1 -0
- package/dist/{chunk-ZWREYEWA.js → chunk-SCPUJS53.js} +41 -4
- package/dist/chunk-SCPUJS53.js.map +1 -0
- package/dist/{chunk-SK7YYHBI.js → chunk-SIBYBA2D.js} +46 -1
- package/dist/chunk-SIBYBA2D.js.map +1 -0
- package/dist/chunk-TIKF3KTI.js +383 -0
- package/dist/chunk-TIKF3KTI.js.map +1 -0
- package/dist/chunk-ZZ5LJEFX.js +516 -0
- package/dist/chunk-ZZ5LJEFX.js.map +1 -0
- package/dist/codemode-operations.d.ts +1 -6
- package/dist/company-brain-context-selection-schema.d.ts +705 -0
- package/dist/company-brain-context-selection.d.ts +94 -0
- package/dist/company-brain-governed-writes.d.ts +24 -0
- package/dist/company-brain.d.ts +55 -0
- package/dist/company-profile-agent-admin.d.ts +15 -0
- package/dist/company-profile-schema.d.ts +619 -2
- package/dist/company-profile.d.ts +9 -4
- package/dist/connection-authority.d.ts +95 -0
- package/dist/connection-scopes.d.ts +8 -0
- package/dist/connection-tenancy-backfill.d.ts +41 -0
- package/dist/connection-token-resolver.d.ts +30 -1
- package/dist/database.d.ts +19 -0
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.d.ts +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/governed-learning-activation-schema.d.ts +984 -0
- package/dist/governed-learning-activation.d.ts +98 -0
- package/dist/governed-learning-evaluator-schema.d.ts +633 -0
- package/dist/governed-learning-evaluator.d.ts +28 -0
- package/dist/index.d.ts +1595 -81
- package/dist/index.js +21571 -8126
- package/dist/index.js.map +1 -1
- package/dist/insights.d.ts +18 -0
- package/dist/integration-bindings.d.ts +1 -0
- package/dist/integration-facets.d.ts +30 -0
- package/dist/interaction-placement-loss.d.ts +22 -0
- package/dist/managed-human-provisioning.d.ts +25 -0
- package/dist/memory-domain.d.ts +3 -3
- package/dist/migrate.d.ts +11 -1
- package/dist/migrate.js +1 -1
- package/dist/new-session-drafts.d.ts +43 -5
- package/dist/organization-membership-backfill.d.ts +174 -0
- package/dist/organization-membership-lifecycle.d.ts +162 -0
- package/dist/pr-review.d.ts +107 -0
- package/dist/preference-registry-schema.d.ts +2 -0
- package/dist/preference-registry.d.ts +2 -0
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +22 -8
- package/dist/schema.d.ts +24914 -13703
- package/dist/schema.js +99 -1
- package/dist/scoped-knowledge-schema.d.ts +52 -1
- package/dist/session-background-commands.d.ts +125 -0
- package/dist/session-background-commands.js +34 -0
- package/dist/session-background-commands.js.map +1 -0
- package/dist/session-control.d.ts +156 -3
- package/dist/session-goal-pacing.d.ts +68 -0
- package/dist/session-queue-commands.d.ts +41 -4
- package/dist/session-realtime-ledger.d.ts +2 -0
- package/dist/session-tenancy.d.ts +71 -1
- package/dist/session-tenancy.js +25 -3
- package/dist/session-tool-call-settlement.d.ts +9 -4
- package/dist/slack-routing-personal-workspace.d.ts +23 -0
- package/dist/slack-routing.d.ts +153 -0
- package/dist/slack-task-policy-schema.d.ts +34 -0
- package/dist/slack-task-policy.d.ts +8 -0
- package/dist/slack-user-link-access.d.ts +1 -0
- package/dist/task-notes-schema.d.ts +594 -0
- package/dist/task-notes.d.ts +39 -0
- package/dist/turn-initiator.d.ts +2 -0
- package/dist/user-resource-authority.d.ts +109 -0
- package/dist/video-generation.js +3 -3
- package/dist/workspace-authority.d.ts +81 -0
- package/dist/workspace-instruction-policies-schema.d.ts +279 -0
- package/dist/workspace-instruction-policies.d.ts +62 -0
- package/dist/workspace-learning-policy.d.ts +1 -0
- package/dist/workspace-membership-permissions.d.ts +2 -0
- package/drizzle/0240_enrollment_connection_authority.sql +39 -0
- package/drizzle/0241_atomic_personal_resource_delegation.sql +1000 -0
- package/drizzle/0241_enrollment_agent_runtime.sql +70 -0
- package/drizzle/0244_slack_app_home_refresh_queue.sql +120 -0
- package/drizzle/0245_model_context_contribution_facts.sql +88 -0
- package/drizzle/0246_integration_personal_instance_authority.sql +70 -0
- package/drizzle/0247_terraform_stacks_provenance_repair.sql +428 -0
- package/drizzle/0248_terraform_stacks_component_resolution_fence.sql +83 -0
- package/drizzle/0249_personal_resource_delegation_authority_correction.sql +662 -0
- package/drizzle/0250_direct_retained_process_owner_liveness.sql +199 -0
- package/drizzle/0251_connected_machine_operation_policy.sql +45 -0
- package/drizzle/0252_scheduled_personal_resource_delegation.sql +1867 -0
- package/drizzle/0253_common_user_resource_authority_lifecycle.sql +1555 -0
- package/drizzle/0254_scoped_variable_set_authority.sql +1255 -0
- package/drizzle/0255_company_brain_governed_write_proposals.sql +524 -0
- package/drizzle/0256_connection_authority_delegation.sql +703 -0
- package/drizzle/0257_goal_revision_decisions_and_root_constraints.sql +436 -0
- package/drizzle/0258_three_scope_document_knowledge_authority.sql +1273 -0
- package/drizzle/0259_company_brain_context_selection_receipts.sql +869 -0
- package/drizzle/0260_task_note_knowledge_promotion.sql +820 -0
- package/drizzle/0261_preference_knowledge_proposal_actor_binding.sql +471 -0
- package/drizzle/0262_scoped_connected_machines_and_rigs.sql +1700 -0
- package/drizzle/0263_organization_membership_lifecycle.sql +3284 -0
- package/drizzle/0264_connection_authority_runtime_activation.sql +1084 -0
- package/drizzle/0266_company_brain_context_receipt_inspection.sql +156 -0
- package/drizzle/0268_governed_learning_decision_receipts.sql +825 -0
- package/drizzle/0269_governed_learning_activation_controller.sql +1874 -0
- package/drizzle/0270_governed_learning_history_inspection.sql +170 -0
- package/drizzle/0271_company_brain_retrieval_only_default.sql +524 -0
- package/drizzle/0272_human_confirmed_learning_activation.sql +591 -0
- package/drizzle/0273_scheduled_variable_set_materialization.sql +268 -0
- package/drizzle/0274_human_confirmed_knowledge_review.sql +310 -0
- package/drizzle/0275_scheduled_connection_authority.sql +5527 -0
- package/drizzle/0276_onboarding_proposal_initiating_human_guc.sql +198 -0
- package/drizzle/0277_workspace_writer_authority_attribution.sql +393 -0
- package/drizzle/0278_workspace_membership_removal_fencing.sql +1174 -0
- package/drizzle/0279_workspace_connection_use_lane.sql +343 -0
- package/drizzle/0280_connection_and_variable_set_audit_attribution.sql +773 -0
- package/drizzle/0281_viewer_holder_authority_claims.sql +52 -0
- package/drizzle/0282_variable_set_session_attach_attribution.sql +178 -0
- package/drizzle/0283_editable_spreadsheet_authored_state.sql +82 -0
- package/drizzle/0284_truthful_human_confirmed_review_reason.sql +930 -0
- package/drizzle/0285_organization_tenancy_inventory.sql +329 -0
- package/drizzle/0286_widen_task_note_expiry_ceiling.sql +391 -0
- package/drizzle/0287_open_suffix_pending_tool_calls.sql +18 -0
- package/drizzle/0288_attached_browser_reenrollment.sql +64 -0
- package/drizzle/0289_session_composer_policy_authority.sql +597 -0
- package/drizzle/0290_organization_membership_backfill.sql +268 -0
- package/drizzle/0291_resource_authority_classification_assertion.sql +371 -0
- package/drizzle/0292_truthful_tenancy_inventory_counters.sql +291 -0
- package/drizzle/0293_confirm_time_rule_rebaseline.sql +615 -0
- package/drizzle/0294_preference_activation_authority.sql +237 -0
- package/drizzle/0295_retire_legacy_standing_memory_mode.sql +476 -0
- package/drizzle/0296_force_rls_backfill_noop_repair.sql +215 -0
- package/drizzle/0297_session_ownership_classification_and_backfill.sql +752 -0
- package/drizzle/0298_organization_tenancy_parity.sql +609 -0
- package/drizzle/0299_organization_membership_lock_order.sql +291 -0
- package/drizzle/0300_tenancy_backfill_ledger.sql +459 -0
- package/drizzle/0301_session_snapshot_and_pin_visibility.sql +181 -0
- package/drizzle/0302_personal_workspace_session_ownership.sql +303 -0
- package/drizzle/0303_session_tenancy_product_activation.sql +919 -0
- package/drizzle/0304_personal_workspace_private_session_reads.sql +97 -0
- package/drizzle/0305_personal_resource_grant_management.sql +584 -0
- package/drizzle/0306_atomic_personal_resource_attachments.sql +1374 -0
- package/drizzle/0307_session_attention_state.sql +51 -0
- package/drizzle/0308_session_archives.sql +35 -0
- package/drizzle/0309_channel_project_pins.sql +6 -0
- package/drizzle/0310_channel_project_order.sql +27 -0
- package/drizzle/0311_company_scope_and_private_session_create.sql +656 -0
- package/drizzle/0312_quiescent_session_tree_deletion.sql +39 -0
- package/drizzle/0313_private_child_session_authority.sql +365 -0
- package/drizzle/0314_unregistered_organization_invitations.sql +606 -0
- package/drizzle/0315_personal_github_repository_selection.sql +624 -0
- package/drizzle/0316_human_confirmed_activation_resumed_generation.sql +869 -0
- package/drizzle/0317_session_goal_continuation_hold.sql +64 -0
- package/drizzle/0318_session_turn_startup_milestones.sql +115 -0
- package/drizzle/0319_event_triggered_automations.sql +254 -0
- package/drizzle/0320_pr_review_pack.sql +113 -0
- package/drizzle/0321_slack_bot_environment_display_name.sql +15 -0
- package/drizzle/0322_session_turns_unclaimed_prompt_trigger_index.sql +5 -0
- package/drizzle/0323_organization_private_session_enablement.sql +489 -0
- package/drizzle/0324_human_confirmed_company_profile_agent_admin.sql +856 -0
- package/drizzle/0325_child_lifecycle_notices.sql +44 -0
- package/drizzle/0326_interaction_operation_error_codes.sql +62 -0
- package/drizzle/0327_slack_first_task_hint.sql +29 -0
- package/drizzle/0328_session_background_commands.sql +590 -0
- package/drizzle/0329_slack_orchestration_delivery_events.sql +91 -0
- package/drizzle/0330_api_key_descriptions.sql +20 -0
- package/drizzle/0331_managed_organization_creation.sql +163 -0
- package/drizzle/0332_organization_shared_workspace_control_plane.sql +539 -0
- package/drizzle/0333_session_turn_prompt_routing.sql +45 -0
- package/drizzle/0334_connected_machine_workspace_root.sql +99 -0
- package/drizzle/0335_slack_workspace_routing.sql +460 -0
- package/drizzle/0336_atomic_session_fork_visibility.sql +667 -0
- package/drizzle/0337_slack_routed_action_handles.sql +189 -0
- package/drizzle/0338_atomic_connected_machine_attachments.sql +410 -0
- package/drizzle/0339_document_authority_reclassification.sql +1153 -0
- package/drizzle/0340_tenancy_backfill_activation_evidence.sql +1347 -0
- package/drizzle/0341_slack_routing_probe_organization_fence.sql +109 -0
- package/package.json +10 -6
- package/src/attached-browser-devices.ts +233 -5
- package/src/automations.ts +911 -0
- package/src/browser-sessions.ts +10 -0
- package/src/capability-integrations.ts +175 -1
- package/src/child-lifecycle-notices.ts +241 -0
- package/src/codemode-operations.ts +1 -35
- package/src/company-brain-context-selection-schema.ts +100 -0
- package/src/company-brain-context-selection.ts +359 -0
- package/src/company-brain-governed-writes.ts +1170 -0
- package/src/company-brain.ts +309 -0
- package/src/company-profile-agent-admin.ts +225 -0
- package/src/company-profile-schema.ts +121 -1
- package/src/company-profile.ts +21 -0
- package/src/computer-sessions.ts +10 -1
- package/src/connection-authority.ts +290 -0
- package/src/connection-scopes.ts +20 -0
- package/src/connection-tenancy-backfill.ts +81 -0
- package/src/connection-token-resolver.ts +263 -31
- package/src/database.ts +75 -2
- package/src/editable-artifacts-schema.ts +10 -5
- package/src/editable-artifacts.ts +21 -11
- package/src/governed-learning-activation-schema.ts +121 -0
- package/src/governed-learning-activation.ts +588 -0
- package/src/governed-learning-evaluator-schema.ts +72 -0
- package/src/governed-learning-evaluator.ts +217 -0
- package/src/index.ts +11651 -1548
- package/src/insights.ts +107 -0
- package/src/integration-bindings.ts +88 -6
- package/src/integration-facets.ts +287 -84
- package/src/interaction-placement-loss.ts +234 -0
- package/src/managed-human-provisioning.ts +116 -0
- package/src/memory-domain.ts +27 -32
- package/src/migrate.ts +77 -1
- package/src/new-session-drafts.ts +229 -35
- package/src/organization-membership-backfill.ts +735 -0
- package/src/organization-membership-lifecycle.ts +985 -0
- package/src/pr-review.ts +890 -0
- package/src/preference-registry.ts +31 -1
- package/src/provision-roles.ts +877 -6
- package/src/runtime-posture-cli.ts +2 -0
- package/src/runtime-posture.ts +1291 -76
- package/src/schema.ts +3303 -428
- package/src/scoped-knowledge-schema.ts +16 -8
- package/src/scoped-knowledge.ts +1 -1
- package/src/session-background-commands.ts +759 -0
- package/src/session-control.ts +640 -74
- package/src/session-goal-pacing.ts +126 -0
- package/src/session-queue-commands.ts +437 -84
- package/src/session-realtime-context.ts +3 -3
- package/src/session-realtime-ledger.ts +22 -11
- package/src/session-realtime-mirror.ts +1 -1
- package/src/session-tenancy.ts +403 -49
- package/src/session-tool-call-settlement.ts +38 -29
- package/src/slack-routing-personal-workspace.ts +67 -0
- package/src/slack-routing.ts +469 -0
- package/src/slack-task-policy-schema.ts +5 -0
- package/src/slack-task-policy.ts +18 -0
- package/src/slack-user-link-access.ts +17 -1
- package/src/task-notes-schema.ts +74 -0
- package/src/task-notes.ts +124 -2
- package/src/turn-initiator.ts +8 -0
- package/src/user-resource-authority.ts +377 -0
- package/src/workspace-authority.ts +160 -0
- package/src/workspace-instruction-policies-schema.ts +53 -1
- package/src/workspace-instruction-policies.ts +528 -77
- package/src/workspace-learning-policy.ts +21 -5
- package/src/workspace-membership-permissions.ts +9 -0
- package/dist/chunk-4SR4HKKA.js.map +0 -1
- package/dist/chunk-6ZYKCRFO.js.map +0 -1
- package/dist/chunk-NXAFLCQX.js +0 -2468
- package/dist/chunk-NXAFLCQX.js.map +0 -1
- package/dist/chunk-SK7YYHBI.js.map +0 -1
- package/dist/chunk-WD5ROSLL.js +0 -117
- package/dist/chunk-WD5ROSLL.js.map +0 -1
- package/dist/chunk-ZWREYEWA.js.map +0 -1
- /package/dist/{chunk-LTG3S6ZY.js.map → chunk-EULAN2NP.js.map} +0 -0
- /package/dist/{chunk-CUPM3FGB.js.map → chunk-NJVZPWXY.js.map} +0 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Migration 0279: workspace-owned connections stop bypassing the accepted
|
|
3
|
+
-- connection-use authority.
|
|
4
|
+
--
|
|
5
|
+
-- Before this migration `resolve_accepted_connection_use` had two lanes -
|
|
6
|
+
-- the frozen per-turn personal snapshot ('user') and the bounded
|
|
7
|
+
-- 'legacy_user' compatibility lane - and the worker short-circuited every
|
|
8
|
+
-- workspace-scope request straight to credential resolution: no lifecycle
|
|
9
|
+
-- fences, no idempotent audit fact, no per-provider-request authorization.
|
|
10
|
+
-- This redefinition adds the workspace lane: the same canonical
|
|
11
|
+
-- control/workspace/session/turn/attempt fences and interruption checks, the
|
|
12
|
+
-- same physical-request idempotency, and a live validation that the exact
|
|
13
|
+
-- connection is workspace-owned ('workspace' authority scope), belongs to
|
|
14
|
+
-- this workspace, still matches its provider domain and kind, and is active.
|
|
15
|
+
-- The audit-fact shape already admits authority_scope 'workspace' (0264).
|
|
16
|
+
--
|
|
17
|
+
-- A frozen personal snapshot for the same turn+server keeps taking the
|
|
18
|
+
-- snapshot lane, so a workspace-scope request against a personally delegated
|
|
19
|
+
-- server denies with connection_identity_changed instead of borrowing the
|
|
20
|
+
-- workspace row. Requests with no connection id remain unresolvable in this
|
|
21
|
+
-- lane ('connection_missing'): the worker's bounded legacy path for
|
|
22
|
+
-- pre-snapshot turns stays TypeScript-side and unprivileged.
|
|
23
|
+
--
|
|
24
|
+
-- Rolling window: same function identity, so existing EXECUTE grants
|
|
25
|
+
-- survive; an old worker image keeps its short-circuit (exactly as weak as
|
|
26
|
+
-- before, never weaker) until replaced. CREATE OR REPLACE resets the
|
|
27
|
+
-- attached search_path, so the 0275 definer posture is re-applied below.
|
|
28
|
+
|
|
29
|
+
SET LOCAL lock_timeout = '5s';
|
|
30
|
+
SET LOCAL statement_timeout = '5min';
|
|
31
|
+
|
|
32
|
+
CREATE OR REPLACE FUNCTION resolve_accepted_connection_use(
|
|
33
|
+
p_account_id uuid, p_workspace_id uuid, p_session_id uuid, p_turn_id uuid,
|
|
34
|
+
p_attempt_id uuid, p_execution_generation integer, p_physical_request_id uuid,
|
|
35
|
+
p_use_phase text, p_server_id text, p_connection_id uuid,
|
|
36
|
+
p_provider_domain text, p_connection_kind text, p_subject_scope text,
|
|
37
|
+
p_owner_subject_id text DEFAULT NULL
|
|
38
|
+
) RETURNS TABLE (
|
|
39
|
+
authorization_status text, denial_reason text, resolved_connection_id uuid,
|
|
40
|
+
connection_generation bigint, origin_workspace_id uuid,
|
|
41
|
+
resolved_connection_kind text, authority_scope text, owner_subject_id text,
|
|
42
|
+
authority_id uuid, grant_id uuid
|
|
43
|
+
)
|
|
44
|
+
LANGUAGE plpgsql SECURITY DEFINER
|
|
45
|
+
SET search_path = pg_catalog, pg_temp
|
|
46
|
+
AS $body$
|
|
47
|
+
#variable_conflict use_column
|
|
48
|
+
DECLARE
|
|
49
|
+
prior record;
|
|
50
|
+
connection_row record;
|
|
51
|
+
snapshot record;
|
|
52
|
+
session_row record;
|
|
53
|
+
grant_row record;
|
|
54
|
+
request_digest bytea;
|
|
55
|
+
has_prior boolean := false;
|
|
56
|
+
reason text;
|
|
57
|
+
scheduled_run_id uuid;
|
|
58
|
+
BEGIN
|
|
59
|
+
IF p_account_id IS DISTINCT FROM nullif(current_setting('opengeni.account_id', true), '')::uuid
|
|
60
|
+
OR p_workspace_id IS DISTINCT FROM nullif(current_setting('opengeni.workspace_id', true), '')::uuid
|
|
61
|
+
OR p_execution_generation <= 0
|
|
62
|
+
OR p_use_phase NOT IN ('credential_resolution', 'provider_request')
|
|
63
|
+
OR nullif(btrim(p_server_id), '') IS NULL OR octet_length(p_server_id) > 256
|
|
64
|
+
THEN RAISE EXCEPTION 'connection use scope mismatch' USING ERRCODE = '42501';
|
|
65
|
+
END IF;
|
|
66
|
+
request_digest := digest(convert_to(jsonb_build_object(
|
|
67
|
+
'accountId', p_account_id, 'workspaceId', p_workspace_id,
|
|
68
|
+
'sessionId', p_session_id, 'turnId', p_turn_id, 'attemptId', p_attempt_id,
|
|
69
|
+
'executionGeneration', p_execution_generation, 'usePhase', p_use_phase,
|
|
70
|
+
'serverId', p_server_id, 'connectionId', p_connection_id,
|
|
71
|
+
'providerDomain', lower(p_provider_domain), 'connectionKind', p_connection_kind,
|
|
72
|
+
'subjectScope', p_subject_scope, 'ownerSubjectId', p_owner_subject_id
|
|
73
|
+
)::text, 'UTF8'), 'sha256');
|
|
74
|
+
|
|
75
|
+
-- Canonical lifecycle lock prefix: control -> workspace -> session -> turn -> attempt.
|
|
76
|
+
PERFORM 1 FROM workspace_inference_controls control_row
|
|
77
|
+
WHERE control_row.account_id = p_account_id AND control_row.workspace_id = p_workspace_id
|
|
78
|
+
FOR SHARE;
|
|
79
|
+
IF NOT FOUND THEN reason := 'session_identity_changed'; END IF;
|
|
80
|
+
IF reason IS NULL THEN
|
|
81
|
+
PERFORM 1 FROM workspaces workspace_value
|
|
82
|
+
WHERE workspace_value.account_id = p_account_id AND workspace_value.id = p_workspace_id
|
|
83
|
+
FOR KEY SHARE;
|
|
84
|
+
IF NOT FOUND THEN reason := 'session_identity_changed'; END IF;
|
|
85
|
+
END IF;
|
|
86
|
+
IF reason IS NULL THEN
|
|
87
|
+
SELECT session_value.* INTO session_row FROM sessions session_value
|
|
88
|
+
WHERE session_value.id = p_session_id AND session_value.account_id = p_account_id
|
|
89
|
+
AND session_value.workspace_id = p_workspace_id
|
|
90
|
+
FOR NO KEY UPDATE;
|
|
91
|
+
IF NOT FOUND OR session_row.active_turn_id IS DISTINCT FROM p_turn_id
|
|
92
|
+
OR session_row.status = 'cancelled'
|
|
93
|
+
THEN reason := 'session_identity_changed'; END IF;
|
|
94
|
+
END IF;
|
|
95
|
+
IF reason IS NULL THEN
|
|
96
|
+
PERFORM 1 FROM session_turns turn_value
|
|
97
|
+
WHERE turn_value.id = p_turn_id AND turn_value.account_id = p_account_id
|
|
98
|
+
AND turn_value.workspace_id = p_workspace_id AND turn_value.session_id = p_session_id
|
|
99
|
+
AND turn_value.active_attempt_id = p_attempt_id
|
|
100
|
+
AND turn_value.execution_generation = p_execution_generation
|
|
101
|
+
AND turn_value.status = 'running'
|
|
102
|
+
FOR UPDATE;
|
|
103
|
+
IF NOT FOUND THEN reason := 'session_identity_changed'; END IF;
|
|
104
|
+
END IF;
|
|
105
|
+
IF reason IS NULL THEN
|
|
106
|
+
PERFORM 1 FROM session_turn_attempts attempt
|
|
107
|
+
WHERE attempt.id = p_attempt_id AND attempt.account_id = p_account_id
|
|
108
|
+
AND attempt.workspace_id = p_workspace_id AND attempt.session_id = p_session_id
|
|
109
|
+
AND attempt.turn_id = p_turn_id
|
|
110
|
+
AND attempt.execution_generation = p_execution_generation
|
|
111
|
+
AND attempt.state IN ('claimed', 'running')
|
|
112
|
+
AND attempt.closed_at IS NULL AND attempt.quiesced_at IS NULL
|
|
113
|
+
AND attempt.authority_visibility = session_row.visibility
|
|
114
|
+
AND attempt.authority_epoch = session_row.authority_epoch
|
|
115
|
+
AND attempt.authority_owner_organization_membership_id
|
|
116
|
+
IS NOT DISTINCT FROM session_row.owner_organization_membership_id
|
|
117
|
+
FOR UPDATE;
|
|
118
|
+
IF NOT FOUND OR EXISTS (
|
|
119
|
+
SELECT 1 FROM session_attempt_interruptions interruption
|
|
120
|
+
WHERE interruption.account_id = p_account_id
|
|
121
|
+
AND interruption.workspace_id = p_workspace_id
|
|
122
|
+
AND interruption.session_id = p_session_id
|
|
123
|
+
AND interruption.attempt_id = p_attempt_id
|
|
124
|
+
AND interruption.state IN ('pending', 'delivered', 'acknowledged')
|
|
125
|
+
) THEN reason := 'session_identity_changed'; END IF;
|
|
126
|
+
END IF;
|
|
127
|
+
|
|
128
|
+
PERFORM pg_advisory_xact_lock(hashtextextended(p_physical_request_id::text, 0));
|
|
129
|
+
SELECT EXISTS (SELECT 1 FROM connection_use_audit_facts audit
|
|
130
|
+
WHERE audit.physical_request_id = p_physical_request_id) INTO has_prior;
|
|
131
|
+
-- Only dereference `prior` inside the guarded branch: PL/pgSQL evaluates
|
|
132
|
+
-- both operands of `has_prior AND prior.<field>`, and an unassigned record
|
|
133
|
+
-- raises instead of yielding NULL.
|
|
134
|
+
IF has_prior THEN
|
|
135
|
+
SELECT audit.* INTO STRICT prior FROM connection_use_audit_facts audit
|
|
136
|
+
WHERE audit.physical_request_id = p_physical_request_id;
|
|
137
|
+
IF prior.request_digest IS DISTINCT FROM request_digest THEN
|
|
138
|
+
RAISE EXCEPTION 'physical connection request id was reused for different work'
|
|
139
|
+
USING ERRCODE = '23505';
|
|
140
|
+
END IF;
|
|
141
|
+
IF reason IS NULL AND prior.outcome = 'denied' THEN
|
|
142
|
+
authorization_status := prior.outcome; denial_reason := prior.denial_reason;
|
|
143
|
+
RETURN NEXT; RETURN;
|
|
144
|
+
END IF;
|
|
145
|
+
END IF;
|
|
146
|
+
|
|
147
|
+
IF reason IS NULL THEN
|
|
148
|
+
SELECT authority_snapshot.* INTO snapshot
|
|
149
|
+
FROM turn_connection_authority_snapshots authority_snapshot
|
|
150
|
+
WHERE authority_snapshot.turn_id = p_turn_id
|
|
151
|
+
AND authority_snapshot.server_id = p_server_id
|
|
152
|
+
AND authority_snapshot.account_id = p_account_id
|
|
153
|
+
AND authority_snapshot.workspace_id = p_workspace_id
|
|
154
|
+
AND authority_snapshot.session_id = p_session_id;
|
|
155
|
+
IF FOUND THEN
|
|
156
|
+
scheduled_run_id := CASE
|
|
157
|
+
WHEN snapshot.canonical_snapshot -> 'acceptedWork' ->> 'kind' = 'scheduled_task'
|
|
158
|
+
THEN nullif(snapshot.canonical_snapshot -> 'acceptedWork' ->> 'runId', '')::uuid
|
|
159
|
+
ELSE NULL END;
|
|
160
|
+
SELECT connection_value.* INTO connection_row FROM connections connection_value
|
|
161
|
+
WHERE connection_value.id = snapshot.connection_id
|
|
162
|
+
AND connection_value.account_id = p_account_id;
|
|
163
|
+
IF snapshot.snapshot_digest IS DISTINCT FROM digest(
|
|
164
|
+
convert_to(snapshot.canonical_snapshot::text, 'UTF8'), 'sha256'
|
|
165
|
+
) THEN reason := 'accepted_snapshot_digest_changed';
|
|
166
|
+
ELSIF NOT FOUND THEN reason := 'connection_missing';
|
|
167
|
+
ELSIF snapshot.authority_scope IS DISTINCT FROM 'user'
|
|
168
|
+
OR p_subject_scope IS DISTINCT FROM 'subject'
|
|
169
|
+
OR p_connection_id IS DISTINCT FROM snapshot.connection_id
|
|
170
|
+
OR lower(p_provider_domain) IS DISTINCT FROM snapshot.provider_domain
|
|
171
|
+
OR (p_connection_kind IS NOT NULL
|
|
172
|
+
AND p_connection_kind IS DISTINCT FROM snapshot.connection_kind)
|
|
173
|
+
THEN reason := 'connection_identity_changed';
|
|
174
|
+
ELSIF connection_row.status <> 'active' THEN reason := 'connection_status_inactive';
|
|
175
|
+
ELSIF connection_row.authority_scope IS DISTINCT FROM 'user'
|
|
176
|
+
OR connection_row.subject_id IS DISTINCT FROM snapshot.owner_subject_id
|
|
177
|
+
OR connection_row.owner_organization_membership_id
|
|
178
|
+
IS DISTINCT FROM snapshot.owner_organization_membership_id
|
|
179
|
+
OR connection_row.origin_workspace_id IS DISTINCT FROM snapshot.origin_workspace_id
|
|
180
|
+
THEN reason := 'connection_owner_changed';
|
|
181
|
+
ELSIF connection_row.authority_generation IS DISTINCT FROM snapshot.connection_generation
|
|
182
|
+
THEN reason := 'connection_generation_changed';
|
|
183
|
+
ELSIF session_row.visibility IS DISTINCT FROM snapshot.session_visibility
|
|
184
|
+
OR session_row.authority_epoch IS DISTINCT FROM snapshot.session_authority_epoch
|
|
185
|
+
THEN reason := 'session_authority_epoch_changed';
|
|
186
|
+
ELSIF NOT EXISTS (
|
|
187
|
+
SELECT 1 FROM organization_memberships membership
|
|
188
|
+
WHERE membership.id = snapshot.owner_organization_membership_id
|
|
189
|
+
AND membership.account_id = p_account_id
|
|
190
|
+
AND membership.subject_id = snapshot.owner_subject_id
|
|
191
|
+
AND membership.status = 'active' AND membership.revoked_at IS NULL
|
|
192
|
+
AND membership.authorization_revision = snapshot.membership_authorization_revision
|
|
193
|
+
AND (membership.personal_workspace_id = p_workspace_id OR EXISTS (
|
|
194
|
+
SELECT 1 FROM workspace_memberships workspace_membership
|
|
195
|
+
WHERE workspace_membership.account_id = p_account_id
|
|
196
|
+
AND workspace_membership.workspace_id = p_workspace_id
|
|
197
|
+
AND workspace_membership.subject_id = snapshot.owner_subject_id
|
|
198
|
+
))
|
|
199
|
+
) THEN reason := 'owner_membership_inactive';
|
|
200
|
+
ELSIF NOT EXISTS (
|
|
201
|
+
SELECT 1 FROM organization_user_resource_authorities authority
|
|
202
|
+
WHERE authority.id = snapshot.authority_id AND authority.account_id = p_account_id
|
|
203
|
+
AND authority.organization_membership_id = snapshot.owner_organization_membership_id
|
|
204
|
+
AND authority.resource_kind = 'connection'
|
|
205
|
+
AND authority.resource_id = snapshot.connection_id
|
|
206
|
+
AND authority.origin_workspace_id = snapshot.origin_workspace_id
|
|
207
|
+
AND authority.generation = snapshot.authority_generation
|
|
208
|
+
AND authority.status = 'active' AND authority.revoked_at IS NULL
|
|
209
|
+
) THEN reason := 'authority_status_inactive';
|
|
210
|
+
ELSE
|
|
211
|
+
SELECT grant_value.* INTO grant_row FROM organization_user_resource_grants grant_value
|
|
212
|
+
WHERE grant_value.id = snapshot.grant_id AND grant_value.account_id = p_account_id
|
|
213
|
+
FOR UPDATE;
|
|
214
|
+
IF NOT FOUND THEN reason := 'grant_missing';
|
|
215
|
+
ELSIF grant_row.authority_id IS DISTINCT FROM snapshot.authority_id
|
|
216
|
+
OR grant_row.owner_organization_membership_id
|
|
217
|
+
IS DISTINCT FROM snapshot.owner_organization_membership_id
|
|
218
|
+
OR grant_row.workspace_id IS DISTINCT FROM p_workspace_id
|
|
219
|
+
OR grant_row.action <> 'connection.use'
|
|
220
|
+
OR grant_row.mode IS DISTINCT FROM snapshot.grant_mode
|
|
221
|
+
OR grant_row.context IS DISTINCT FROM snapshot.grant_context
|
|
222
|
+
OR grant_row.session_id IS DISTINCT FROM snapshot.grant_session_id
|
|
223
|
+
OR grant_row.authority_epoch IS DISTINCT FROM snapshot.grant_authority_epoch
|
|
224
|
+
THEN reason := 'grant_identity_changed';
|
|
225
|
+
ELSIF grant_row.generation IS DISTINCT FROM snapshot.grant_generation
|
|
226
|
+
THEN reason := 'grant_generation_changed';
|
|
227
|
+
ELSIF grant_row.expires_at IS NOT NULL AND grant_row.expires_at <= clock_timestamp()
|
|
228
|
+
THEN reason := 'grant_expired';
|
|
229
|
+
ELSIF grant_row.mode = 'once' THEN
|
|
230
|
+
IF grant_row.status <> 'consumed' OR NOT EXISTS (
|
|
231
|
+
SELECT 1 FROM connection_use_once_consumption_receipts receipt
|
|
232
|
+
WHERE receipt.grant_id = grant_row.id
|
|
233
|
+
AND receipt.authority_id = snapshot.authority_id
|
|
234
|
+
AND receipt.authority_generation = snapshot.authority_generation
|
|
235
|
+
AND receipt.grant_generation = snapshot.grant_generation
|
|
236
|
+
AND (
|
|
237
|
+
(receipt.accepted_work_kind = 'turn'
|
|
238
|
+
AND receipt.accepted_work_id = p_turn_id)
|
|
239
|
+
OR (receipt.accepted_work_kind = 'scheduled_task'
|
|
240
|
+
AND scheduled_run_id IS NOT NULL
|
|
241
|
+
AND receipt.accepted_work_id = scheduled_run_id)
|
|
242
|
+
)
|
|
243
|
+
) THEN reason := 'grant_already_consumed'; END IF;
|
|
244
|
+
ELSIF grant_row.status <> 'active' THEN reason := 'grant_status_inactive';
|
|
245
|
+
END IF;
|
|
246
|
+
END IF;
|
|
247
|
+
resolved_connection_id := snapshot.connection_id;
|
|
248
|
+
connection_generation := snapshot.connection_generation;
|
|
249
|
+
origin_workspace_id := snapshot.origin_workspace_id;
|
|
250
|
+
resolved_connection_kind := snapshot.connection_kind;
|
|
251
|
+
authority_scope := snapshot.authority_scope;
|
|
252
|
+
owner_subject_id := snapshot.owner_subject_id;
|
|
253
|
+
authority_id := snapshot.authority_id;
|
|
254
|
+
grant_id := snapshot.grant_id;
|
|
255
|
+
ELSIF p_subject_scope = 'workspace' THEN
|
|
256
|
+
-- Workspace lane (0279): a workspace-owned connection is ambient shared
|
|
257
|
+
-- workspace capability, never frozen on the turn, so it is validated
|
|
258
|
+
-- against the live row inside the same canonical lifecycle fences and
|
|
259
|
+
-- recorded in the same idempotent audit facts. A frozen per-turn
|
|
260
|
+
-- personal snapshot for this server takes the snapshot lane above and
|
|
261
|
+
-- therefore denies a workspace-scope request outright (fail closed).
|
|
262
|
+
SELECT connection_value.* INTO connection_row FROM connections connection_value
|
|
263
|
+
WHERE connection_value.id = p_connection_id AND connection_value.account_id = p_account_id;
|
|
264
|
+
IF p_connection_id IS NULL OR NOT FOUND THEN reason := 'connection_missing';
|
|
265
|
+
ELSIF connection_row.authority_scope IS DISTINCT FROM 'workspace'
|
|
266
|
+
OR p_owner_subject_id IS NOT NULL
|
|
267
|
+
OR connection_row.workspace_id IS DISTINCT FROM p_workspace_id
|
|
268
|
+
OR connection_row.origin_workspace_id IS DISTINCT FROM p_workspace_id
|
|
269
|
+
OR lower(connection_row.provider_domain) IS DISTINCT FROM lower(p_provider_domain)
|
|
270
|
+
OR (p_connection_kind IS NOT NULL
|
|
271
|
+
AND connection_row.kind IS DISTINCT FROM p_connection_kind)
|
|
272
|
+
THEN reason := 'connection_identity_changed';
|
|
273
|
+
ELSIF connection_row.status <> 'active' THEN reason := 'connection_status_inactive';
|
|
274
|
+
ELSE
|
|
275
|
+
resolved_connection_id := connection_row.id;
|
|
276
|
+
connection_generation := connection_row.authority_generation;
|
|
277
|
+
origin_workspace_id := connection_row.origin_workspace_id;
|
|
278
|
+
resolved_connection_kind := connection_row.kind;
|
|
279
|
+
authority_scope := 'workspace';
|
|
280
|
+
END IF;
|
|
281
|
+
ELSE
|
|
282
|
+
SELECT connection_value.* INTO connection_row FROM connections connection_value
|
|
283
|
+
WHERE connection_value.id = p_connection_id AND connection_value.account_id = p_account_id;
|
|
284
|
+
IF NOT FOUND THEN reason := 'connection_missing';
|
|
285
|
+
ELSIF connection_row.authority_scope IS DISTINCT FROM 'legacy_user'
|
|
286
|
+
OR p_subject_scope IS DISTINCT FROM 'subject' OR p_owner_subject_id IS NULL
|
|
287
|
+
OR connection_row.subject_id IS DISTINCT FROM p_owner_subject_id
|
|
288
|
+
OR connection_row.workspace_id IS DISTINCT FROM p_workspace_id
|
|
289
|
+
OR connection_row.origin_workspace_id IS DISTINCT FROM p_workspace_id
|
|
290
|
+
OR lower(connection_row.provider_domain) IS DISTINCT FROM lower(p_provider_domain)
|
|
291
|
+
OR (p_connection_kind IS NOT NULL
|
|
292
|
+
AND connection_row.kind IS DISTINCT FROM p_connection_kind)
|
|
293
|
+
THEN reason := 'connection_identity_changed';
|
|
294
|
+
ELSIF connection_row.status <> 'active' THEN reason := 'connection_status_inactive';
|
|
295
|
+
ELSE
|
|
296
|
+
resolved_connection_id := connection_row.id;
|
|
297
|
+
connection_generation := connection_row.authority_generation;
|
|
298
|
+
origin_workspace_id := connection_row.origin_workspace_id;
|
|
299
|
+
resolved_connection_kind := connection_row.kind;
|
|
300
|
+
authority_scope := 'legacy_user'; owner_subject_id := connection_row.subject_id;
|
|
301
|
+
END IF;
|
|
302
|
+
END IF;
|
|
303
|
+
END IF;
|
|
304
|
+
|
|
305
|
+
authorization_status := CASE WHEN reason IS NULL THEN 'authorized' ELSE 'denied' END;
|
|
306
|
+
denial_reason := reason;
|
|
307
|
+
IF NOT has_prior THEN
|
|
308
|
+
INSERT INTO connection_use_audit_facts (
|
|
309
|
+
physical_request_id, use_phase, request_digest, account_id, workspace_id,
|
|
310
|
+
session_id, turn_id, attempt_id, execution_generation, server_id,
|
|
311
|
+
connection_id, connection_generation, authority_scope, owner_subject_id,
|
|
312
|
+
authority_id, grant_id, outcome, denial_reason
|
|
313
|
+
) VALUES (
|
|
314
|
+
p_physical_request_id, p_use_phase, request_digest, p_account_id,
|
|
315
|
+
p_workspace_id, p_session_id, p_turn_id, p_attempt_id,
|
|
316
|
+
p_execution_generation, p_server_id, resolved_connection_id,
|
|
317
|
+
connection_generation, authority_scope, owner_subject_id, authority_id,
|
|
318
|
+
grant_id, authorization_status, denial_reason
|
|
319
|
+
) ON CONFLICT (physical_request_id) DO NOTHING;
|
|
320
|
+
END IF;
|
|
321
|
+
RETURN NEXT;
|
|
322
|
+
END
|
|
323
|
+
$body$;
|
|
324
|
+
|
|
325
|
+
DO $workspace_connection_lane_posture$
|
|
326
|
+
DECLARE
|
|
327
|
+
data_schema text := pg_catalog.current_schema();
|
|
328
|
+
signature text := 'resolve_accepted_connection_use'
|
|
329
|
+
|| '(uuid,uuid,uuid,uuid,uuid,integer,uuid,text,text,uuid,text,text,text,text)';
|
|
330
|
+
BEGIN
|
|
331
|
+
-- Re-pin the 0275 definer posture: CREATE OR REPLACE replaced the attached
|
|
332
|
+
-- search_path with the minimal header value. `public` stays in the path for
|
|
333
|
+
-- the pgcrypto digest() dependency, exactly as 0275 set it.
|
|
334
|
+
EXECUTE format(
|
|
335
|
+
'ALTER FUNCTION %I.%s SET search_path = pg_catalog, %I, public, pg_temp',
|
|
336
|
+
data_schema, signature, data_schema
|
|
337
|
+
);
|
|
338
|
+
EXECUTE format('REVOKE ALL ON FUNCTION %I.%s FROM PUBLIC', data_schema, signature);
|
|
339
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
340
|
+
EXECUTE format('GRANT EXECUTE ON FUNCTION %I.%s TO opengeni_app', data_schema, signature);
|
|
341
|
+
END IF;
|
|
342
|
+
END
|
|
343
|
+
$workspace_connection_lane_posture$;
|