@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,1273 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- This migration activates organization-user ownership for personal Documents. Existing
|
|
3
|
+
-- personal rows remain fail-closed to their original workspace; new personal
|
|
4
|
+
-- rows may carry the common user-resource authority and follow their owner
|
|
5
|
+
-- across workspaces in the same organization. Agent reads require an exact
|
|
6
|
+
-- attempt snapshot backed by an explicit once/session/always grant.
|
|
7
|
+
|
|
8
|
+
SET LOCAL lock_timeout = '5s';
|
|
9
|
+
SET LOCAL statement_timeout = '10min';
|
|
10
|
+
|
|
11
|
+
ALTER TABLE "documents"
|
|
12
|
+
ADD COLUMN "authority_id" uuid,
|
|
13
|
+
ADD COLUMN "owner_organization_membership_id" uuid,
|
|
14
|
+
ADD COLUMN "origin_workspace_id" uuid;
|
|
15
|
+
|
|
16
|
+
ALTER TABLE "document_chunks"
|
|
17
|
+
ADD COLUMN "authority_id" uuid,
|
|
18
|
+
ADD COLUMN "owner_organization_membership_id" uuid;
|
|
19
|
+
|
|
20
|
+
UPDATE "documents" SET "origin_workspace_id" = "workspace_id";
|
|
21
|
+
ALTER TABLE "documents" ADD CONSTRAINT "documents_origin_workspace_not_null_chk"
|
|
22
|
+
CHECK ("origin_workspace_id" IS NOT NULL) NOT VALID;
|
|
23
|
+
ALTER TABLE "documents" VALIDATE CONSTRAINT "documents_origin_workspace_not_null_chk";
|
|
24
|
+
ALTER TABLE "documents" ALTER COLUMN "origin_workspace_id" SET NOT NULL;
|
|
25
|
+
ALTER TABLE "documents" DROP CONSTRAINT "documents_origin_workspace_not_null_chk";
|
|
26
|
+
ALTER TABLE "documents" ADD CONSTRAINT "documents_origin_workspace_chk"
|
|
27
|
+
CHECK ("origin_workspace_id" = "workspace_id") NOT VALID;
|
|
28
|
+
ALTER TABLE "documents" VALIDATE CONSTRAINT "documents_origin_workspace_chk";
|
|
29
|
+
|
|
30
|
+
ALTER TABLE "documents"
|
|
31
|
+
ADD CONSTRAINT "documents_user_authority_fk"
|
|
32
|
+
FOREIGN KEY ("authority_id", "account_id", "owner_organization_membership_id")
|
|
33
|
+
REFERENCES "organization_user_resource_authorities"(
|
|
34
|
+
"id", "account_id", "organization_membership_id"
|
|
35
|
+
) ON DELETE RESTRICT NOT VALID;
|
|
36
|
+
ALTER TABLE "documents" VALIDATE CONSTRAINT "documents_user_authority_fk";
|
|
37
|
+
|
|
38
|
+
ALTER TABLE "document_chunks"
|
|
39
|
+
ADD CONSTRAINT "document_chunks_user_authority_fk"
|
|
40
|
+
FOREIGN KEY ("authority_id", "account_id", "owner_organization_membership_id")
|
|
41
|
+
REFERENCES "organization_user_resource_authorities"(
|
|
42
|
+
"id", "account_id", "organization_membership_id"
|
|
43
|
+
) ON DELETE RESTRICT NOT VALID;
|
|
44
|
+
ALTER TABLE "document_chunks" VALIDATE CONSTRAINT "document_chunks_user_authority_fk";
|
|
45
|
+
|
|
46
|
+
ALTER TABLE "documents" DROP CONSTRAINT "documents_authority_chk";
|
|
47
|
+
ALTER TABLE "documents" ADD CONSTRAINT "documents_authority_chk" CHECK (
|
|
48
|
+
(
|
|
49
|
+
"authority_kind" = 'organization'
|
|
50
|
+
AND "authority_workspace_id" IS NULL
|
|
51
|
+
AND "authority_subject_id" IS NULL
|
|
52
|
+
AND "authority_id" IS NULL
|
|
53
|
+
AND "owner_organization_membership_id" IS NULL
|
|
54
|
+
) OR (
|
|
55
|
+
"authority_kind" = 'workspace'
|
|
56
|
+
AND "authority_workspace_id" = "workspace_id"
|
|
57
|
+
AND "authority_subject_id" IS NULL
|
|
58
|
+
AND "authority_id" IS NULL
|
|
59
|
+
AND "owner_organization_membership_id" IS NULL
|
|
60
|
+
) OR (
|
|
61
|
+
"authority_kind" = 'personal'
|
|
62
|
+
AND NULLIF(btrim("authority_subject_id"), '') IS NOT NULL
|
|
63
|
+
AND octet_length(convert_to("authority_subject_id", 'UTF8')) <= 1024
|
|
64
|
+
AND "authority_subject_id" = "created_by"
|
|
65
|
+
AND (
|
|
66
|
+
(
|
|
67
|
+
"authority_workspace_id" = "workspace_id"
|
|
68
|
+
AND "authority_id" IS NULL
|
|
69
|
+
AND "owner_organization_membership_id" IS NULL
|
|
70
|
+
) OR (
|
|
71
|
+
"authority_workspace_id" IS NULL
|
|
72
|
+
AND "authority_id" IS NOT NULL
|
|
73
|
+
AND "owner_organization_membership_id" IS NOT NULL
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
) NOT VALID;
|
|
78
|
+
ALTER TABLE "documents" VALIDATE CONSTRAINT "documents_authority_chk";
|
|
79
|
+
|
|
80
|
+
ALTER TABLE "document_chunks" DROP CONSTRAINT "document_chunks_authority_chk";
|
|
81
|
+
ALTER TABLE "document_chunks" ADD CONSTRAINT "document_chunks_authority_chk" CHECK (
|
|
82
|
+
(
|
|
83
|
+
"authority_kind" = 'organization'
|
|
84
|
+
AND "authority_workspace_id" IS NULL
|
|
85
|
+
AND "authority_subject_id" IS NULL
|
|
86
|
+
AND "authority_id" IS NULL
|
|
87
|
+
AND "owner_organization_membership_id" IS NULL
|
|
88
|
+
) OR (
|
|
89
|
+
"authority_kind" = 'workspace'
|
|
90
|
+
AND "authority_workspace_id" = "workspace_id"
|
|
91
|
+
AND "authority_subject_id" IS NULL
|
|
92
|
+
AND "authority_id" IS NULL
|
|
93
|
+
AND "owner_organization_membership_id" IS NULL
|
|
94
|
+
) OR (
|
|
95
|
+
"authority_kind" = 'personal'
|
|
96
|
+
AND NULLIF(btrim("authority_subject_id"), '') IS NOT NULL
|
|
97
|
+
AND octet_length(convert_to("authority_subject_id", 'UTF8')) <= 1024
|
|
98
|
+
AND (
|
|
99
|
+
(
|
|
100
|
+
"authority_workspace_id" = "workspace_id"
|
|
101
|
+
AND "authority_id" IS NULL
|
|
102
|
+
AND "owner_organization_membership_id" IS NULL
|
|
103
|
+
) OR (
|
|
104
|
+
"authority_workspace_id" IS NULL
|
|
105
|
+
AND "authority_id" IS NOT NULL
|
|
106
|
+
AND "owner_organization_membership_id" IS NOT NULL
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
) NOT VALID;
|
|
111
|
+
ALTER TABLE "document_chunks" VALIDATE CONSTRAINT "document_chunks_authority_chk";
|
|
112
|
+
|
|
113
|
+
CREATE INDEX "documents_user_authority_idx"
|
|
114
|
+
ON "documents" ("account_id", "owner_organization_membership_id", "status", "id")
|
|
115
|
+
WHERE "authority_kind" = 'personal' AND "authority_id" IS NOT NULL;
|
|
116
|
+
|
|
117
|
+
CREATE TABLE opengeni_private.personal_document_authority_capabilities (
|
|
118
|
+
"backend_pid" integer NOT NULL,
|
|
119
|
+
"transaction_id" xid8 NOT NULL,
|
|
120
|
+
"capability_kind" text NOT NULL,
|
|
121
|
+
"created_at" timestamptz NOT NULL DEFAULT clock_timestamp(),
|
|
122
|
+
CONSTRAINT "personal_document_authority_capabilities_kind_chk" CHECK (
|
|
123
|
+
"capability_kind" IN ('write', 'admit', 'resolve')
|
|
124
|
+
),
|
|
125
|
+
CONSTRAINT "personal_document_authority_capabilities_pk" PRIMARY KEY (
|
|
126
|
+
"backend_pid", "transaction_id", "capability_kind"
|
|
127
|
+
)
|
|
128
|
+
);
|
|
129
|
+
REVOKE ALL ON TABLE opengeni_private.personal_document_authority_capabilities FROM PUBLIC;
|
|
130
|
+
|
|
131
|
+
CREATE OR REPLACE FUNCTION opengeni_private.personal_document_authority_capability_active(
|
|
132
|
+
p_capability_kind text DEFAULT NULL
|
|
133
|
+
) RETURNS boolean
|
|
134
|
+
LANGUAGE sql
|
|
135
|
+
STABLE
|
|
136
|
+
SECURITY DEFINER
|
|
137
|
+
SET search_path = pg_catalog
|
|
138
|
+
AS $capability_active$
|
|
139
|
+
SELECT EXISTS (
|
|
140
|
+
SELECT 1
|
|
141
|
+
FROM opengeni_private.personal_document_authority_capabilities capability
|
|
142
|
+
WHERE capability.backend_pid = pg_catalog.pg_backend_pid()
|
|
143
|
+
AND capability.transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
144
|
+
AND (
|
|
145
|
+
p_capability_kind IS NULL
|
|
146
|
+
OR capability.capability_kind = p_capability_kind
|
|
147
|
+
)
|
|
148
|
+
)
|
|
149
|
+
$capability_active$;
|
|
150
|
+
REVOKE ALL ON FUNCTION
|
|
151
|
+
opengeni_private.personal_document_authority_capability_active(text) FROM PUBLIC;
|
|
152
|
+
|
|
153
|
+
CREATE TABLE "session_attempt_personal_document_admissions" (
|
|
154
|
+
"attempt_id" uuid PRIMARY KEY REFERENCES "session_turn_attempts"("id") ON DELETE CASCADE,
|
|
155
|
+
"account_id" uuid NOT NULL,
|
|
156
|
+
"workspace_id" uuid NOT NULL,
|
|
157
|
+
"session_id" uuid NOT NULL,
|
|
158
|
+
"turn_id" uuid NOT NULL,
|
|
159
|
+
"execution_generation" integer NOT NULL,
|
|
160
|
+
"initiating_human_subject_id" text NOT NULL,
|
|
161
|
+
"owner_organization_membership_id" uuid NOT NULL,
|
|
162
|
+
"membership_authorization_revision" bigint NOT NULL,
|
|
163
|
+
"session_visibility" text NOT NULL,
|
|
164
|
+
"session_authority_epoch" integer NOT NULL,
|
|
165
|
+
"document_count" integer NOT NULL,
|
|
166
|
+
"admitted_at" timestamptz NOT NULL DEFAULT clock_timestamp(),
|
|
167
|
+
CONSTRAINT "session_attempt_personal_document_admissions_attempt_fk"
|
|
168
|
+
FOREIGN KEY ("account_id", "workspace_id", "session_id", "turn_id", "attempt_id")
|
|
169
|
+
REFERENCES "session_turn_attempts"(
|
|
170
|
+
"account_id", "workspace_id", "session_id", "turn_id", "id"
|
|
171
|
+
) ON DELETE CASCADE,
|
|
172
|
+
CONSTRAINT "session_attempt_personal_document_admissions_owner_fk"
|
|
173
|
+
FOREIGN KEY ("owner_organization_membership_id", "account_id")
|
|
174
|
+
REFERENCES "organization_memberships"("id", "account_id") ON DELETE RESTRICT,
|
|
175
|
+
CONSTRAINT "session_attempt_personal_document_admissions_shape_chk" CHECK (
|
|
176
|
+
"execution_generation" > 0
|
|
177
|
+
AND "membership_authorization_revision" > 0
|
|
178
|
+
AND "session_authority_epoch" > 0
|
|
179
|
+
AND "document_count" >= 0
|
|
180
|
+
AND "session_visibility" IN ('user_private', 'workspace_shared')
|
|
181
|
+
AND length(btrim("initiating_human_subject_id")) BETWEEN 1 AND 1024
|
|
182
|
+
)
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
CREATE TABLE "session_attempt_personal_document_snapshots" (
|
|
186
|
+
"attempt_id" uuid NOT NULL,
|
|
187
|
+
"document_id" uuid NOT NULL REFERENCES "documents"("id") ON DELETE CASCADE,
|
|
188
|
+
"account_id" uuid NOT NULL,
|
|
189
|
+
"workspace_id" uuid NOT NULL,
|
|
190
|
+
"session_id" uuid NOT NULL,
|
|
191
|
+
"turn_id" uuid NOT NULL,
|
|
192
|
+
"execution_generation" integer NOT NULL,
|
|
193
|
+
"owner_organization_membership_id" uuid NOT NULL,
|
|
194
|
+
"membership_authorization_revision" bigint NOT NULL,
|
|
195
|
+
"authority_id" uuid NOT NULL,
|
|
196
|
+
"authority_generation" bigint NOT NULL,
|
|
197
|
+
"target_workspace_id" uuid NOT NULL,
|
|
198
|
+
"session_visibility" text NOT NULL,
|
|
199
|
+
"session_authority_epoch" integer NOT NULL,
|
|
200
|
+
"grant_id" uuid NOT NULL,
|
|
201
|
+
"grant_generation" bigint NOT NULL,
|
|
202
|
+
"grant_mode" text NOT NULL,
|
|
203
|
+
"grant_context" text NOT NULL,
|
|
204
|
+
"grant_session_id" uuid,
|
|
205
|
+
"grant_authority_epoch" integer,
|
|
206
|
+
"created_at" timestamptz NOT NULL DEFAULT clock_timestamp(),
|
|
207
|
+
CONSTRAINT "session_attempt_personal_document_snapshots_pk"
|
|
208
|
+
PRIMARY KEY ("attempt_id", "document_id"),
|
|
209
|
+
CONSTRAINT "session_attempt_personal_document_snapshots_admission_fk"
|
|
210
|
+
FOREIGN KEY ("attempt_id")
|
|
211
|
+
REFERENCES "session_attempt_personal_document_admissions"("attempt_id") ON DELETE CASCADE,
|
|
212
|
+
CONSTRAINT "session_attempt_personal_document_snapshots_authority_fk"
|
|
213
|
+
FOREIGN KEY ("authority_id", "account_id", "owner_organization_membership_id")
|
|
214
|
+
REFERENCES "organization_user_resource_authorities"(
|
|
215
|
+
"id", "account_id", "organization_membership_id"
|
|
216
|
+
) ON DELETE RESTRICT,
|
|
217
|
+
CONSTRAINT "session_attempt_personal_document_snapshots_grant_fk"
|
|
218
|
+
FOREIGN KEY ("grant_id", "account_id")
|
|
219
|
+
REFERENCES "organization_user_resource_grants"("id", "account_id") ON DELETE RESTRICT,
|
|
220
|
+
CONSTRAINT "session_attempt_personal_document_snapshots_shape_chk" CHECK (
|
|
221
|
+
"execution_generation" > 0
|
|
222
|
+
AND "membership_authorization_revision" > 0
|
|
223
|
+
AND "authority_generation" > 0
|
|
224
|
+
AND "target_workspace_id" = "workspace_id"
|
|
225
|
+
AND "session_authority_epoch" > 0
|
|
226
|
+
AND "grant_generation" > 0
|
|
227
|
+
AND "session_visibility" IN ('user_private', 'workspace_shared')
|
|
228
|
+
AND "grant_context" = "session_visibility"
|
|
229
|
+
AND (
|
|
230
|
+
(
|
|
231
|
+
"grant_mode" = 'always'
|
|
232
|
+
AND "grant_session_id" IS NULL
|
|
233
|
+
AND "grant_authority_epoch" IS NULL
|
|
234
|
+
) OR (
|
|
235
|
+
"grant_mode" IN ('once', 'session')
|
|
236
|
+
AND "grant_session_id" = "session_id"
|
|
237
|
+
AND "grant_authority_epoch" = "session_authority_epoch"
|
|
238
|
+
)
|
|
239
|
+
)
|
|
240
|
+
)
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
CREATE TABLE "personal_document_once_consumption_receipts" (
|
|
244
|
+
"grant_id" uuid PRIMARY KEY,
|
|
245
|
+
"account_id" uuid NOT NULL,
|
|
246
|
+
"attempt_id" uuid NOT NULL,
|
|
247
|
+
"document_id" uuid NOT NULL,
|
|
248
|
+
"authority_id" uuid NOT NULL,
|
|
249
|
+
"authority_generation" bigint NOT NULL,
|
|
250
|
+
"grant_generation" bigint NOT NULL,
|
|
251
|
+
"consumed_at" timestamptz NOT NULL DEFAULT clock_timestamp(),
|
|
252
|
+
CONSTRAINT "personal_document_once_consumption_receipts_grant_fk"
|
|
253
|
+
FOREIGN KEY ("grant_id", "account_id")
|
|
254
|
+
REFERENCES "organization_user_resource_grants"("id", "account_id") ON DELETE RESTRICT,
|
|
255
|
+
CONSTRAINT "personal_document_once_consumption_receipts_snapshot_fk"
|
|
256
|
+
FOREIGN KEY ("attempt_id", "document_id")
|
|
257
|
+
REFERENCES "session_attempt_personal_document_snapshots"(
|
|
258
|
+
"attempt_id", "document_id"
|
|
259
|
+
) ON DELETE CASCADE,
|
|
260
|
+
CONSTRAINT "personal_document_once_consumption_receipts_generation_chk" CHECK (
|
|
261
|
+
"authority_generation" > 0 AND "grant_generation" > 0
|
|
262
|
+
)
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
ALTER TABLE "session_attempt_personal_document_admissions" ENABLE ROW LEVEL SECURITY;
|
|
266
|
+
ALTER TABLE "session_attempt_personal_document_admissions" FORCE ROW LEVEL SECURITY;
|
|
267
|
+
ALTER TABLE "session_attempt_personal_document_snapshots" ENABLE ROW LEVEL SECURITY;
|
|
268
|
+
ALTER TABLE "session_attempt_personal_document_snapshots" FORCE ROW LEVEL SECURITY;
|
|
269
|
+
ALTER TABLE "personal_document_once_consumption_receipts" ENABLE ROW LEVEL SECURITY;
|
|
270
|
+
ALTER TABLE "personal_document_once_consumption_receipts" FORCE ROW LEVEL SECURITY;
|
|
271
|
+
|
|
272
|
+
DO $personal_document_capability_policies$
|
|
273
|
+
DECLARE
|
|
274
|
+
data_schema text := current_schema();
|
|
275
|
+
migration_owner text := current_user;
|
|
276
|
+
table_name text;
|
|
277
|
+
BEGIN
|
|
278
|
+
FOREACH table_name IN ARRAY ARRAY[
|
|
279
|
+
'documents', 'files', 'organization_memberships', 'workspace_memberships',
|
|
280
|
+
'organization_user_resource_authorities', 'organization_user_resource_grants',
|
|
281
|
+
'sessions', 'session_turns', 'session_turn_attempts', 'session_attempt_interruptions',
|
|
282
|
+
'session_attempt_personal_document_admissions',
|
|
283
|
+
'session_attempt_personal_document_snapshots',
|
|
284
|
+
'personal_document_once_consumption_receipts'
|
|
285
|
+
] LOOP
|
|
286
|
+
EXECUTE format(
|
|
287
|
+
'CREATE POLICY personal_document_authority_capability_read ON %I.%I '
|
|
288
|
+
|| 'FOR SELECT USING (current_user = %L AND '
|
|
289
|
+
|| 'opengeni_private.personal_document_authority_capability_active())',
|
|
290
|
+
data_schema, table_name, migration_owner
|
|
291
|
+
);
|
|
292
|
+
END LOOP;
|
|
293
|
+
|
|
294
|
+
EXECUTE format(
|
|
295
|
+
'CREATE POLICY personal_document_authority_capability_insert '
|
|
296
|
+
|| 'ON %I.organization_user_resource_authorities FOR INSERT WITH CHECK ('
|
|
297
|
+
|| 'current_user = %L AND '
|
|
298
|
+
|| 'opengeni_private.personal_document_authority_capability_active(''write''))',
|
|
299
|
+
data_schema, migration_owner
|
|
300
|
+
);
|
|
301
|
+
EXECUTE format(
|
|
302
|
+
'CREATE POLICY personal_document_authority_capability_update '
|
|
303
|
+
|| 'ON %I.organization_user_resource_authorities FOR UPDATE USING ('
|
|
304
|
+
|| 'current_user = %L AND '
|
|
305
|
+
|| 'opengeni_private.personal_document_authority_capability_active(''write'')) '
|
|
306
|
+
|| 'WITH CHECK (current_user = %L AND '
|
|
307
|
+
|| 'opengeni_private.personal_document_authority_capability_active(''write''))',
|
|
308
|
+
data_schema, migration_owner, migration_owner
|
|
309
|
+
);
|
|
310
|
+
EXECUTE format(
|
|
311
|
+
'CREATE POLICY personal_document_grant_capability_update '
|
|
312
|
+
|| 'ON %I.organization_user_resource_grants FOR UPDATE USING ('
|
|
313
|
+
|| 'current_user = %L AND '
|
|
314
|
+
|| 'opengeni_private.personal_document_authority_capability_active()) '
|
|
315
|
+
|| 'WITH CHECK (current_user = %L AND '
|
|
316
|
+
|| 'opengeni_private.personal_document_authority_capability_active())',
|
|
317
|
+
data_schema, migration_owner, migration_owner
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
FOREACH table_name IN ARRAY ARRAY[
|
|
321
|
+
'session_attempt_personal_document_admissions',
|
|
322
|
+
'session_attempt_personal_document_snapshots',
|
|
323
|
+
'personal_document_once_consumption_receipts'
|
|
324
|
+
] LOOP
|
|
325
|
+
EXECUTE format(
|
|
326
|
+
'CREATE POLICY personal_document_authority_capability_insert ON %I.%I '
|
|
327
|
+
|| 'FOR INSERT WITH CHECK (current_user = %L AND '
|
|
328
|
+
|| 'opengeni_private.personal_document_authority_capability_active(''admit''))',
|
|
329
|
+
data_schema, table_name, migration_owner
|
|
330
|
+
);
|
|
331
|
+
END LOOP;
|
|
332
|
+
EXECUTE format(
|
|
333
|
+
'CREATE POLICY personal_document_authority_capability_update '
|
|
334
|
+
|| 'ON %I.session_attempt_personal_document_admissions FOR UPDATE USING ('
|
|
335
|
+
|| 'current_user = %L AND '
|
|
336
|
+
|| 'opengeni_private.personal_document_authority_capability_active(''admit'')) '
|
|
337
|
+
|| 'WITH CHECK (current_user = %L AND '
|
|
338
|
+
|| 'opengeni_private.personal_document_authority_capability_active(''admit''))',
|
|
339
|
+
data_schema, migration_owner, migration_owner
|
|
340
|
+
);
|
|
341
|
+
END
|
|
342
|
+
$personal_document_capability_policies$;
|
|
343
|
+
|
|
344
|
+
DO $personal_document_functions$
|
|
345
|
+
DECLARE
|
|
346
|
+
data_schema text := current_schema();
|
|
347
|
+
BEGIN
|
|
348
|
+
EXECUTE format($ddl$
|
|
349
|
+
CREATE OR REPLACE FUNCTION %1$I.create_personal_document_authority(
|
|
350
|
+
p_account_id uuid,
|
|
351
|
+
p_workspace_id uuid,
|
|
352
|
+
p_document_id uuid
|
|
353
|
+
) RETURNS TABLE (
|
|
354
|
+
authority_id uuid,
|
|
355
|
+
owner_organization_membership_id uuid,
|
|
356
|
+
authority_generation bigint
|
|
357
|
+
)
|
|
358
|
+
LANGUAGE plpgsql
|
|
359
|
+
SECURITY DEFINER
|
|
360
|
+
SET search_path = %1$I, pg_catalog
|
|
361
|
+
AS $body$
|
|
362
|
+
DECLARE
|
|
363
|
+
caller_subject text := nullif(pg_catalog.current_setting('opengeni.subject_id', true), '');
|
|
364
|
+
member_row organization_memberships%%ROWTYPE;
|
|
365
|
+
created_authority_id uuid := pg_catalog.gen_random_uuid();
|
|
366
|
+
BEGIN
|
|
367
|
+
INSERT INTO opengeni_private.personal_document_authority_capabilities (
|
|
368
|
+
backend_pid, transaction_id, capability_kind
|
|
369
|
+
) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'write')
|
|
370
|
+
ON CONFLICT DO NOTHING;
|
|
371
|
+
|
|
372
|
+
IF p_account_id IS DISTINCT FROM nullif(
|
|
373
|
+
pg_catalog.current_setting('opengeni.account_id', true), ''
|
|
374
|
+
)::uuid
|
|
375
|
+
OR p_workspace_id IS DISTINCT FROM nullif(
|
|
376
|
+
pg_catalog.current_setting('opengeni.workspace_id', true), ''
|
|
377
|
+
)::uuid
|
|
378
|
+
OR caller_subject IS NULL
|
|
379
|
+
THEN
|
|
380
|
+
RAISE EXCEPTION 'personal document creation scope mismatch' USING ERRCODE = '42501';
|
|
381
|
+
END IF;
|
|
382
|
+
|
|
383
|
+
SELECT membership.* INTO member_row
|
|
384
|
+
FROM organization_memberships membership
|
|
385
|
+
WHERE membership.account_id = p_account_id
|
|
386
|
+
AND membership.subject_id = caller_subject
|
|
387
|
+
AND membership.status = 'active'
|
|
388
|
+
AND membership.revoked_at IS NULL
|
|
389
|
+
FOR SHARE;
|
|
390
|
+
|
|
391
|
+
-- Configured/local and rolling-legacy subjects may legitimately use the
|
|
392
|
+
-- pre-organization personal Document lane. Only create the portable
|
|
393
|
+
-- organization-user authority when there is one deterministic active
|
|
394
|
+
-- organization membership; otherwise the caller inserts the existing
|
|
395
|
+
-- workspace-anchored personal tuple in the same transaction.
|
|
396
|
+
IF NOT FOUND THEN
|
|
397
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
398
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
399
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
400
|
+
AND capability_kind = 'write';
|
|
401
|
+
RETURN;
|
|
402
|
+
END IF;
|
|
403
|
+
|
|
404
|
+
IF member_row.personal_workspace_id IS DISTINCT FROM p_workspace_id THEN
|
|
405
|
+
PERFORM 1 FROM workspace_memberships workspace_membership
|
|
406
|
+
WHERE workspace_membership.account_id = p_account_id
|
|
407
|
+
AND workspace_membership.workspace_id = p_workspace_id
|
|
408
|
+
AND workspace_membership.subject_id = caller_subject
|
|
409
|
+
FOR KEY SHARE;
|
|
410
|
+
IF NOT FOUND THEN
|
|
411
|
+
RAISE EXCEPTION 'personal document owner lacks current workspace access'
|
|
412
|
+
USING ERRCODE = '42501';
|
|
413
|
+
END IF;
|
|
414
|
+
END IF;
|
|
415
|
+
|
|
416
|
+
INSERT INTO organization_user_resource_authorities (
|
|
417
|
+
id, account_id, organization_membership_id, resource_kind,
|
|
418
|
+
resource_id, origin_workspace_id, generation, status
|
|
419
|
+
) VALUES (
|
|
420
|
+
created_authority_id, p_account_id, member_row.id, 'document',
|
|
421
|
+
p_document_id, p_workspace_id, 1, 'active'
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
authority_id := created_authority_id;
|
|
425
|
+
owner_organization_membership_id := member_row.id;
|
|
426
|
+
authority_generation := 1;
|
|
427
|
+
RETURN NEXT;
|
|
428
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
429
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
430
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
431
|
+
AND capability_kind = 'write';
|
|
432
|
+
RETURN;
|
|
433
|
+
EXCEPTION WHEN OTHERS THEN
|
|
434
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
435
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
436
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
437
|
+
AND capability_kind = 'write';
|
|
438
|
+
RAISE;
|
|
439
|
+
END
|
|
440
|
+
$body$;
|
|
441
|
+
$ddl$, data_schema);
|
|
442
|
+
|
|
443
|
+
EXECUTE format($ddl$
|
|
444
|
+
CREATE OR REPLACE FUNCTION %1$I.prepare_session_attempt_personal_document_reads(
|
|
445
|
+
p_account_id uuid,
|
|
446
|
+
p_workspace_id uuid,
|
|
447
|
+
p_session_id uuid,
|
|
448
|
+
p_attempt_id uuid
|
|
449
|
+
) RETURNS integer
|
|
450
|
+
LANGUAGE plpgsql
|
|
451
|
+
SECURITY DEFINER
|
|
452
|
+
SET search_path = %1$I, pg_catalog
|
|
453
|
+
AS $body$
|
|
454
|
+
DECLARE
|
|
455
|
+
session_row sessions%%ROWTYPE;
|
|
456
|
+
turn_row session_turns%%ROWTYPE;
|
|
457
|
+
attempt_row session_turn_attempts%%ROWTYPE;
|
|
458
|
+
member_row organization_memberships%%ROWTYPE;
|
|
459
|
+
document_row record;
|
|
460
|
+
grant_row organization_user_resource_grants%%ROWTYPE;
|
|
461
|
+
existing_count integer;
|
|
462
|
+
admitted_count integer := 0;
|
|
463
|
+
initiating_subject text;
|
|
464
|
+
affected integer;
|
|
465
|
+
BEGIN
|
|
466
|
+
INSERT INTO opengeni_private.personal_document_authority_capabilities (
|
|
467
|
+
backend_pid, transaction_id, capability_kind
|
|
468
|
+
) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'admit')
|
|
469
|
+
ON CONFLICT DO NOTHING;
|
|
470
|
+
|
|
471
|
+
SELECT attempt.* INTO STRICT attempt_row
|
|
472
|
+
FROM session_turn_attempts attempt
|
|
473
|
+
WHERE attempt.id = p_attempt_id
|
|
474
|
+
AND attempt.account_id = p_account_id
|
|
475
|
+
AND attempt.workspace_id = p_workspace_id
|
|
476
|
+
AND attempt.session_id = p_session_id
|
|
477
|
+
FOR UPDATE;
|
|
478
|
+
SELECT session_value.* INTO STRICT session_row
|
|
479
|
+
FROM sessions session_value
|
|
480
|
+
WHERE session_value.id = attempt_row.session_id
|
|
481
|
+
AND session_value.account_id = attempt_row.account_id
|
|
482
|
+
AND session_value.workspace_id = attempt_row.workspace_id
|
|
483
|
+
FOR SHARE;
|
|
484
|
+
SELECT turn_value.* INTO STRICT turn_row
|
|
485
|
+
FROM session_turns turn_value
|
|
486
|
+
WHERE turn_value.id = attempt_row.turn_id
|
|
487
|
+
AND turn_value.account_id = attempt_row.account_id
|
|
488
|
+
AND turn_value.workspace_id = attempt_row.workspace_id
|
|
489
|
+
AND turn_value.session_id = attempt_row.session_id
|
|
490
|
+
FOR SHARE;
|
|
491
|
+
|
|
492
|
+
IF attempt_row.execution_generation <= 0
|
|
493
|
+
OR attempt_row.state NOT IN ('claimed', 'running')
|
|
494
|
+
OR attempt_row.closed_at IS NOT NULL
|
|
495
|
+
OR attempt_row.quiesced_at IS NOT NULL
|
|
496
|
+
OR session_row.active_turn_id IS DISTINCT FROM attempt_row.turn_id
|
|
497
|
+
OR turn_row.active_attempt_id IS DISTINCT FROM attempt_row.id
|
|
498
|
+
OR turn_row.execution_generation IS DISTINCT FROM attempt_row.execution_generation
|
|
499
|
+
OR turn_row.status <> 'running'
|
|
500
|
+
OR attempt_row.authority_visibility IS DISTINCT FROM session_row.visibility
|
|
501
|
+
OR attempt_row.authority_epoch IS DISTINCT FROM session_row.authority_epoch
|
|
502
|
+
OR EXISTS (
|
|
503
|
+
SELECT 1 FROM session_attempt_interruptions interruption
|
|
504
|
+
WHERE interruption.account_id = p_account_id
|
|
505
|
+
AND interruption.workspace_id = p_workspace_id
|
|
506
|
+
AND interruption.session_id = p_session_id
|
|
507
|
+
AND interruption.attempt_id = p_attempt_id
|
|
508
|
+
AND interruption.state IN ('pending', 'delivered', 'acknowledged')
|
|
509
|
+
)
|
|
510
|
+
THEN
|
|
511
|
+
RAISE EXCEPTION 'personal document admission requires the exact current uninterrupted attempt'
|
|
512
|
+
USING ERRCODE = '42501';
|
|
513
|
+
END IF;
|
|
514
|
+
|
|
515
|
+
initiating_subject := coalesce(
|
|
516
|
+
nullif(btrim(turn_row.initiating_human_subject_id), ''),
|
|
517
|
+
CASE WHEN turn_row.initiator_kind = 'subject'
|
|
518
|
+
THEN nullif(btrim(turn_row.initiator_subject_id), '') END
|
|
519
|
+
);
|
|
520
|
+
IF initiating_subject IS NULL THEN
|
|
521
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
522
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
523
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
524
|
+
AND capability_kind = 'admit';
|
|
525
|
+
RETURN 0;
|
|
526
|
+
END IF;
|
|
527
|
+
|
|
528
|
+
SELECT membership.* INTO member_row
|
|
529
|
+
FROM organization_memberships membership
|
|
530
|
+
WHERE membership.account_id = p_account_id
|
|
531
|
+
AND membership.subject_id = initiating_subject
|
|
532
|
+
AND membership.status = 'active'
|
|
533
|
+
AND membership.revoked_at IS NULL
|
|
534
|
+
FOR SHARE;
|
|
535
|
+
IF NOT FOUND THEN
|
|
536
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
537
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
538
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
539
|
+
AND capability_kind = 'admit';
|
|
540
|
+
RETURN 0;
|
|
541
|
+
END IF;
|
|
542
|
+
IF member_row.personal_workspace_id IS DISTINCT FROM p_workspace_id THEN
|
|
543
|
+
PERFORM 1 FROM workspace_memberships workspace_membership
|
|
544
|
+
WHERE workspace_membership.account_id = p_account_id
|
|
545
|
+
AND workspace_membership.workspace_id = p_workspace_id
|
|
546
|
+
AND workspace_membership.subject_id = initiating_subject
|
|
547
|
+
FOR KEY SHARE;
|
|
548
|
+
IF NOT FOUND THEN
|
|
549
|
+
RAISE EXCEPTION 'initiating human lacks target-workspace membership'
|
|
550
|
+
USING ERRCODE = '42501';
|
|
551
|
+
END IF;
|
|
552
|
+
END IF;
|
|
553
|
+
|
|
554
|
+
SELECT admission.document_count INTO existing_count
|
|
555
|
+
FROM session_attempt_personal_document_admissions admission
|
|
556
|
+
WHERE admission.attempt_id = p_attempt_id;
|
|
557
|
+
IF FOUND THEN
|
|
558
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
559
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
560
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
561
|
+
AND capability_kind = 'admit';
|
|
562
|
+
RETURN existing_count;
|
|
563
|
+
END IF;
|
|
564
|
+
|
|
565
|
+
INSERT INTO session_attempt_personal_document_admissions (
|
|
566
|
+
attempt_id, account_id, workspace_id, session_id, turn_id,
|
|
567
|
+
execution_generation, initiating_human_subject_id,
|
|
568
|
+
owner_organization_membership_id, membership_authorization_revision,
|
|
569
|
+
session_visibility, session_authority_epoch, document_count
|
|
570
|
+
) VALUES (
|
|
571
|
+
p_attempt_id, p_account_id, p_workspace_id, p_session_id, attempt_row.turn_id,
|
|
572
|
+
attempt_row.execution_generation, initiating_subject, member_row.id,
|
|
573
|
+
member_row.authorization_revision, session_row.visibility,
|
|
574
|
+
session_row.authority_epoch, 0
|
|
575
|
+
) ON CONFLICT (attempt_id) DO NOTHING;
|
|
576
|
+
IF NOT FOUND THEN
|
|
577
|
+
SELECT admission.document_count INTO STRICT existing_count
|
|
578
|
+
FROM session_attempt_personal_document_admissions admission
|
|
579
|
+
WHERE admission.attempt_id = p_attempt_id;
|
|
580
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
581
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
582
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
583
|
+
AND capability_kind = 'admit';
|
|
584
|
+
RETURN existing_count;
|
|
585
|
+
END IF;
|
|
586
|
+
|
|
587
|
+
FOR document_row IN
|
|
588
|
+
SELECT document_value.id, document_value.authority_id,
|
|
589
|
+
authority.generation AS authority_generation
|
|
590
|
+
FROM documents document_value
|
|
591
|
+
JOIN organization_user_resource_authorities authority
|
|
592
|
+
ON authority.id = document_value.authority_id
|
|
593
|
+
AND authority.account_id = document_value.account_id
|
|
594
|
+
AND authority.organization_membership_id
|
|
595
|
+
= document_value.owner_organization_membership_id
|
|
596
|
+
AND authority.resource_kind = 'document'
|
|
597
|
+
AND authority.resource_id = document_value.id
|
|
598
|
+
AND authority.status = 'active'
|
|
599
|
+
AND authority.revoked_at IS NULL
|
|
600
|
+
WHERE document_value.account_id = p_account_id
|
|
601
|
+
AND document_value.authority_kind = 'personal'
|
|
602
|
+
AND document_value.authority_workspace_id IS NULL
|
|
603
|
+
AND document_value.authority_subject_id = initiating_subject
|
|
604
|
+
AND document_value.owner_organization_membership_id = member_row.id
|
|
605
|
+
AND document_value.status = 'ready'
|
|
606
|
+
AND document_value.agent_access = true
|
|
607
|
+
ORDER BY document_value.id
|
|
608
|
+
FOR SHARE OF document_value, authority
|
|
609
|
+
LOOP
|
|
610
|
+
SELECT grant_value.* INTO grant_row
|
|
611
|
+
FROM organization_user_resource_grants grant_value
|
|
612
|
+
WHERE grant_value.account_id = p_account_id
|
|
613
|
+
AND grant_value.authority_id = document_row.authority_id
|
|
614
|
+
AND grant_value.owner_organization_membership_id = member_row.id
|
|
615
|
+
AND grant_value.workspace_id = p_workspace_id
|
|
616
|
+
AND grant_value.action = 'document.read'
|
|
617
|
+
AND grant_value.context = session_row.visibility
|
|
618
|
+
AND grant_value.status = 'active'
|
|
619
|
+
AND (grant_value.expires_at IS NULL OR grant_value.expires_at > clock_timestamp())
|
|
620
|
+
AND (
|
|
621
|
+
(
|
|
622
|
+
grant_value.mode IN ('once', 'session')
|
|
623
|
+
AND grant_value.session_id = p_session_id
|
|
624
|
+
AND grant_value.authority_epoch = session_row.authority_epoch
|
|
625
|
+
) OR (
|
|
626
|
+
grant_value.mode = 'always'
|
|
627
|
+
AND grant_value.session_id IS NULL
|
|
628
|
+
AND grant_value.authority_epoch IS NULL
|
|
629
|
+
)
|
|
630
|
+
)
|
|
631
|
+
ORDER BY CASE grant_value.mode WHEN 'once' THEN 1 WHEN 'session' THEN 2 ELSE 3 END,
|
|
632
|
+
grant_value.generation DESC, grant_value.id
|
|
633
|
+
LIMIT 1
|
|
634
|
+
FOR UPDATE;
|
|
635
|
+
IF NOT FOUND THEN CONTINUE; END IF;
|
|
636
|
+
|
|
637
|
+
INSERT INTO session_attempt_personal_document_snapshots (
|
|
638
|
+
attempt_id, document_id, account_id, workspace_id, session_id, turn_id,
|
|
639
|
+
execution_generation, owner_organization_membership_id,
|
|
640
|
+
membership_authorization_revision, authority_id, authority_generation,
|
|
641
|
+
target_workspace_id, session_visibility, session_authority_epoch,
|
|
642
|
+
grant_id, grant_generation, grant_mode, grant_context,
|
|
643
|
+
grant_session_id, grant_authority_epoch
|
|
644
|
+
) VALUES (
|
|
645
|
+
p_attempt_id, document_row.id, p_account_id, p_workspace_id, p_session_id,
|
|
646
|
+
attempt_row.turn_id, attempt_row.execution_generation, member_row.id,
|
|
647
|
+
member_row.authorization_revision, document_row.authority_id,
|
|
648
|
+
document_row.authority_generation, p_workspace_id, session_row.visibility,
|
|
649
|
+
session_row.authority_epoch, grant_row.id, grant_row.generation,
|
|
650
|
+
grant_row.mode, grant_row.context, grant_row.session_id,
|
|
651
|
+
grant_row.authority_epoch
|
|
652
|
+
);
|
|
653
|
+
|
|
654
|
+
IF grant_row.mode = 'once' THEN
|
|
655
|
+
UPDATE organization_user_resource_grants
|
|
656
|
+
SET status = 'consumed', updated_at = clock_timestamp()
|
|
657
|
+
WHERE id = grant_row.id AND account_id = p_account_id
|
|
658
|
+
AND generation = grant_row.generation AND status = 'active';
|
|
659
|
+
GET DIAGNOSTICS affected = ROW_COUNT;
|
|
660
|
+
IF affected <> 1 THEN
|
|
661
|
+
RAISE EXCEPTION 'once document grant lost its first-use race'
|
|
662
|
+
USING ERRCODE = '40001';
|
|
663
|
+
END IF;
|
|
664
|
+
INSERT INTO personal_document_once_consumption_receipts (
|
|
665
|
+
grant_id, account_id, attempt_id, document_id, authority_id,
|
|
666
|
+
authority_generation, grant_generation
|
|
667
|
+
) VALUES (
|
|
668
|
+
grant_row.id, p_account_id, p_attempt_id, document_row.id,
|
|
669
|
+
document_row.authority_id, document_row.authority_generation,
|
|
670
|
+
grant_row.generation
|
|
671
|
+
);
|
|
672
|
+
END IF;
|
|
673
|
+
admitted_count := admitted_count + 1;
|
|
674
|
+
END LOOP;
|
|
675
|
+
|
|
676
|
+
UPDATE session_attempt_personal_document_admissions
|
|
677
|
+
SET document_count = admitted_count
|
|
678
|
+
WHERE attempt_id = p_attempt_id;
|
|
679
|
+
|
|
680
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
681
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
682
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
683
|
+
AND capability_kind = 'admit';
|
|
684
|
+
RETURN admitted_count;
|
|
685
|
+
EXCEPTION WHEN OTHERS THEN
|
|
686
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
687
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
688
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
689
|
+
AND capability_kind = 'admit';
|
|
690
|
+
RAISE;
|
|
691
|
+
END
|
|
692
|
+
$body$;
|
|
693
|
+
$ddl$, data_schema);
|
|
694
|
+
|
|
695
|
+
EXECUTE format($ddl$
|
|
696
|
+
CREATE OR REPLACE FUNCTION %1$I.resolve_session_attempt_personal_document_reads(
|
|
697
|
+
p_account_id uuid,
|
|
698
|
+
p_workspace_id uuid,
|
|
699
|
+
p_session_id uuid,
|
|
700
|
+
p_attempt_id uuid
|
|
701
|
+
) RETURNS SETOF uuid
|
|
702
|
+
LANGUAGE plpgsql
|
|
703
|
+
SECURITY DEFINER
|
|
704
|
+
SET search_path = %1$I, pg_catalog
|
|
705
|
+
AS $body$
|
|
706
|
+
DECLARE
|
|
707
|
+
admission_row session_attempt_personal_document_admissions%%ROWTYPE;
|
|
708
|
+
invalid_count integer;
|
|
709
|
+
actual_count integer;
|
|
710
|
+
caller_subject text := coalesce(
|
|
711
|
+
nullif(pg_catalog.current_setting('opengeni.initiating_human_subject_id', true), ''),
|
|
712
|
+
nullif(pg_catalog.current_setting('opengeni.subject_id', true), '')
|
|
713
|
+
);
|
|
714
|
+
BEGIN
|
|
715
|
+
IF p_account_id IS DISTINCT FROM nullif(
|
|
716
|
+
pg_catalog.current_setting('opengeni.account_id', true), ''
|
|
717
|
+
)::uuid
|
|
718
|
+
OR p_workspace_id IS DISTINCT FROM nullif(
|
|
719
|
+
pg_catalog.current_setting('opengeni.workspace_id', true), ''
|
|
720
|
+
)::uuid
|
|
721
|
+
THEN
|
|
722
|
+
RAISE EXCEPTION 'personal document resolve scope mismatch' USING ERRCODE = '42501';
|
|
723
|
+
END IF;
|
|
724
|
+
|
|
725
|
+
INSERT INTO opengeni_private.personal_document_authority_capabilities (
|
|
726
|
+
backend_pid, transaction_id, capability_kind
|
|
727
|
+
) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'resolve')
|
|
728
|
+
ON CONFLICT DO NOTHING;
|
|
729
|
+
|
|
730
|
+
SELECT admission.* INTO admission_row
|
|
731
|
+
FROM session_attempt_personal_document_admissions admission
|
|
732
|
+
WHERE admission.attempt_id = p_attempt_id
|
|
733
|
+
AND admission.account_id = p_account_id
|
|
734
|
+
AND admission.workspace_id = p_workspace_id
|
|
735
|
+
AND admission.session_id = p_session_id;
|
|
736
|
+
IF NOT FOUND THEN
|
|
737
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
738
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
739
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
740
|
+
AND capability_kind = 'resolve';
|
|
741
|
+
RETURN;
|
|
742
|
+
END IF;
|
|
743
|
+
|
|
744
|
+
IF caller_subject IS DISTINCT FROM admission_row.initiating_human_subject_id THEN
|
|
745
|
+
RAISE EXCEPTION 'personal document resolve initiating human mismatch'
|
|
746
|
+
USING ERRCODE = '42501';
|
|
747
|
+
END IF;
|
|
748
|
+
|
|
749
|
+
SELECT count(*)::integer INTO invalid_count
|
|
750
|
+
FROM session_attempt_personal_document_snapshots snapshot
|
|
751
|
+
WHERE snapshot.attempt_id = p_attempt_id
|
|
752
|
+
AND NOT (
|
|
753
|
+
EXISTS (
|
|
754
|
+
SELECT 1
|
|
755
|
+
FROM session_turn_attempts attempt
|
|
756
|
+
JOIN sessions session_value
|
|
757
|
+
ON session_value.id = attempt.session_id
|
|
758
|
+
AND session_value.account_id = attempt.account_id
|
|
759
|
+
AND session_value.workspace_id = attempt.workspace_id
|
|
760
|
+
JOIN session_turns turn_value
|
|
761
|
+
ON turn_value.id = attempt.turn_id
|
|
762
|
+
AND turn_value.account_id = attempt.account_id
|
|
763
|
+
AND turn_value.workspace_id = attempt.workspace_id
|
|
764
|
+
AND turn_value.session_id = attempt.session_id
|
|
765
|
+
WHERE attempt.id = snapshot.attempt_id
|
|
766
|
+
AND attempt.account_id = snapshot.account_id
|
|
767
|
+
AND attempt.workspace_id = snapshot.workspace_id
|
|
768
|
+
AND attempt.session_id = snapshot.session_id
|
|
769
|
+
AND attempt.turn_id = snapshot.turn_id
|
|
770
|
+
AND attempt.execution_generation = snapshot.execution_generation
|
|
771
|
+
AND attempt.state IN ('claimed', 'running')
|
|
772
|
+
AND attempt.closed_at IS NULL
|
|
773
|
+
AND attempt.quiesced_at IS NULL
|
|
774
|
+
AND session_value.active_turn_id = snapshot.turn_id
|
|
775
|
+
AND turn_value.active_attempt_id = snapshot.attempt_id
|
|
776
|
+
AND turn_value.execution_generation = snapshot.execution_generation
|
|
777
|
+
AND turn_value.status = 'running'
|
|
778
|
+
AND session_value.visibility = snapshot.session_visibility
|
|
779
|
+
AND session_value.authority_epoch = snapshot.session_authority_epoch
|
|
780
|
+
)
|
|
781
|
+
AND NOT EXISTS (
|
|
782
|
+
SELECT 1 FROM session_attempt_interruptions interruption
|
|
783
|
+
WHERE interruption.account_id = snapshot.account_id
|
|
784
|
+
AND interruption.workspace_id = snapshot.workspace_id
|
|
785
|
+
AND interruption.session_id = snapshot.session_id
|
|
786
|
+
AND interruption.attempt_id = snapshot.attempt_id
|
|
787
|
+
AND interruption.state IN ('pending', 'delivered', 'acknowledged')
|
|
788
|
+
)
|
|
789
|
+
AND EXISTS (
|
|
790
|
+
SELECT 1 FROM organization_memberships membership
|
|
791
|
+
WHERE membership.id = snapshot.owner_organization_membership_id
|
|
792
|
+
AND membership.account_id = snapshot.account_id
|
|
793
|
+
AND membership.subject_id = admission_row.initiating_human_subject_id
|
|
794
|
+
AND membership.status = 'active'
|
|
795
|
+
AND membership.revoked_at IS NULL
|
|
796
|
+
AND membership.authorization_revision
|
|
797
|
+
= snapshot.membership_authorization_revision
|
|
798
|
+
AND (
|
|
799
|
+
membership.personal_workspace_id = snapshot.workspace_id
|
|
800
|
+
OR EXISTS (
|
|
801
|
+
SELECT 1 FROM workspace_memberships workspace_membership
|
|
802
|
+
WHERE workspace_membership.account_id = membership.account_id
|
|
803
|
+
AND workspace_membership.workspace_id = snapshot.workspace_id
|
|
804
|
+
AND workspace_membership.subject_id = membership.subject_id
|
|
805
|
+
)
|
|
806
|
+
)
|
|
807
|
+
)
|
|
808
|
+
AND EXISTS (
|
|
809
|
+
SELECT 1
|
|
810
|
+
FROM documents document_value
|
|
811
|
+
JOIN organization_user_resource_authorities authority
|
|
812
|
+
ON authority.id = document_value.authority_id
|
|
813
|
+
AND authority.account_id = document_value.account_id
|
|
814
|
+
AND authority.organization_membership_id
|
|
815
|
+
= document_value.owner_organization_membership_id
|
|
816
|
+
WHERE document_value.id = snapshot.document_id
|
|
817
|
+
AND document_value.account_id = snapshot.account_id
|
|
818
|
+
AND document_value.authority_kind = 'personal'
|
|
819
|
+
AND document_value.authority_workspace_id IS NULL
|
|
820
|
+
AND document_value.authority_subject_id
|
|
821
|
+
= admission_row.initiating_human_subject_id
|
|
822
|
+
AND document_value.owner_organization_membership_id
|
|
823
|
+
= snapshot.owner_organization_membership_id
|
|
824
|
+
AND document_value.authority_id = snapshot.authority_id
|
|
825
|
+
AND document_value.status = 'ready'
|
|
826
|
+
AND document_value.agent_access = true
|
|
827
|
+
AND authority.resource_kind = 'document'
|
|
828
|
+
AND authority.resource_id = document_value.id
|
|
829
|
+
AND authority.generation = snapshot.authority_generation
|
|
830
|
+
AND authority.status = 'active'
|
|
831
|
+
AND authority.revoked_at IS NULL
|
|
832
|
+
)
|
|
833
|
+
AND EXISTS (
|
|
834
|
+
SELECT 1 FROM organization_user_resource_grants grant_value
|
|
835
|
+
WHERE grant_value.id = snapshot.grant_id
|
|
836
|
+
AND grant_value.account_id = snapshot.account_id
|
|
837
|
+
AND grant_value.authority_id = snapshot.authority_id
|
|
838
|
+
AND grant_value.owner_organization_membership_id
|
|
839
|
+
= snapshot.owner_organization_membership_id
|
|
840
|
+
AND grant_value.workspace_id = snapshot.target_workspace_id
|
|
841
|
+
AND grant_value.action = 'document.read'
|
|
842
|
+
AND grant_value.mode = snapshot.grant_mode
|
|
843
|
+
AND grant_value.context = snapshot.grant_context
|
|
844
|
+
AND grant_value.generation = snapshot.grant_generation
|
|
845
|
+
AND grant_value.session_id IS NOT DISTINCT FROM snapshot.grant_session_id
|
|
846
|
+
AND grant_value.authority_epoch
|
|
847
|
+
IS NOT DISTINCT FROM snapshot.grant_authority_epoch
|
|
848
|
+
AND (grant_value.expires_at IS NULL OR grant_value.expires_at > clock_timestamp())
|
|
849
|
+
AND (
|
|
850
|
+
(
|
|
851
|
+
snapshot.grant_mode = 'once'
|
|
852
|
+
AND grant_value.status = 'consumed'
|
|
853
|
+
AND EXISTS (
|
|
854
|
+
SELECT 1 FROM personal_document_once_consumption_receipts receipt
|
|
855
|
+
WHERE receipt.grant_id = snapshot.grant_id
|
|
856
|
+
AND receipt.account_id = snapshot.account_id
|
|
857
|
+
AND receipt.attempt_id = snapshot.attempt_id
|
|
858
|
+
AND receipt.document_id = snapshot.document_id
|
|
859
|
+
AND receipt.authority_id = snapshot.authority_id
|
|
860
|
+
AND receipt.authority_generation = snapshot.authority_generation
|
|
861
|
+
AND receipt.grant_generation = snapshot.grant_generation
|
|
862
|
+
)
|
|
863
|
+
) OR (
|
|
864
|
+
snapshot.grant_mode IN ('session', 'always')
|
|
865
|
+
AND grant_value.status = 'active'
|
|
866
|
+
)
|
|
867
|
+
)
|
|
868
|
+
)
|
|
869
|
+
);
|
|
870
|
+
IF invalid_count <> 0 THEN
|
|
871
|
+
RAISE EXCEPTION 'personal document authority snapshot is no longer live'
|
|
872
|
+
USING ERRCODE = '42501';
|
|
873
|
+
END IF;
|
|
874
|
+
|
|
875
|
+
SELECT count(*)::integer INTO actual_count
|
|
876
|
+
FROM session_attempt_personal_document_snapshots snapshot
|
|
877
|
+
WHERE snapshot.attempt_id = p_attempt_id;
|
|
878
|
+
IF actual_count <> admission_row.document_count THEN
|
|
879
|
+
RAISE EXCEPTION 'personal document snapshot collection is incomplete'
|
|
880
|
+
USING ERRCODE = '42501';
|
|
881
|
+
END IF;
|
|
882
|
+
|
|
883
|
+
RETURN QUERY
|
|
884
|
+
SELECT snapshot.document_id
|
|
885
|
+
FROM session_attempt_personal_document_snapshots snapshot
|
|
886
|
+
WHERE snapshot.attempt_id = p_attempt_id
|
|
887
|
+
ORDER BY snapshot.document_id;
|
|
888
|
+
|
|
889
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
890
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
891
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
892
|
+
AND capability_kind = 'resolve';
|
|
893
|
+
RETURN;
|
|
894
|
+
EXCEPTION WHEN OTHERS THEN
|
|
895
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
896
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
897
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
898
|
+
AND capability_kind = 'resolve';
|
|
899
|
+
RAISE;
|
|
900
|
+
END
|
|
901
|
+
$body$;
|
|
902
|
+
$ddl$, data_schema);
|
|
903
|
+
|
|
904
|
+
EXECUTE format($ddl$
|
|
905
|
+
CREATE OR REPLACE FUNCTION %1$I.resolve_document_original_file(
|
|
906
|
+
p_account_id uuid,
|
|
907
|
+
p_request_workspace_id uuid,
|
|
908
|
+
p_actor_id text,
|
|
909
|
+
p_document_id uuid
|
|
910
|
+
) RETURNS SETOF %1$I.files
|
|
911
|
+
LANGUAGE plpgsql
|
|
912
|
+
SECURITY DEFINER
|
|
913
|
+
SET search_path = %1$I, pg_catalog
|
|
914
|
+
AS $body$
|
|
915
|
+
DECLARE
|
|
916
|
+
document_row %1$I.documents%%ROWTYPE;
|
|
917
|
+
authority_row %1$I.organization_user_resource_authorities%%ROWTYPE;
|
|
918
|
+
owner_membership_row %1$I.organization_memberships%%ROWTYPE;
|
|
919
|
+
BEGIN
|
|
920
|
+
IF p_account_id IS DISTINCT FROM nullif(
|
|
921
|
+
pg_catalog.current_setting('opengeni.account_id', true), ''
|
|
922
|
+
)::uuid
|
|
923
|
+
OR p_request_workspace_id IS DISTINCT FROM nullif(
|
|
924
|
+
pg_catalog.current_setting('opengeni.workspace_id', true), ''
|
|
925
|
+
)::uuid
|
|
926
|
+
OR p_actor_id IS NULL
|
|
927
|
+
OR p_actor_id IS DISTINCT FROM nullif(
|
|
928
|
+
pg_catalog.current_setting('opengeni.subject_id', true), ''
|
|
929
|
+
)
|
|
930
|
+
OR p_document_id IS NULL
|
|
931
|
+
THEN
|
|
932
|
+
RAISE EXCEPTION 'document original-file scope mismatch' USING ERRCODE = '42501';
|
|
933
|
+
END IF;
|
|
934
|
+
|
|
935
|
+
INSERT INTO opengeni_private.personal_document_authority_capabilities (
|
|
936
|
+
backend_pid, transaction_id, capability_kind
|
|
937
|
+
) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'resolve')
|
|
938
|
+
ON CONFLICT DO NOTHING;
|
|
939
|
+
|
|
940
|
+
SELECT document_value.* INTO document_row
|
|
941
|
+
FROM %1$I.documents document_value
|
|
942
|
+
WHERE document_value.id = p_document_id
|
|
943
|
+
AND document_value.account_id = p_account_id
|
|
944
|
+
AND (
|
|
945
|
+
(
|
|
946
|
+
document_value.authority_kind = 'organization'
|
|
947
|
+
AND document_value.authority_workspace_id IS NULL
|
|
948
|
+
AND document_value.authority_subject_id IS NULL
|
|
949
|
+
) OR (
|
|
950
|
+
document_value.authority_kind = 'workspace'
|
|
951
|
+
AND document_value.authority_workspace_id = p_request_workspace_id
|
|
952
|
+
AND document_value.authority_subject_id IS NULL
|
|
953
|
+
) OR (
|
|
954
|
+
document_value.authority_kind = 'personal'
|
|
955
|
+
AND document_value.authority_subject_id = p_actor_id
|
|
956
|
+
AND (
|
|
957
|
+
(
|
|
958
|
+
document_value.authority_id IS NULL
|
|
959
|
+
AND document_value.owner_organization_membership_id IS NULL
|
|
960
|
+
AND document_value.authority_workspace_id = p_request_workspace_id
|
|
961
|
+
) OR (
|
|
962
|
+
document_value.authority_id IS NOT NULL
|
|
963
|
+
AND document_value.owner_organization_membership_id IS NOT NULL
|
|
964
|
+
AND document_value.authority_workspace_id IS NULL
|
|
965
|
+
)
|
|
966
|
+
)
|
|
967
|
+
)
|
|
968
|
+
)
|
|
969
|
+
FOR SHARE;
|
|
970
|
+
IF NOT FOUND THEN
|
|
971
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
972
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
973
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
974
|
+
AND capability_kind = 'resolve';
|
|
975
|
+
RETURN;
|
|
976
|
+
END IF;
|
|
977
|
+
|
|
978
|
+
IF document_row.authority_kind = 'personal' AND document_row.authority_id IS NOT NULL THEN
|
|
979
|
+
SELECT authority.* INTO authority_row
|
|
980
|
+
FROM %1$I.organization_user_resource_authorities authority
|
|
981
|
+
WHERE authority.id = document_row.authority_id
|
|
982
|
+
AND authority.account_id = document_row.account_id
|
|
983
|
+
AND authority.organization_membership_id
|
|
984
|
+
= document_row.owner_organization_membership_id
|
|
985
|
+
AND authority.resource_kind = 'document'
|
|
986
|
+
AND authority.resource_id = document_row.id
|
|
987
|
+
AND authority.status = 'active'
|
|
988
|
+
AND authority.revoked_at IS NULL
|
|
989
|
+
FOR SHARE;
|
|
990
|
+
IF NOT FOUND THEN
|
|
991
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
992
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
993
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
994
|
+
AND capability_kind = 'resolve';
|
|
995
|
+
RETURN;
|
|
996
|
+
END IF;
|
|
997
|
+
|
|
998
|
+
SELECT membership.* INTO owner_membership_row
|
|
999
|
+
FROM %1$I.organization_memberships membership
|
|
1000
|
+
WHERE membership.id = authority_row.organization_membership_id
|
|
1001
|
+
AND membership.account_id = authority_row.account_id
|
|
1002
|
+
AND membership.subject_id = p_actor_id
|
|
1003
|
+
AND membership.status = 'active'
|
|
1004
|
+
AND membership.revoked_at IS NULL
|
|
1005
|
+
FOR SHARE;
|
|
1006
|
+
IF NOT FOUND THEN
|
|
1007
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
1008
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
1009
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
1010
|
+
AND capability_kind = 'resolve';
|
|
1011
|
+
RETURN;
|
|
1012
|
+
END IF;
|
|
1013
|
+
|
|
1014
|
+
IF owner_membership_row.personal_workspace_id IS DISTINCT FROM p_request_workspace_id THEN
|
|
1015
|
+
PERFORM 1
|
|
1016
|
+
FROM %1$I.workspace_memberships workspace_membership
|
|
1017
|
+
WHERE workspace_membership.account_id = p_account_id
|
|
1018
|
+
AND workspace_membership.workspace_id = p_request_workspace_id
|
|
1019
|
+
AND workspace_membership.subject_id = p_actor_id
|
|
1020
|
+
FOR SHARE;
|
|
1021
|
+
IF NOT FOUND THEN
|
|
1022
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
1023
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
1024
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
1025
|
+
AND capability_kind = 'resolve';
|
|
1026
|
+
RETURN;
|
|
1027
|
+
END IF;
|
|
1028
|
+
END IF;
|
|
1029
|
+
END IF;
|
|
1030
|
+
|
|
1031
|
+
RETURN QUERY
|
|
1032
|
+
SELECT file_value.*
|
|
1033
|
+
FROM %1$I.files file_value
|
|
1034
|
+
WHERE file_value.id = document_row.file_id
|
|
1035
|
+
AND file_value.account_id = document_row.account_id
|
|
1036
|
+
AND file_value.workspace_id = document_row.origin_workspace_id
|
|
1037
|
+
AND %1$I.google_drive_file_authorized(
|
|
1038
|
+
p_account_id, p_request_workspace_id, p_actor_id, file_value.id
|
|
1039
|
+
)
|
|
1040
|
+
FOR SHARE;
|
|
1041
|
+
|
|
1042
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
1043
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
1044
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
1045
|
+
AND capability_kind = 'resolve';
|
|
1046
|
+
RETURN;
|
|
1047
|
+
EXCEPTION WHEN OTHERS THEN
|
|
1048
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
1049
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
1050
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
1051
|
+
AND capability_kind = 'resolve';
|
|
1052
|
+
RAISE;
|
|
1053
|
+
END
|
|
1054
|
+
$body$;
|
|
1055
|
+
$ddl$, data_schema);
|
|
1056
|
+
|
|
1057
|
+
EXECUTE format($ddl$
|
|
1058
|
+
CREATE OR REPLACE FUNCTION %1$I.admit_session_attempt_personal_documents()
|
|
1059
|
+
RETURNS trigger
|
|
1060
|
+
LANGUAGE plpgsql
|
|
1061
|
+
SECURITY DEFINER
|
|
1062
|
+
SET search_path = %1$I, pg_catalog
|
|
1063
|
+
AS $body$
|
|
1064
|
+
BEGIN
|
|
1065
|
+
PERFORM prepare_session_attempt_personal_document_reads(
|
|
1066
|
+
NEW.account_id, NEW.workspace_id, NEW.session_id, NEW.id
|
|
1067
|
+
);
|
|
1068
|
+
RETURN NEW;
|
|
1069
|
+
END
|
|
1070
|
+
$body$;
|
|
1071
|
+
$ddl$, data_schema);
|
|
1072
|
+
|
|
1073
|
+
EXECUTE format($ddl$
|
|
1074
|
+
CREATE OR REPLACE FUNCTION opengeni_private.apply_document_authority()
|
|
1075
|
+
RETURNS trigger
|
|
1076
|
+
LANGUAGE plpgsql
|
|
1077
|
+
SET search_path = %1$I, pg_catalog
|
|
1078
|
+
AS $body$
|
|
1079
|
+
BEGIN
|
|
1080
|
+
IF TG_OP = 'UPDATE' AND (
|
|
1081
|
+
NEW.authority_kind IS DISTINCT FROM OLD.authority_kind
|
|
1082
|
+
OR NEW.authority_workspace_id IS DISTINCT FROM OLD.authority_workspace_id
|
|
1083
|
+
OR NEW.authority_subject_id IS DISTINCT FROM OLD.authority_subject_id
|
|
1084
|
+
OR NEW.authority_id IS DISTINCT FROM OLD.authority_id
|
|
1085
|
+
OR NEW.owner_organization_membership_id
|
|
1086
|
+
IS DISTINCT FROM OLD.owner_organization_membership_id
|
|
1087
|
+
OR NEW.origin_workspace_id IS DISTINCT FROM OLD.origin_workspace_id
|
|
1088
|
+
OR NEW.created_by IS DISTINCT FROM OLD.created_by
|
|
1089
|
+
OR NEW.visibility IS DISTINCT FROM OLD.visibility
|
|
1090
|
+
) THEN
|
|
1091
|
+
RAISE EXCEPTION 'document authority is immutable';
|
|
1092
|
+
END IF;
|
|
1093
|
+
IF NEW.authority_kind IS NULL OR (
|
|
1094
|
+
NEW.authority_kind = 'workspace'
|
|
1095
|
+
AND NEW.authority_workspace_id IS NULL
|
|
1096
|
+
AND NEW.visibility = 'private'
|
|
1097
|
+
) THEN
|
|
1098
|
+
NEW.authority_kind := CASE
|
|
1099
|
+
WHEN NEW.visibility = 'private' THEN 'personal'
|
|
1100
|
+
ELSE 'workspace'
|
|
1101
|
+
END;
|
|
1102
|
+
END IF;
|
|
1103
|
+
NEW.origin_workspace_id := NEW.workspace_id;
|
|
1104
|
+
CASE NEW.authority_kind
|
|
1105
|
+
WHEN 'organization' THEN
|
|
1106
|
+
NEW.authority_workspace_id := NULL;
|
|
1107
|
+
NEW.authority_subject_id := NULL;
|
|
1108
|
+
NEW.authority_id := NULL;
|
|
1109
|
+
NEW.owner_organization_membership_id := NULL;
|
|
1110
|
+
NEW.visibility := 'workspace';
|
|
1111
|
+
WHEN 'workspace' THEN
|
|
1112
|
+
NEW.authority_workspace_id := NEW.workspace_id;
|
|
1113
|
+
NEW.authority_subject_id := NULL;
|
|
1114
|
+
NEW.authority_id := NULL;
|
|
1115
|
+
NEW.owner_organization_membership_id := NULL;
|
|
1116
|
+
NEW.visibility := 'workspace';
|
|
1117
|
+
WHEN 'personal' THEN
|
|
1118
|
+
NEW.authority_subject_id := coalesce(
|
|
1119
|
+
nullif(btrim(NEW.authority_subject_id), ''),
|
|
1120
|
+
nullif(btrim(NEW.created_by), '')
|
|
1121
|
+
);
|
|
1122
|
+
IF NEW.authority_id IS NULL THEN
|
|
1123
|
+
NEW.authority_workspace_id := NEW.workspace_id;
|
|
1124
|
+
NEW.owner_organization_membership_id := NULL;
|
|
1125
|
+
ELSE
|
|
1126
|
+
NEW.authority_workspace_id := NULL;
|
|
1127
|
+
END IF;
|
|
1128
|
+
NEW.visibility := 'private';
|
|
1129
|
+
ELSE
|
|
1130
|
+
RAISE EXCEPTION 'invalid document authority kind: %%', NEW.authority_kind;
|
|
1131
|
+
END CASE;
|
|
1132
|
+
RETURN NEW;
|
|
1133
|
+
END
|
|
1134
|
+
$body$;
|
|
1135
|
+
$ddl$, data_schema);
|
|
1136
|
+
|
|
1137
|
+
EXECUTE format($ddl$
|
|
1138
|
+
CREATE OR REPLACE FUNCTION opengeni_private.apply_document_chunk_authority()
|
|
1139
|
+
RETURNS trigger
|
|
1140
|
+
LANGUAGE plpgsql
|
|
1141
|
+
SET search_path = %1$I, pg_catalog
|
|
1142
|
+
AS $body$
|
|
1143
|
+
DECLARE parent %1$I.documents%%ROWTYPE;
|
|
1144
|
+
BEGIN
|
|
1145
|
+
IF TG_OP = 'UPDATE' AND (
|
|
1146
|
+
NEW.authority_kind IS DISTINCT FROM OLD.authority_kind
|
|
1147
|
+
OR NEW.authority_workspace_id IS DISTINCT FROM OLD.authority_workspace_id
|
|
1148
|
+
OR NEW.authority_subject_id IS DISTINCT FROM OLD.authority_subject_id
|
|
1149
|
+
OR NEW.authority_id IS DISTINCT FROM OLD.authority_id
|
|
1150
|
+
OR NEW.owner_organization_membership_id
|
|
1151
|
+
IS DISTINCT FROM OLD.owner_organization_membership_id
|
|
1152
|
+
OR NEW.document_id IS DISTINCT FROM OLD.document_id
|
|
1153
|
+
) THEN
|
|
1154
|
+
RAISE EXCEPTION 'document chunk authority is immutable';
|
|
1155
|
+
END IF;
|
|
1156
|
+
SELECT * INTO parent FROM %1$I.documents WHERE id = NEW.document_id;
|
|
1157
|
+
IF NOT FOUND
|
|
1158
|
+
OR parent.account_id IS DISTINCT FROM NEW.account_id
|
|
1159
|
+
OR parent.workspace_id IS DISTINCT FROM NEW.workspace_id
|
|
1160
|
+
OR parent.base_id IS DISTINCT FROM NEW.base_id
|
|
1161
|
+
OR parent.file_id IS DISTINCT FROM NEW.file_id
|
|
1162
|
+
THEN
|
|
1163
|
+
RAISE EXCEPTION 'document chunk parent identity mismatch';
|
|
1164
|
+
END IF;
|
|
1165
|
+
NEW.authority_kind := parent.authority_kind;
|
|
1166
|
+
NEW.authority_workspace_id := parent.authority_workspace_id;
|
|
1167
|
+
NEW.authority_subject_id := parent.authority_subject_id;
|
|
1168
|
+
NEW.authority_id := parent.authority_id;
|
|
1169
|
+
NEW.owner_organization_membership_id := parent.owner_organization_membership_id;
|
|
1170
|
+
RETURN NEW;
|
|
1171
|
+
END
|
|
1172
|
+
$body$;
|
|
1173
|
+
$ddl$, data_schema);
|
|
1174
|
+
|
|
1175
|
+
EXECUTE format($ddl$
|
|
1176
|
+
CREATE OR REPLACE FUNCTION %1$I.revoke_personal_document_authority_after_delete()
|
|
1177
|
+
RETURNS trigger
|
|
1178
|
+
LANGUAGE plpgsql
|
|
1179
|
+
SECURITY DEFINER
|
|
1180
|
+
SET search_path = %1$I, pg_catalog
|
|
1181
|
+
AS $body$
|
|
1182
|
+
BEGIN
|
|
1183
|
+
IF OLD.authority_kind <> 'personal' OR OLD.authority_id IS NULL THEN
|
|
1184
|
+
RETURN OLD;
|
|
1185
|
+
END IF;
|
|
1186
|
+
INSERT INTO opengeni_private.personal_document_authority_capabilities (
|
|
1187
|
+
backend_pid, transaction_id, capability_kind
|
|
1188
|
+
) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'write')
|
|
1189
|
+
ON CONFLICT DO NOTHING;
|
|
1190
|
+
UPDATE organization_user_resource_grants
|
|
1191
|
+
SET status = 'revoked', generation = generation + 1,
|
|
1192
|
+
revoked_at = coalesce(revoked_at, clock_timestamp()),
|
|
1193
|
+
updated_at = clock_timestamp()
|
|
1194
|
+
WHERE authority_id = OLD.authority_id AND account_id = OLD.account_id
|
|
1195
|
+
AND status IN ('active', 'consumed');
|
|
1196
|
+
UPDATE organization_user_resource_authorities
|
|
1197
|
+
SET status = 'revoked', generation = generation + 1,
|
|
1198
|
+
revoked_at = clock_timestamp(), updated_at = clock_timestamp()
|
|
1199
|
+
WHERE id = OLD.authority_id AND account_id = OLD.account_id
|
|
1200
|
+
AND status <> 'revoked';
|
|
1201
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
1202
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
1203
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
1204
|
+
AND capability_kind = 'write';
|
|
1205
|
+
RETURN OLD;
|
|
1206
|
+
EXCEPTION WHEN OTHERS THEN
|
|
1207
|
+
DELETE FROM opengeni_private.personal_document_authority_capabilities
|
|
1208
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
1209
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
1210
|
+
AND capability_kind = 'write';
|
|
1211
|
+
RAISE;
|
|
1212
|
+
END
|
|
1213
|
+
$body$;
|
|
1214
|
+
$ddl$, data_schema);
|
|
1215
|
+
END
|
|
1216
|
+
$personal_document_functions$;
|
|
1217
|
+
|
|
1218
|
+
DROP TRIGGER "documents_authority_guard" ON "documents";
|
|
1219
|
+
CREATE TRIGGER "documents_authority_guard"
|
|
1220
|
+
BEFORE INSERT OR UPDATE ON "documents"
|
|
1221
|
+
FOR EACH ROW EXECUTE FUNCTION opengeni_private.apply_document_authority();
|
|
1222
|
+
|
|
1223
|
+
DROP TRIGGER "document_chunks_authority_guard" ON "document_chunks";
|
|
1224
|
+
CREATE TRIGGER "document_chunks_authority_guard"
|
|
1225
|
+
BEFORE INSERT OR UPDATE ON "document_chunks"
|
|
1226
|
+
FOR EACH ROW EXECUTE FUNCTION opengeni_private.apply_document_chunk_authority();
|
|
1227
|
+
|
|
1228
|
+
CREATE TRIGGER "documents_personal_authority_revoke"
|
|
1229
|
+
AFTER DELETE ON "documents"
|
|
1230
|
+
FOR EACH ROW EXECUTE FUNCTION revoke_personal_document_authority_after_delete();
|
|
1231
|
+
|
|
1232
|
+
CREATE TRIGGER "session_attempt_personal_document_admission"
|
|
1233
|
+
AFTER INSERT ON "session_turn_attempts"
|
|
1234
|
+
FOR EACH ROW EXECUTE FUNCTION admit_session_attempt_personal_documents();
|
|
1235
|
+
|
|
1236
|
+
REVOKE ALL ON FUNCTION create_personal_document_authority(uuid, uuid, uuid) FROM PUBLIC;
|
|
1237
|
+
REVOKE ALL ON FUNCTION
|
|
1238
|
+
prepare_session_attempt_personal_document_reads(uuid, uuid, uuid, uuid) FROM PUBLIC;
|
|
1239
|
+
REVOKE ALL ON FUNCTION
|
|
1240
|
+
resolve_session_attempt_personal_document_reads(uuid, uuid, uuid, uuid) FROM PUBLIC;
|
|
1241
|
+
REVOKE ALL ON FUNCTION
|
|
1242
|
+
resolve_document_original_file(uuid, uuid, text, uuid) FROM PUBLIC;
|
|
1243
|
+
REVOKE ALL ON FUNCTION admit_session_attempt_personal_documents() FROM PUBLIC;
|
|
1244
|
+
|
|
1245
|
+
DO $personal_document_runtime_grants$
|
|
1246
|
+
BEGIN
|
|
1247
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
1248
|
+
GRANT EXECUTE ON FUNCTION
|
|
1249
|
+
opengeni_private.personal_document_authority_capability_active(text)
|
|
1250
|
+
TO opengeni_app;
|
|
1251
|
+
GRANT EXECUTE ON FUNCTION create_personal_document_authority(uuid, uuid, uuid)
|
|
1252
|
+
TO opengeni_app;
|
|
1253
|
+
GRANT EXECUTE ON FUNCTION
|
|
1254
|
+
resolve_session_attempt_personal_document_reads(uuid, uuid, uuid, uuid)
|
|
1255
|
+
TO opengeni_app;
|
|
1256
|
+
GRANT EXECUTE ON FUNCTION
|
|
1257
|
+
resolve_document_original_file(uuid, uuid, text, uuid)
|
|
1258
|
+
TO opengeni_app;
|
|
1259
|
+
REVOKE ALL ON TABLE session_attempt_personal_document_admissions FROM opengeni_app;
|
|
1260
|
+
REVOKE ALL ON TABLE session_attempt_personal_document_snapshots FROM opengeni_app;
|
|
1261
|
+
REVOKE ALL ON TABLE personal_document_once_consumption_receipts FROM opengeni_app;
|
|
1262
|
+
REVOKE ALL ON TABLE organization_user_resource_authorities FROM opengeni_app;
|
|
1263
|
+
REVOKE ALL ON TABLE organization_user_resource_grants FROM opengeni_app;
|
|
1264
|
+
END IF;
|
|
1265
|
+
END
|
|
1266
|
+
$personal_document_runtime_grants$;
|
|
1267
|
+
|
|
1268
|
+
COMMENT ON COLUMN "documents"."origin_workspace_id" IS
|
|
1269
|
+
'Upload provenance only. It never narrows activated organization-user document authority.';
|
|
1270
|
+
COMMENT ON COLUMN "documents"."authority_id" IS
|
|
1271
|
+
'Common organization-user resource authority for activated personal Documents; null on legacy anchored personal rows.';
|
|
1272
|
+
COMMENT ON TABLE "session_attempt_personal_document_snapshots" IS
|
|
1273
|
+
'Immutable exact-attempt personal Document grants; shared-session snapshots require the grant lifecycle acknowledgement.';
|