@opengeni/db 1.0.1 → 3.2.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-4SR4HKKA.js → chunk-2EH4WRHL.js} +19 -11
- package/dist/chunk-2EH4WRHL.js.map +1 -0
- package/dist/{chunk-CUPM3FGB.js → chunk-2PRS4J5Q.js} +3 -3
- package/dist/chunk-6HMM2R5T.js +390 -0
- package/dist/chunk-6HMM2R5T.js.map +1 -0
- package/dist/{chunk-ZWREYEWA.js → chunk-AZHW7R5V.js} +56 -11
- package/dist/chunk-AZHW7R5V.js.map +1 -0
- package/dist/{chunk-LTG3S6ZY.js → chunk-E6CLMKEE.js} +2 -2
- package/dist/{chunk-6ZYKCRFO.js → chunk-KRLPEMLH.js} +7591 -4417
- package/dist/chunk-KRLPEMLH.js.map +1 -0
- package/dist/chunk-NAB6FKFN.js +516 -0
- package/dist/chunk-NAB6FKFN.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-UZNXG44K.js +4508 -0
- package/dist/chunk-UZNXG44K.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 +85 -0
- package/dist/connection-token-resolver.d.ts +30 -1
- package/dist/database.d.ts +23 -4
- 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 +1606 -81
- package/dist/index.js +21898 -8147
- 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 +29 -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 +43 -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 +268 -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 +28 -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/drizzle/0342_slack_route_prompt_single_pending.sql +32 -0
- package/drizzle/0343_personal_document_force_rls_lock_repair.sql +146 -0
- package/drizzle/0344_private_session_visibility_transition_gate.sql +85 -0
- package/drizzle/0345_tenant_scoped_session_tenancy_fence.sql +2839 -0
- package/drizzle/0346_document_migration_audit_surface.sql +454 -0
- package/drizzle/0347_connection_authority_convergence_evidence.sql +396 -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 +167 -0
- package/src/connection-token-resolver.ts +263 -31
- package/src/database.ts +87 -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 +11676 -1550
- 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 +995 -0
- package/src/pr-review.ts +890 -0
- package/src/preference-registry.ts +31 -1
- package/src/provision-roles.ts +905 -6
- package/src/runtime-posture-cli.ts +2 -0
- package/src/runtime-posture.ts +1317 -72
- package/src/schema.ts +3316 -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 +441 -85
- package/src/session-realtime-context.ts +4 -6
- package/src/session-realtime-ledger.ts +28 -14
- package/src/session-realtime-mirror.ts +1 -1
- package/src/session-tenancy.ts +410 -49
- package/src/session-tool-call-settlement.ts +38 -29
- package/src/slack-routing-personal-workspace.ts +67 -0
- package/src/slack-routing.ts +867 -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 +138 -11
- 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-CUPM3FGB.js.map → chunk-2PRS4J5Q.js.map} +0 -0
- /package/dist/{chunk-LTG3S6ZY.js.map → chunk-E6CLMKEE.js.map} +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Two things per-channel Slack routing needs from storage once the routed
|
|
3
|
+
-- workspace and the installation's workspace can actually differ.
|
|
4
|
+
--
|
|
5
|
+
-- 1. A Slack button click arrives on an inbox row that carries HOME tenancy and
|
|
6
|
+
-- names one action handle by id. The handle lives in the workspace that owns
|
|
7
|
+
-- its session, which is TARGET, and its RESTRICTIVE session-visibility policy
|
|
8
|
+
-- resolves the session under the handle's own scope. Without a way to learn
|
|
9
|
+
-- that scope from the id, every routed Status/Stop/Approve click reads under
|
|
10
|
+
-- HOME, finds nothing, and is refused as an invalid handle.
|
|
11
|
+
--
|
|
12
|
+
-- 2. `slack_shared_task_origins` carries TWO composite foreign keys on the SAME
|
|
13
|
+
-- (account_id, workspace_id) pair: one to `slack_interactions` and one to
|
|
14
|
+
-- `slack_task_policy_revisions`. The interaction is TARGET and the Slack task
|
|
15
|
+
-- policy stays HOME by explicit decision, because it governs what may be read
|
|
16
|
+
-- out of the Slack conversation rather than who the task belongs to. Once the
|
|
17
|
+
-- two differ, no value of that pair satisfies both constraints and every
|
|
18
|
+
-- private-handoff task in a routed workspace fails at insert.
|
|
19
|
+
--
|
|
20
|
+
-- Rolling: the probe is additive, and the shared-task-origin columns are
|
|
21
|
+
-- nullable with the existing rows backfilled to their own tenancy, so an old
|
|
22
|
+
-- image that writes neither column keeps working exactly as it does today.
|
|
23
|
+
|
|
24
|
+
SET LOCAL lock_timeout = '5s';
|
|
25
|
+
SET LOCAL statement_timeout = '10min';
|
|
26
|
+
|
|
27
|
+
-- `slack_interaction_action_handles` carries a RESTRICTIVE
|
|
28
|
+
-- `session_visibility_isolation` policy whose helper resolves the handle's
|
|
29
|
+
-- session under the CURRENT scope. A permissive policy cannot open that: a
|
|
30
|
+
-- restrictive policy is ANDed, and weakening it would weaken session visibility
|
|
31
|
+
-- itself. So the tenancy is not read out of the handle table at all. A private,
|
|
32
|
+
-- ids-only mapping is maintained by a trigger on the handle table and lives in
|
|
33
|
+
-- `opengeni_private`, where the runtime role has no privileges and the definer
|
|
34
|
+
-- probe is the only reader.
|
|
35
|
+
--
|
|
36
|
+
-- Content-free by construction: handle id, connection id, and the tenancy pair.
|
|
37
|
+
-- No action kind, no target value, no subject, no session content. The caller
|
|
38
|
+
-- must still re-read the full handle under the returned tenancy's own RLS, which
|
|
39
|
+
-- is where every existing authorization check already lives.
|
|
40
|
+
CREATE TABLE opengeni_private.slack_action_handle_tenancy (
|
|
41
|
+
"handle_id" uuid PRIMARY KEY,
|
|
42
|
+
"connection_id" uuid NOT NULL,
|
|
43
|
+
"account_id" uuid NOT NULL,
|
|
44
|
+
"workspace_id" uuid NOT NULL
|
|
45
|
+
);
|
|
46
|
+
REVOKE ALL ON TABLE opengeni_private.slack_action_handle_tenancy FROM PUBLIC;
|
|
47
|
+
|
|
48
|
+
CREATE FUNCTION opengeni_private.sync_slack_action_handle_tenancy()
|
|
49
|
+
RETURNS trigger
|
|
50
|
+
LANGUAGE plpgsql
|
|
51
|
+
SECURITY DEFINER
|
|
52
|
+
SET search_path = pg_catalog
|
|
53
|
+
AS $$
|
|
54
|
+
BEGIN
|
|
55
|
+
IF TG_OP = 'DELETE' THEN
|
|
56
|
+
DELETE FROM opengeni_private.slack_action_handle_tenancy
|
|
57
|
+
WHERE handle_id = OLD.id;
|
|
58
|
+
RETURN OLD;
|
|
59
|
+
END IF;
|
|
60
|
+
INSERT INTO opengeni_private.slack_action_handle_tenancy (
|
|
61
|
+
handle_id, connection_id, account_id, workspace_id
|
|
62
|
+
) VALUES (NEW.id, NEW.connection_id, NEW.account_id, NEW.workspace_id)
|
|
63
|
+
ON CONFLICT (handle_id) DO UPDATE
|
|
64
|
+
SET connection_id = EXCLUDED.connection_id,
|
|
65
|
+
account_id = EXCLUDED.account_id,
|
|
66
|
+
workspace_id = EXCLUDED.workspace_id;
|
|
67
|
+
RETURN NEW;
|
|
68
|
+
END
|
|
69
|
+
$$;
|
|
70
|
+
REVOKE ALL ON FUNCTION opengeni_private.sync_slack_action_handle_tenancy() FROM PUBLIC;
|
|
71
|
+
|
|
72
|
+
DO $slack_handle_trigger$
|
|
73
|
+
DECLARE data_schema text := current_schema();
|
|
74
|
+
BEGIN
|
|
75
|
+
EXECUTE format(
|
|
76
|
+
'CREATE TRIGGER slack_action_handle_tenancy_sync
|
|
77
|
+
AFTER INSERT OR UPDATE OF account_id, workspace_id, connection_id OR DELETE
|
|
78
|
+
ON %I.slack_interaction_action_handles
|
|
79
|
+
FOR EACH ROW EXECUTE FUNCTION opengeni_private.sync_slack_action_handle_tenancy()',
|
|
80
|
+
data_schema
|
|
81
|
+
);
|
|
82
|
+
END
|
|
83
|
+
$slack_handle_trigger$;
|
|
84
|
+
|
|
85
|
+
-- FORCE ROW LEVEL SECURITY binds the table owner and no tenant GUC is set during
|
|
86
|
+
-- a migration, so reading the existing handles needs the owner-only posture
|
|
87
|
+
-- window. The app role stays policy-bound throughout.
|
|
88
|
+
ALTER TABLE "slack_interaction_action_handles" NO FORCE ROW LEVEL SECURITY;
|
|
89
|
+
|
|
90
|
+
INSERT INTO opengeni_private.slack_action_handle_tenancy (
|
|
91
|
+
handle_id, connection_id, account_id, workspace_id
|
|
92
|
+
)
|
|
93
|
+
SELECT H.id, H.connection_id, H.account_id, H.workspace_id
|
|
94
|
+
FROM "slack_interaction_action_handles" H
|
|
95
|
+
ON CONFLICT (handle_id) DO NOTHING;
|
|
96
|
+
|
|
97
|
+
ALTER TABLE "slack_interaction_action_handles" FORCE ROW LEVEL SECURITY;
|
|
98
|
+
|
|
99
|
+
DO $slack_handle_probe$
|
|
100
|
+
BEGIN
|
|
101
|
+
EXECUTE $ddl$
|
|
102
|
+
CREATE FUNCTION opengeni_private.resolve_slack_action_handle_tenancy(
|
|
103
|
+
p_connection_id uuid,
|
|
104
|
+
p_handle_id uuid
|
|
105
|
+
)
|
|
106
|
+
RETURNS TABLE (account_id uuid, workspace_id uuid)
|
|
107
|
+
LANGUAGE sql
|
|
108
|
+
STABLE
|
|
109
|
+
SECURITY DEFINER
|
|
110
|
+
SET search_path = opengeni_private, pg_catalog
|
|
111
|
+
AS $function$
|
|
112
|
+
SELECT T.account_id, T.workspace_id
|
|
113
|
+
FROM slack_action_handle_tenancy T
|
|
114
|
+
WHERE T.handle_id = p_handle_id
|
|
115
|
+
AND T.connection_id = p_connection_id
|
|
116
|
+
LIMIT 1
|
|
117
|
+
$function$
|
|
118
|
+
$ddl$;
|
|
119
|
+
END
|
|
120
|
+
$slack_handle_probe$;
|
|
121
|
+
|
|
122
|
+
REVOKE ALL ON FUNCTION opengeni_private.resolve_slack_action_handle_tenancy(uuid, uuid)
|
|
123
|
+
FROM PUBLIC;
|
|
124
|
+
|
|
125
|
+
-- The Slack task policy revision this origin froze is a HOME fact. Give it its
|
|
126
|
+
-- own tenancy pair so the row's own (account_id, workspace_id) stays free to be
|
|
127
|
+
-- the interaction's.
|
|
128
|
+
ALTER TABLE "slack_shared_task_origins"
|
|
129
|
+
ADD COLUMN "policy_account_id" uuid,
|
|
130
|
+
ADD COLUMN "policy_workspace_id" uuid;
|
|
131
|
+
|
|
132
|
+
-- Two owner-bound guards stand between this backfill and the rows it must reach.
|
|
133
|
+
--
|
|
134
|
+
-- FORCE ROW LEVEL SECURITY binds the table owner and no tenant GUC is set during
|
|
135
|
+
-- a migration, so a bare UPDATE would match ZERO rows and report success.
|
|
136
|
+
--
|
|
137
|
+
-- `slack_shared_task_origins_immutable` is an unconditional BEFORE UPDATE OR
|
|
138
|
+
-- DELETE trigger, so the same UPDATE would instead RAISE and abort this whole
|
|
139
|
+
-- migration on any deployment that has ever recorded one shared-task origin.
|
|
140
|
+
--
|
|
141
|
+
-- Relax both for exactly this statement. The value written is the one each row
|
|
142
|
+
-- already implied - before routing, the policy revision was always frozen in the
|
|
143
|
+
-- row's own workspace - so no evidence changes meaning. The app role stays
|
|
144
|
+
-- policy-bound and the immutability guard is restored immediately.
|
|
145
|
+
ALTER TABLE "slack_shared_task_origins" NO FORCE ROW LEVEL SECURITY;
|
|
146
|
+
ALTER TABLE "slack_shared_task_origins" DISABLE TRIGGER "slack_shared_task_origins_immutable";
|
|
147
|
+
|
|
148
|
+
UPDATE "slack_shared_task_origins"
|
|
149
|
+
SET "policy_account_id" = "account_id",
|
|
150
|
+
"policy_workspace_id" = "workspace_id"
|
|
151
|
+
WHERE "policy_account_id" IS NULL;
|
|
152
|
+
|
|
153
|
+
ALTER TABLE "slack_shared_task_origins" ENABLE TRIGGER "slack_shared_task_origins_immutable";
|
|
154
|
+
ALTER TABLE "slack_shared_task_origins" FORCE ROW LEVEL SECURITY;
|
|
155
|
+
|
|
156
|
+
ALTER TABLE "slack_shared_task_origins"
|
|
157
|
+
DROP CONSTRAINT "slack_shared_task_origins_policy_fk";
|
|
158
|
+
|
|
159
|
+
ALTER TABLE "slack_shared_task_origins"
|
|
160
|
+
ADD CONSTRAINT "slack_shared_task_origins_policy_home_fk"
|
|
161
|
+
FOREIGN KEY ("policy_account_id", "policy_workspace_id", "policy_revision_id")
|
|
162
|
+
REFERENCES "slack_task_policy_revisions"("account_id", "workspace_id", "id")
|
|
163
|
+
ON DELETE RESTRICT NOT VALID;
|
|
164
|
+
|
|
165
|
+
ALTER TABLE "slack_shared_task_origins"
|
|
166
|
+
VALIDATE CONSTRAINT "slack_shared_task_origins_policy_home_fk";
|
|
167
|
+
|
|
168
|
+
ALTER TABLE "slack_shared_task_origins"
|
|
169
|
+
ADD CONSTRAINT "slack_shared_task_origins_policy_home_chk"
|
|
170
|
+
CHECK (("policy_account_id" IS NULL) = ("policy_workspace_id" IS NULL)) NOT VALID;
|
|
171
|
+
|
|
172
|
+
ALTER TABLE "slack_shared_task_origins"
|
|
173
|
+
VALIDATE CONSTRAINT "slack_shared_task_origins_policy_home_chk";
|
|
174
|
+
|
|
175
|
+
DO $grants$
|
|
176
|
+
BEGIN
|
|
177
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
178
|
+
GRANT EXECUTE ON FUNCTION
|
|
179
|
+
opengeni_private.resolve_slack_action_handle_tenancy(uuid, uuid) TO opengeni_app;
|
|
180
|
+
REVOKE ALL ON TABLE opengeni_private.slack_action_handle_tenancy FROM opengeni_app;
|
|
181
|
+
END IF;
|
|
182
|
+
END
|
|
183
|
+
$grants$;
|
|
184
|
+
|
|
185
|
+
COMMENT ON COLUMN "slack_shared_task_origins"."policy_workspace_id" IS
|
|
186
|
+
'Home tenancy of the frozen Slack task policy revision; null on rows written before Slack workspace routing.';
|
|
187
|
+
|
|
188
|
+
RESET statement_timeout;
|
|
189
|
+
RESET lock_timeout;
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
-- deployment-mode: maintenance
|
|
2
|
+
-- Extend accepted-turn personal-resource attachments to the selected user-owned
|
|
3
|
+
-- Connected Machine. The attachment summary and protocol-v1 attempt snapshot
|
|
4
|
+
-- now admit a third resource kind, so every API/control/turn worker must be
|
|
5
|
+
-- stopped before this cutover and no pre-0338 worker may restart afterwards.
|
|
6
|
+
|
|
7
|
+
SET LOCAL lock_timeout = '5s';
|
|
8
|
+
SET LOCAL statement_timeout = '10min';
|
|
9
|
+
|
|
10
|
+
DO $atomic_connected_machine_writer_drain_before_lock$
|
|
11
|
+
DECLARE
|
|
12
|
+
configured_roles_text text := nullif(
|
|
13
|
+
current_setting('opengeni.migration_application_roles', true), ''
|
|
14
|
+
);
|
|
15
|
+
configured_roles jsonb;
|
|
16
|
+
BEGIN
|
|
17
|
+
IF configured_roles_text IS NULL THEN
|
|
18
|
+
RAISE EXCEPTION
|
|
19
|
+
'0338 atomic Connected Machine attachment requires an explicit application database role list'
|
|
20
|
+
USING ERRCODE = '55000';
|
|
21
|
+
END IF;
|
|
22
|
+
BEGIN
|
|
23
|
+
configured_roles := configured_roles_text::jsonb;
|
|
24
|
+
EXCEPTION WHEN OTHERS THEN
|
|
25
|
+
RAISE EXCEPTION
|
|
26
|
+
'0338 atomic Connected Machine attachment received a malformed application database role list'
|
|
27
|
+
USING ERRCODE = '55000';
|
|
28
|
+
END;
|
|
29
|
+
IF jsonb_typeof(configured_roles) <> 'array'
|
|
30
|
+
OR jsonb_array_length(configured_roles) NOT BETWEEN 1 AND 16
|
|
31
|
+
OR EXISTS (
|
|
32
|
+
SELECT 1 FROM jsonb_array_elements(configured_roles) AS roles(value)
|
|
33
|
+
WHERE jsonb_typeof(value) <> 'string'
|
|
34
|
+
OR btrim(value #>> '{}') = ''
|
|
35
|
+
OR octet_length(value #>> '{}') > 63
|
|
36
|
+
)
|
|
37
|
+
OR (
|
|
38
|
+
SELECT count(*) FROM jsonb_array_elements_text(configured_roles)
|
|
39
|
+
) <> (
|
|
40
|
+
SELECT count(DISTINCT value)
|
|
41
|
+
FROM jsonb_array_elements_text(configured_roles) AS roles(value)
|
|
42
|
+
)
|
|
43
|
+
THEN
|
|
44
|
+
RAISE EXCEPTION
|
|
45
|
+
'0338 atomic Connected Machine attachment received an invalid application database role list'
|
|
46
|
+
USING ERRCODE = '55000';
|
|
47
|
+
END IF;
|
|
48
|
+
IF EXISTS (
|
|
49
|
+
SELECT 1 FROM pg_stat_activity activity
|
|
50
|
+
JOIN jsonb_array_elements_text(configured_roles) roles(role_name)
|
|
51
|
+
ON roles.role_name = activity.usename
|
|
52
|
+
WHERE activity.datname = current_database()
|
|
53
|
+
AND activity.pid <> pg_backend_pid()
|
|
54
|
+
)
|
|
55
|
+
THEN
|
|
56
|
+
RAISE EXCEPTION
|
|
57
|
+
'0338 atomic Connected Machine attachment requires all configured OpenGeni application database sessions to be stopped'
|
|
58
|
+
USING ERRCODE = '55000';
|
|
59
|
+
END IF;
|
|
60
|
+
END
|
|
61
|
+
$atomic_connected_machine_writer_drain_before_lock$;
|
|
62
|
+
|
|
63
|
+
LOCK TABLE sessions IN ACCESS EXCLUSIVE MODE;
|
|
64
|
+
LOCK TABLE session_turns IN ACCESS EXCLUSIVE MODE;
|
|
65
|
+
LOCK TABLE session_turn_attempts IN ACCESS EXCLUSIVE MODE;
|
|
66
|
+
LOCK TABLE turn_personal_resource_attachment_receipts IN ACCESS EXCLUSIVE MODE;
|
|
67
|
+
LOCK TABLE turn_personal_resource_snapshots IN ACCESS EXCLUSIVE MODE;
|
|
68
|
+
LOCK TABLE session_attempt_personal_resource_snapshots IN ACCESS EXCLUSIVE MODE;
|
|
69
|
+
LOCK TABLE enrollments IN ACCESS EXCLUSIVE MODE;
|
|
70
|
+
LOCK TABLE sandboxes IN ACCESS EXCLUSIVE MODE;
|
|
71
|
+
|
|
72
|
+
DO $atomic_connected_machine_writer_drain_after_lock$
|
|
73
|
+
DECLARE
|
|
74
|
+
configured_roles jsonb := current_setting(
|
|
75
|
+
'opengeni.migration_application_roles', false
|
|
76
|
+
)::jsonb;
|
|
77
|
+
BEGIN
|
|
78
|
+
IF EXISTS (
|
|
79
|
+
SELECT 1 FROM pg_stat_activity activity
|
|
80
|
+
JOIN jsonb_array_elements_text(configured_roles) roles(role_name)
|
|
81
|
+
ON roles.role_name = activity.usename
|
|
82
|
+
WHERE activity.datname = current_database()
|
|
83
|
+
AND activity.pid <> pg_backend_pid()
|
|
84
|
+
)
|
|
85
|
+
THEN
|
|
86
|
+
RAISE EXCEPTION
|
|
87
|
+
'0338 atomic Connected Machine attachment requires all configured OpenGeni application database sessions to be stopped'
|
|
88
|
+
USING ERRCODE = '55000';
|
|
89
|
+
END IF;
|
|
90
|
+
END
|
|
91
|
+
$atomic_connected_machine_writer_drain_after_lock$;
|
|
92
|
+
|
|
93
|
+
ALTER TABLE turn_personal_resource_attachment_receipts
|
|
94
|
+
DROP CONSTRAINT turn_personal_resource_attachment_receipts_identity_chk;
|
|
95
|
+
ALTER TABLE turn_personal_resource_attachment_receipts
|
|
96
|
+
ADD CONSTRAINT turn_personal_resource_attachment_receipts_identity_chk CHECK (
|
|
97
|
+
octet_length(initiating_human_subject_id) BETWEEN 1 AND 512
|
|
98
|
+
AND membership_authorization_revision > 0
|
|
99
|
+
AND session_authority_epoch > 0
|
|
100
|
+
AND grant_mode IN ('once', 'session', 'always')
|
|
101
|
+
AND session_visibility IN ('user_private', 'workspace_shared')
|
|
102
|
+
AND shared_output_warning_version = 1
|
|
103
|
+
AND resource_count BETWEEN 1 AND 28
|
|
104
|
+
AND (session_visibility <> 'workspace_shared' OR shared_output_acknowledged IS TRUE)
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
ALTER TABLE turn_personal_resource_snapshots
|
|
108
|
+
DROP CONSTRAINT turn_personal_resource_snapshots_kind_chk;
|
|
109
|
+
ALTER TABLE turn_personal_resource_snapshots
|
|
110
|
+
ADD CONSTRAINT turn_personal_resource_snapshots_kind_chk CHECK (
|
|
111
|
+
(resource_kind = 'variable_set' AND action = 'variable_set.use'
|
|
112
|
+
AND resource_version_id IS NULL)
|
|
113
|
+
OR (resource_kind = 'rig' AND action = 'rig.use'
|
|
114
|
+
AND resource_version_id IS NOT NULL)
|
|
115
|
+
OR (resource_kind = 'connected_machine' AND action = 'connected_machine.use'
|
|
116
|
+
AND resource_version_id IS NULL)
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
ALTER TABLE session_attempt_personal_resource_snapshots
|
|
120
|
+
DROP CONSTRAINT session_attempt_personal_resource_snapshots_kind_chk;
|
|
121
|
+
ALTER TABLE session_attempt_personal_resource_snapshots
|
|
122
|
+
ADD CONSTRAINT session_attempt_personal_resource_snapshots_kind_chk CHECK (
|
|
123
|
+
(resource_kind = 'variable_set' AND resource_version_id IS NULL)
|
|
124
|
+
OR (resource_kind = 'rig' AND resource_version_id IS NOT NULL)
|
|
125
|
+
OR (resource_kind = 'connected_machine' AND resource_version_id IS NULL)
|
|
126
|
+
);
|
|
127
|
+
ALTER TABLE session_attempt_personal_resource_snapshots
|
|
128
|
+
DROP CONSTRAINT session_attempt_personal_resource_snapshots_action_chk;
|
|
129
|
+
ALTER TABLE session_attempt_personal_resource_snapshots
|
|
130
|
+
ADD CONSTRAINT session_attempt_personal_resource_snapshots_action_chk CHECK (
|
|
131
|
+
(resource_kind = 'variable_set' AND action = 'variable_set.use')
|
|
132
|
+
OR (resource_kind = 'rig' AND action = 'rig.use')
|
|
133
|
+
OR (resource_kind = 'connected_machine' AND action = 'connected_machine.use')
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
-- The source-patch block contains the replacement function's enrollment and
|
|
137
|
+
-- sandbox reads. The production migrator is a NON-superuser/NOBYPASSRLS owner,
|
|
138
|
+
-- so make those references owner-visible inside this exact transaction-local
|
|
139
|
+
-- window. A failure rolls the complete migration back, including FORCE state.
|
|
140
|
+
ALTER TABLE enrollments NO FORCE ROW LEVEL SECURITY;
|
|
141
|
+
ALTER TABLE sandboxes NO FORCE ROW LEVEL SECURITY;
|
|
142
|
+
|
|
143
|
+
-- The 0306 function is long and security-sensitive. Patch only its four exact,
|
|
144
|
+
-- previously shipped source fragments and abort if any expected fragment is
|
|
145
|
+
-- absent. Recreating the signature explicitly preserves the hardened search
|
|
146
|
+
-- path while keeping this migration reviewable as a narrow protocol extension.
|
|
147
|
+
DO $extend_atomic_attachment_function$
|
|
148
|
+
DECLARE
|
|
149
|
+
data_schema text := current_schema();
|
|
150
|
+
function_source text;
|
|
151
|
+
prior_source text;
|
|
152
|
+
BEGIN
|
|
153
|
+
SELECT procedure_value.prosrc INTO STRICT function_source
|
|
154
|
+
FROM pg_proc procedure_value
|
|
155
|
+
JOIN pg_namespace namespace_value ON namespace_value.oid = procedure_value.pronamespace
|
|
156
|
+
WHERE namespace_value.nspname = data_schema
|
|
157
|
+
AND procedure_value.oid = (
|
|
158
|
+
pg_catalog.format(
|
|
159
|
+
'%I.accept_turn_personal_resource_attachment(uuid,uuid,uuid,uuid,text,integer,boolean,integer)',
|
|
160
|
+
data_schema
|
|
161
|
+
)::regprocedure
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
prior_source := function_source;
|
|
165
|
+
function_source := replace(function_source,
|
|
166
|
+
$old$ FOR SHARE OF variable_set;
|
|
167
|
+
|
|
168
|
+
WITH selected AS ($old$,
|
|
169
|
+
$new$ FOR SHARE OF variable_set;
|
|
170
|
+
PERFORM sandbox.id
|
|
171
|
+
FROM sandboxes sandbox
|
|
172
|
+
WHERE sandbox.id = session_row.active_sandbox_id
|
|
173
|
+
AND sandbox.account_id = p_account_id
|
|
174
|
+
AND sandbox.kind = 'selfhosted'
|
|
175
|
+
FOR SHARE;
|
|
176
|
+
PERFORM enrollment.id
|
|
177
|
+
FROM sandboxes sandbox
|
|
178
|
+
JOIN enrollments enrollment
|
|
179
|
+
ON enrollment.id = sandbox.enrollment_id
|
|
180
|
+
AND enrollment.account_id = p_account_id
|
|
181
|
+
WHERE sandbox.id = session_row.active_sandbox_id
|
|
182
|
+
AND sandbox.account_id = p_account_id
|
|
183
|
+
AND sandbox.kind = 'selfhosted'
|
|
184
|
+
AND enrollment.authority_scope = 'user'
|
|
185
|
+
FOR SHARE OF enrollment;
|
|
186
|
+
|
|
187
|
+
WITH selected AS ($new$
|
|
188
|
+
);
|
|
189
|
+
IF function_source = prior_source THEN
|
|
190
|
+
RAISE EXCEPTION '0338 could not extend the atomic attachment lock set'
|
|
191
|
+
USING ERRCODE = '55000';
|
|
192
|
+
END IF;
|
|
193
|
+
|
|
194
|
+
prior_source := function_source;
|
|
195
|
+
function_source := replace(function_source,
|
|
196
|
+
$old$ WHERE version_value.id = session_row.rig_version_id
|
|
197
|
+
AND version_value.rig_id = session_row.rig_id
|
|
198
|
+
AND version_value.account_id = p_account_id
|
|
199
|
+
), grouped AS ($old$,
|
|
200
|
+
$new$ WHERE version_value.id = session_row.rig_version_id
|
|
201
|
+
AND version_value.rig_id = session_row.rig_id
|
|
202
|
+
AND version_value.account_id = p_account_id
|
|
203
|
+
UNION ALL
|
|
204
|
+
SELECT 'connected_machine', enrollment.id, NULL::uuid,
|
|
205
|
+
'connected_machine.use', 'session_active_sandbox',
|
|
206
|
+
enrollment.origin_workspace_id, enrollment.authority_id,
|
|
207
|
+
enrollment.owner_organization_membership_id
|
|
208
|
+
FROM sandboxes sandbox
|
|
209
|
+
JOIN enrollments enrollment
|
|
210
|
+
ON enrollment.id = sandbox.enrollment_id
|
|
211
|
+
AND enrollment.account_id = p_account_id
|
|
212
|
+
WHERE sandbox.id = session_row.active_sandbox_id
|
|
213
|
+
AND sandbox.account_id = p_account_id
|
|
214
|
+
AND sandbox.kind = 'selfhosted'
|
|
215
|
+
AND enrollment.authority_scope = 'user'
|
|
216
|
+
AND enrollment.status = 'active'
|
|
217
|
+
), grouped AS ($new$
|
|
218
|
+
);
|
|
219
|
+
IF function_source = prior_source THEN
|
|
220
|
+
RAISE EXCEPTION '0338 could not extend the atomic attachment closure'
|
|
221
|
+
USING ERRCODE = '55000';
|
|
222
|
+
END IF;
|
|
223
|
+
|
|
224
|
+
prior_source := function_source;
|
|
225
|
+
function_source := replace(
|
|
226
|
+
function_source,
|
|
227
|
+
'no personal Variable Set or Rig is selected by this session',
|
|
228
|
+
'no personal Variable Set, Rig, or Connected Machine is selected by this session'
|
|
229
|
+
);
|
|
230
|
+
IF function_source = prior_source THEN
|
|
231
|
+
RAISE EXCEPTION '0338 could not update the empty attachment diagnostic'
|
|
232
|
+
USING ERRCODE = '55000';
|
|
233
|
+
END IF;
|
|
234
|
+
function_source := replace(
|
|
235
|
+
function_source,
|
|
236
|
+
'personal Variable Set/Rig closure exceeds the accepted-work bound',
|
|
237
|
+
'personal resource closure exceeds the accepted-work bound'
|
|
238
|
+
);
|
|
239
|
+
function_source := replace(function_source, 'IF selected_count > 27 THEN',
|
|
240
|
+
'IF selected_count > 28 THEN');
|
|
241
|
+
IF function_source NOT LIKE '%IF selected_count > 28 THEN%'
|
|
242
|
+
OR function_source LIKE '%IF selected_count > 27 THEN%'
|
|
243
|
+
THEN
|
|
244
|
+
RAISE EXCEPTION '0338 could not update the attachment bound'
|
|
245
|
+
USING ERRCODE = '55000';
|
|
246
|
+
END IF;
|
|
247
|
+
|
|
248
|
+
EXECUTE pg_catalog.format(
|
|
249
|
+
'CREATE OR REPLACE FUNCTION %I.accept_turn_personal_resource_attachment('
|
|
250
|
+
|| 'p_account_id uuid, p_workspace_id uuid, p_session_id uuid, p_turn_id uuid, '
|
|
251
|
+
|| 'p_mode text, p_expected_authority_epoch integer, '
|
|
252
|
+
|| 'p_workspace_shared_acknowledged boolean, '
|
|
253
|
+
|| 'p_shared_output_warning_version integer) '
|
|
254
|
+
|| 'RETURNS TABLE (grant_mode text, grant_context text, resource_count integer, '
|
|
255
|
+
|| 'resource_kinds text[], shared_output_warning_version integer, replay boolean) '
|
|
256
|
+
|| 'LANGUAGE plpgsql SECURITY DEFINER '
|
|
257
|
+
|| 'SET search_path TO pg_catalog, %I, pg_temp AS %L',
|
|
258
|
+
data_schema, data_schema, function_source
|
|
259
|
+
);
|
|
260
|
+
END
|
|
261
|
+
$extend_atomic_attachment_function$;
|
|
262
|
+
|
|
263
|
+
ALTER TABLE enrollments FORCE ROW LEVEL SECURITY;
|
|
264
|
+
ALTER TABLE sandboxes FORCE ROW LEVEL SECURITY;
|
|
265
|
+
|
|
266
|
+
-- Protocol-v1 attachment admission runs before this alphabetically-later
|
|
267
|
+
-- trigger and has already validated/copy-frozen the complete accepted-turn
|
|
268
|
+
-- snapshot. Reuse that exact machine row, including a consumed `once` grant,
|
|
269
|
+
-- instead of selecting mutable grant state again. Version-0 turns keep the
|
|
270
|
+
-- pre-0338 trigger unchanged.
|
|
271
|
+
CREATE FUNCTION admit_session_attempt_personal_machine_v1() RETURNS trigger
|
|
272
|
+
LANGUAGE plpgsql
|
|
273
|
+
SECURITY DEFINER
|
|
274
|
+
SET search_path FROM CURRENT
|
|
275
|
+
AS $body$
|
|
276
|
+
DECLARE
|
|
277
|
+
session_row sessions%ROWTYPE;
|
|
278
|
+
sandbox_row sandboxes%ROWTYPE;
|
|
279
|
+
enrollment_row enrollments%ROWTYPE;
|
|
280
|
+
snapshot_row session_attempt_personal_resource_snapshots%ROWTYPE;
|
|
281
|
+
BEGIN
|
|
282
|
+
INSERT INTO opengeni_private.scoped_compute_capabilities(
|
|
283
|
+
backend_pid, transaction_id, capability_kind
|
|
284
|
+
) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'write')
|
|
285
|
+
ON CONFLICT DO NOTHING;
|
|
286
|
+
|
|
287
|
+
SELECT session_value.* INTO STRICT session_row
|
|
288
|
+
FROM sessions session_value
|
|
289
|
+
WHERE session_value.id = NEW.session_id
|
|
290
|
+
AND session_value.account_id = NEW.account_id
|
|
291
|
+
AND session_value.workspace_id = NEW.workspace_id
|
|
292
|
+
FOR SHARE;
|
|
293
|
+
IF session_row.active_sandbox_id IS NULL THEN
|
|
294
|
+
DELETE FROM opengeni_private.scoped_compute_capabilities
|
|
295
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
296
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned();
|
|
297
|
+
RETURN NEW;
|
|
298
|
+
END IF;
|
|
299
|
+
|
|
300
|
+
SELECT sandbox.* INTO sandbox_row
|
|
301
|
+
FROM sandboxes sandbox
|
|
302
|
+
WHERE sandbox.id = session_row.active_sandbox_id
|
|
303
|
+
AND sandbox.account_id = NEW.account_id
|
|
304
|
+
AND sandbox.kind = 'selfhosted'
|
|
305
|
+
FOR SHARE;
|
|
306
|
+
IF sandbox_row.enrollment_id IS NULL THEN
|
|
307
|
+
DELETE FROM opengeni_private.scoped_compute_capabilities
|
|
308
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
309
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned();
|
|
310
|
+
RETURN NEW;
|
|
311
|
+
END IF;
|
|
312
|
+
|
|
313
|
+
SELECT enrollment.* INTO enrollment_row
|
|
314
|
+
FROM enrollments enrollment
|
|
315
|
+
WHERE enrollment.id = sandbox_row.enrollment_id
|
|
316
|
+
AND enrollment.account_id = NEW.account_id
|
|
317
|
+
AND enrollment.authority_scope = 'user'
|
|
318
|
+
AND enrollment.status = 'active'
|
|
319
|
+
FOR SHARE;
|
|
320
|
+
IF enrollment_row.id IS NULL THEN
|
|
321
|
+
DELETE FROM opengeni_private.scoped_compute_capabilities
|
|
322
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
323
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned();
|
|
324
|
+
RETURN NEW;
|
|
325
|
+
END IF;
|
|
326
|
+
|
|
327
|
+
SELECT snapshot.* INTO STRICT snapshot_row
|
|
328
|
+
FROM session_attempt_personal_resource_snapshots snapshot
|
|
329
|
+
WHERE snapshot.attempt_id = NEW.id
|
|
330
|
+
AND snapshot.account_id = NEW.account_id
|
|
331
|
+
AND snapshot.workspace_id = NEW.workspace_id
|
|
332
|
+
AND snapshot.session_id = NEW.session_id
|
|
333
|
+
AND snapshot.turn_id = NEW.turn_id
|
|
334
|
+
AND snapshot.execution_generation = NEW.execution_generation
|
|
335
|
+
AND snapshot.resource_kind = 'connected_machine'
|
|
336
|
+
AND snapshot.resource_id = enrollment_row.id
|
|
337
|
+
AND snapshot.action = 'connected_machine.use';
|
|
338
|
+
|
|
339
|
+
IF snapshot_row.authority_id IS DISTINCT FROM enrollment_row.authority_id
|
|
340
|
+
OR snapshot_row.authority_generation IS DISTINCT FROM enrollment_row.generation
|
|
341
|
+
OR snapshot_row.owner_organization_membership_id
|
|
342
|
+
IS DISTINCT FROM enrollment_row.owner_organization_membership_id
|
|
343
|
+
OR snapshot_row.session_visibility IS DISTINCT FROM session_row.visibility
|
|
344
|
+
OR snapshot_row.session_authority_epoch IS DISTINCT FROM session_row.authority_epoch
|
|
345
|
+
THEN
|
|
346
|
+
RAISE EXCEPTION 'turn-bound personal machine snapshot is not current'
|
|
347
|
+
USING ERRCODE = '42501';
|
|
348
|
+
END IF;
|
|
349
|
+
|
|
350
|
+
INSERT INTO session_attempt_connected_machine_authorizations(
|
|
351
|
+
attempt_id, account_id, workspace_id, session_id, turn_id, execution_generation,
|
|
352
|
+
initiating_human_subject_id, owner_organization_membership_id,
|
|
353
|
+
membership_authorization_revision, enrollment_id, sandbox_id, authority_id,
|
|
354
|
+
authority_generation, enrollment_generation, session_visibility,
|
|
355
|
+
session_authority_epoch, grant_id, grant_generation, grant_mode
|
|
356
|
+
)
|
|
357
|
+
SELECT NEW.id, NEW.account_id, NEW.workspace_id, NEW.session_id, NEW.turn_id,
|
|
358
|
+
NEW.execution_generation, admission.initiating_human_subject_id,
|
|
359
|
+
snapshot_row.owner_organization_membership_id,
|
|
360
|
+
snapshot_row.membership_authorization_revision, enrollment_row.id, sandbox_row.id,
|
|
361
|
+
snapshot_row.authority_id, snapshot_row.authority_generation,
|
|
362
|
+
enrollment_row.generation, snapshot_row.session_visibility,
|
|
363
|
+
snapshot_row.session_authority_epoch, snapshot_row.grant_id,
|
|
364
|
+
snapshot_row.grant_generation, snapshot_row.grant_mode
|
|
365
|
+
FROM session_attempt_personal_resource_admissions admission
|
|
366
|
+
WHERE admission.attempt_id = NEW.id
|
|
367
|
+
AND admission.account_id = NEW.account_id
|
|
368
|
+
AND admission.workspace_id = NEW.workspace_id
|
|
369
|
+
AND admission.session_id = NEW.session_id
|
|
370
|
+
AND admission.turn_id = NEW.turn_id;
|
|
371
|
+
IF NOT FOUND THEN
|
|
372
|
+
RAISE EXCEPTION 'turn-bound personal machine admission is missing'
|
|
373
|
+
USING ERRCODE = '42501';
|
|
374
|
+
END IF;
|
|
375
|
+
|
|
376
|
+
DELETE FROM opengeni_private.scoped_compute_capabilities
|
|
377
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
378
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
379
|
+
AND capability_kind = 'write';
|
|
380
|
+
RETURN NEW;
|
|
381
|
+
EXCEPTION WHEN OTHERS THEN
|
|
382
|
+
DELETE FROM opengeni_private.scoped_compute_capabilities
|
|
383
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
384
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned();
|
|
385
|
+
RAISE;
|
|
386
|
+
END
|
|
387
|
+
$body$;
|
|
388
|
+
|
|
389
|
+
DROP TRIGGER z_session_attempt_personal_machine_admission ON session_turn_attempts;
|
|
390
|
+
CREATE TRIGGER z_session_attempt_personal_machine_admission_legacy
|
|
391
|
+
AFTER INSERT ON session_turn_attempts FOR EACH ROW
|
|
392
|
+
WHEN (NEW.personal_resource_protocol_version = 0)
|
|
393
|
+
EXECUTE FUNCTION admit_session_attempt_personal_machine();
|
|
394
|
+
CREATE TRIGGER zz_session_attempt_personal_machine_admission_v1
|
|
395
|
+
AFTER INSERT ON session_turn_attempts FOR EACH ROW
|
|
396
|
+
WHEN (NEW.personal_resource_protocol_version = 1)
|
|
397
|
+
EXECUTE FUNCTION admit_session_attempt_personal_machine_v1();
|
|
398
|
+
|
|
399
|
+
REVOKE ALL ON FUNCTION admit_session_attempt_personal_machine_v1() FROM PUBLIC;
|
|
400
|
+
|
|
401
|
+
DO $atomic_connected_machine_function_hardening$
|
|
402
|
+
DECLARE data_schema text := current_schema();
|
|
403
|
+
BEGIN
|
|
404
|
+
EXECUTE pg_catalog.format(
|
|
405
|
+
'ALTER FUNCTION %I.admit_session_attempt_personal_machine_v1() '
|
|
406
|
+
|| 'SET search_path TO pg_catalog, %I, pg_temp',
|
|
407
|
+
data_schema, data_schema
|
|
408
|
+
);
|
|
409
|
+
END
|
|
410
|
+
$atomic_connected_machine_function_hardening$;
|