@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,820 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Migration 0260 follows the released 0258 three-scope Document authority.
|
|
3
|
+
-- Task notes may be promoted only into workspace-local proposed Knowledge.
|
|
4
|
+
-- The evidence row retains a value-free immutable source receipt after the
|
|
5
|
+
-- short-lived task tree is cleaned up; the source bytes remain in the ordinary
|
|
6
|
+
-- Task-note lifecycle and are never copied into evidence metadata.
|
|
7
|
+
-- Every new path and the complete invoked 0239/0225 Task-note authority
|
|
8
|
+
-- closure explicitly put pg_temp last so caller-created temporary relations
|
|
9
|
+
-- cannot shadow target-schema authority relations.
|
|
10
|
+
|
|
11
|
+
SET LOCAL lock_timeout = '5s';
|
|
12
|
+
SET LOCAL statement_timeout = '10min';
|
|
13
|
+
|
|
14
|
+
ALTER TABLE "knowledge_claim_evidence"
|
|
15
|
+
ALTER COLUMN "document_version_id" DROP NOT NULL,
|
|
16
|
+
ADD COLUMN "task_note_id" uuid,
|
|
17
|
+
ADD COLUMN "task_note_root_session_id" uuid,
|
|
18
|
+
ADD COLUMN "task_note_version" integer,
|
|
19
|
+
ADD CONSTRAINT "knowledge_claim_evidence_source_shape_chk" CHECK (
|
|
20
|
+
(
|
|
21
|
+
"document_version_id" IS NOT NULL
|
|
22
|
+
AND "task_note_id" IS NULL
|
|
23
|
+
AND "task_note_root_session_id" IS NULL
|
|
24
|
+
AND "task_note_version" IS NULL
|
|
25
|
+
) OR (
|
|
26
|
+
"document_version_id" IS NULL
|
|
27
|
+
AND "task_note_id" IS NOT NULL
|
|
28
|
+
AND "task_note_root_session_id" IS NOT NULL
|
|
29
|
+
AND "task_note_version" = 1
|
|
30
|
+
AND "scope_kind" = 'workspace'
|
|
31
|
+
AND "scope_workspace_id" IS NOT NULL
|
|
32
|
+
AND "scope_subject_id" IS NULL
|
|
33
|
+
AND "document_chunk_id" IS NULL
|
|
34
|
+
AND "chunk_index" IS NULL
|
|
35
|
+
AND "locator" IS NULL
|
|
36
|
+
AND "quote_hash" IS NULL
|
|
37
|
+
)
|
|
38
|
+
) NOT VALID;
|
|
39
|
+
|
|
40
|
+
ALTER TABLE "knowledge_claim_evidence"
|
|
41
|
+
VALIDATE CONSTRAINT "knowledge_claim_evidence_source_shape_chk";
|
|
42
|
+
|
|
43
|
+
DROP INDEX "knowledge_claim_evidence_natural_identity_uq";
|
|
44
|
+
CREATE UNIQUE INDEX "knowledge_claim_evidence_document_natural_identity_uq"
|
|
45
|
+
ON "knowledge_claim_evidence" (
|
|
46
|
+
"claim_id", "document_version_id", "polarity",
|
|
47
|
+
coalesce("document_chunk_id"::text, ''), coalesce("locator", '')
|
|
48
|
+
) WHERE "document_version_id" IS NOT NULL;
|
|
49
|
+
CREATE UNIQUE INDEX "knowledge_claim_evidence_task_note_natural_identity_uq"
|
|
50
|
+
ON "knowledge_claim_evidence" ("claim_id", "task_note_id", "polarity")
|
|
51
|
+
WHERE "task_note_id" IS NOT NULL;
|
|
52
|
+
|
|
53
|
+
CREATE TABLE "task_note_knowledge_promotion_capabilities" (
|
|
54
|
+
"backend_pid" integer NOT NULL,
|
|
55
|
+
"transaction_id" xid8 NOT NULL,
|
|
56
|
+
"capability_id" uuid NOT NULL,
|
|
57
|
+
"account_id" uuid NOT NULL,
|
|
58
|
+
"workspace_id" uuid NOT NULL,
|
|
59
|
+
"note_id" uuid NOT NULL,
|
|
60
|
+
"root_session_id" uuid NOT NULL,
|
|
61
|
+
"note_version" integer NOT NULL CHECK ("note_version" = 1),
|
|
62
|
+
"note_text_hash" text NOT NULL,
|
|
63
|
+
"evidence_operation_id" text NOT NULL,
|
|
64
|
+
"claim_operation_id" text NOT NULL,
|
|
65
|
+
"actor_subject_id" text NOT NULL,
|
|
66
|
+
"initiating_human_subject_id" text NOT NULL,
|
|
67
|
+
"learning_policy_snapshot_id" uuid NOT NULL,
|
|
68
|
+
PRIMARY KEY ("backend_pid", "transaction_id", "capability_id")
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
-- A replacement is one atomic, append-only correction receipt. The old note
|
|
72
|
+
-- remains immutable and archived; the replacement is a fresh version-one note.
|
|
73
|
+
-- The receipt deliberately stores no note text.
|
|
74
|
+
CREATE TABLE "task_note_replacement_receipts" (
|
|
75
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
76
|
+
"account_id" uuid NOT NULL,
|
|
77
|
+
"workspace_id" uuid NOT NULL,
|
|
78
|
+
"root_session_id" uuid NOT NULL,
|
|
79
|
+
"operation_id" uuid NOT NULL,
|
|
80
|
+
"input_hash" text NOT NULL,
|
|
81
|
+
"replaced_note_id" uuid NOT NULL,
|
|
82
|
+
"replaced_note_version" integer NOT NULL CHECK ("replaced_note_version" = 2),
|
|
83
|
+
"replacement_note_id" uuid NOT NULL,
|
|
84
|
+
"replacement_note_version" integer NOT NULL CHECK ("replacement_note_version" = 1),
|
|
85
|
+
"archive_operation_id" uuid NOT NULL,
|
|
86
|
+
"create_operation_id" uuid NOT NULL,
|
|
87
|
+
"actor_kind" text NOT NULL,
|
|
88
|
+
"actor_subject_id" text NOT NULL,
|
|
89
|
+
"initiating_human_subject_id" text,
|
|
90
|
+
"actor_session_id" uuid NOT NULL,
|
|
91
|
+
"actor_turn_id" uuid NOT NULL,
|
|
92
|
+
"actor_attempt_id" uuid NOT NULL,
|
|
93
|
+
"actor_execution_generation" integer NOT NULL,
|
|
94
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
95
|
+
CONSTRAINT "task_note_replacement_receipts_workspace_account_fk"
|
|
96
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
97
|
+
REFERENCES "workspaces" ("id", "account_id") ON DELETE CASCADE,
|
|
98
|
+
CONSTRAINT "task_note_replacement_receipts_root_session_fk"
|
|
99
|
+
FOREIGN KEY ("workspace_id", "root_session_id")
|
|
100
|
+
REFERENCES "sessions" ("workspace_id", "id") ON DELETE CASCADE,
|
|
101
|
+
CONSTRAINT "task_note_replacement_receipts_replaced_note_fk"
|
|
102
|
+
FOREIGN KEY ("workspace_id", "replaced_note_id")
|
|
103
|
+
REFERENCES "task_notes" ("workspace_id", "id") ON DELETE CASCADE,
|
|
104
|
+
CONSTRAINT "task_note_replacement_receipts_replacement_note_fk"
|
|
105
|
+
FOREIGN KEY ("workspace_id", "replacement_note_id")
|
|
106
|
+
REFERENCES "task_notes" ("workspace_id", "id") ON DELETE CASCADE,
|
|
107
|
+
CONSTRAINT "task_note_replacement_receipts_actor_session_fk"
|
|
108
|
+
FOREIGN KEY ("workspace_id", "actor_session_id")
|
|
109
|
+
REFERENCES "sessions" ("workspace_id", "id") ON DELETE RESTRICT,
|
|
110
|
+
CONSTRAINT "task_note_replacement_receipts_actor_turn_fk"
|
|
111
|
+
FOREIGN KEY ("workspace_id", "actor_turn_id")
|
|
112
|
+
REFERENCES "session_turns" ("workspace_id", "id") ON DELETE RESTRICT,
|
|
113
|
+
CONSTRAINT "task_note_replacement_receipts_actor_attempt_fk"
|
|
114
|
+
FOREIGN KEY ("workspace_id", "actor_attempt_id")
|
|
115
|
+
REFERENCES "session_turn_attempts" ("workspace_id", "id") ON DELETE RESTRICT,
|
|
116
|
+
CONSTRAINT "task_note_replacement_receipts_shape_chk" CHECK (
|
|
117
|
+
"replaced_note_id" <> "replacement_note_id"
|
|
118
|
+
AND "archive_operation_id" <> "create_operation_id"
|
|
119
|
+
AND "operation_id" <> "archive_operation_id"
|
|
120
|
+
AND "operation_id" <> "create_operation_id"
|
|
121
|
+
AND "input_hash" ~ '^[0-9a-f]{64}$'
|
|
122
|
+
AND "actor_kind" IN ('human', 'service')
|
|
123
|
+
AND length("actor_subject_id") BETWEEN 1 AND 1024
|
|
124
|
+
AND octet_length("actor_subject_id") <= 4096
|
|
125
|
+
AND ("initiating_human_subject_id" IS NULL OR (
|
|
126
|
+
length("initiating_human_subject_id") BETWEEN 1 AND 1024
|
|
127
|
+
AND octet_length("initiating_human_subject_id") <= 4096
|
|
128
|
+
))
|
|
129
|
+
AND "actor_execution_generation" > 0
|
|
130
|
+
),
|
|
131
|
+
CONSTRAINT "task_note_replacement_receipts_workspace_operation_uq"
|
|
132
|
+
UNIQUE ("workspace_id", "operation_id"),
|
|
133
|
+
CONSTRAINT "task_note_replacement_receipts_workspace_replacement_uq"
|
|
134
|
+
UNIQUE ("workspace_id", "replacement_note_id")
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
CREATE INDEX "task_note_replacement_receipts_root_timeline_idx"
|
|
138
|
+
ON "task_note_replacement_receipts" (
|
|
139
|
+
"workspace_id", "root_session_id", "created_at" DESC, "id" DESC
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
ALTER TABLE "task_note_knowledge_promotion_capabilities" ENABLE ROW LEVEL SECURITY;
|
|
143
|
+
ALTER TABLE "task_note_knowledge_promotion_capabilities" FORCE ROW LEVEL SECURITY;
|
|
144
|
+
ALTER TABLE "task_note_replacement_receipts" ENABLE ROW LEVEL SECURITY;
|
|
145
|
+
ALTER TABLE "task_note_replacement_receipts" FORCE ROW LEVEL SECURITY;
|
|
146
|
+
CREATE POLICY session_visibility_isolation ON "task_note_replacement_receipts"
|
|
147
|
+
AS RESTRICTIVE
|
|
148
|
+
FOR ALL
|
|
149
|
+
USING (session_reference_visible(
|
|
150
|
+
"account_id", "workspace_id", "actor_session_id"
|
|
151
|
+
))
|
|
152
|
+
WITH CHECK (session_reference_visible(
|
|
153
|
+
"account_id", "workspace_id", "actor_session_id"
|
|
154
|
+
));
|
|
155
|
+
|
|
156
|
+
DO $promotion_capability_policy$
|
|
157
|
+
DECLARE
|
|
158
|
+
data_schema text := current_schema();
|
|
159
|
+
migration_owner text := current_user;
|
|
160
|
+
BEGIN
|
|
161
|
+
EXECUTE format(
|
|
162
|
+
'CREATE POLICY task_note_knowledge_promotion_capability_owner '
|
|
163
|
+
|| 'ON %I.task_note_knowledge_promotion_capabilities '
|
|
164
|
+
|| 'FOR ALL USING (current_user = %L) WITH CHECK (current_user = %L)',
|
|
165
|
+
data_schema, migration_owner, migration_owner
|
|
166
|
+
);
|
|
167
|
+
EXECUTE format(
|
|
168
|
+
'REVOKE ALL ON %I.task_note_knowledge_promotion_capabilities FROM PUBLIC',
|
|
169
|
+
data_schema
|
|
170
|
+
);
|
|
171
|
+
EXECUTE format(
|
|
172
|
+
'CREATE POLICY task_note_replacement_receipts_owner '
|
|
173
|
+
|| 'ON %I.task_note_replacement_receipts '
|
|
174
|
+
|| 'FOR ALL USING (current_user = %L) WITH CHECK (current_user = %L)',
|
|
175
|
+
data_schema, migration_owner, migration_owner
|
|
176
|
+
);
|
|
177
|
+
EXECUTE format(
|
|
178
|
+
'REVOKE ALL ON %I.task_note_replacement_receipts FROM PUBLIC',
|
|
179
|
+
data_schema
|
|
180
|
+
);
|
|
181
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
182
|
+
EXECUTE format(
|
|
183
|
+
'REVOKE ALL ON %I.task_note_knowledge_promotion_capabilities FROM opengeni_app',
|
|
184
|
+
data_schema
|
|
185
|
+
);
|
|
186
|
+
EXECUTE format(
|
|
187
|
+
'REVOKE ALL ON %I.task_note_replacement_receipts FROM opengeni_app',
|
|
188
|
+
data_schema
|
|
189
|
+
);
|
|
190
|
+
END IF;
|
|
191
|
+
END
|
|
192
|
+
$promotion_capability_policy$;
|
|
193
|
+
|
|
194
|
+
CREATE OR REPLACE FUNCTION reject_task_note_replacement_receipt_mutation()
|
|
195
|
+
RETURNS trigger
|
|
196
|
+
LANGUAGE plpgsql
|
|
197
|
+
SECURITY DEFINER
|
|
198
|
+
SET search_path FROM CURRENT
|
|
199
|
+
AS $$
|
|
200
|
+
BEGIN
|
|
201
|
+
IF TG_OP = 'DELETE'
|
|
202
|
+
AND pg_trigger_depth() > 1
|
|
203
|
+
AND (
|
|
204
|
+
NOT EXISTS (SELECT 1 FROM workspaces WHERE id = OLD.workspace_id)
|
|
205
|
+
OR NOT EXISTS (SELECT 1 FROM sessions WHERE id = OLD.root_session_id)
|
|
206
|
+
OR NOT EXISTS (
|
|
207
|
+
SELECT 1 FROM task_notes
|
|
208
|
+
WHERE workspace_id = OLD.workspace_id AND id = OLD.replaced_note_id
|
|
209
|
+
)
|
|
210
|
+
OR NOT EXISTS (
|
|
211
|
+
SELECT 1 FROM task_notes
|
|
212
|
+
WHERE workspace_id = OLD.workspace_id AND id = OLD.replacement_note_id
|
|
213
|
+
)
|
|
214
|
+
)
|
|
215
|
+
THEN
|
|
216
|
+
RETURN OLD;
|
|
217
|
+
END IF;
|
|
218
|
+
RAISE EXCEPTION 'Task-note replacement receipts are immutable' USING ERRCODE = '55000';
|
|
219
|
+
END;
|
|
220
|
+
$$;
|
|
221
|
+
|
|
222
|
+
CREATE TRIGGER task_note_replacement_receipts_immutable
|
|
223
|
+
BEFORE UPDATE OR DELETE ON "task_note_replacement_receipts"
|
|
224
|
+
FOR EACH ROW EXECUTE FUNCTION reject_task_note_replacement_receipt_mutation();
|
|
225
|
+
|
|
226
|
+
CREATE OR REPLACE FUNCTION validate_task_note_knowledge_evidence()
|
|
227
|
+
RETURNS trigger
|
|
228
|
+
LANGUAGE plpgsql
|
|
229
|
+
SECURITY DEFINER
|
|
230
|
+
SET search_path FROM CURRENT
|
|
231
|
+
AS $$
|
|
232
|
+
DECLARE
|
|
233
|
+
note_row task_notes%ROWTYPE;
|
|
234
|
+
capability_row task_note_knowledge_promotion_capabilities%ROWTYPE;
|
|
235
|
+
BEGIN
|
|
236
|
+
IF NEW.task_note_id IS NULL THEN
|
|
237
|
+
RETURN NEW;
|
|
238
|
+
END IF;
|
|
239
|
+
|
|
240
|
+
SELECT capability.* INTO capability_row
|
|
241
|
+
FROM task_note_knowledge_promotion_capabilities capability
|
|
242
|
+
WHERE capability.backend_pid = pg_catalog.pg_backend_pid()
|
|
243
|
+
AND capability.transaction_id = pg_catalog.pg_current_xact_id()
|
|
244
|
+
AND capability.capability_id = nullif(
|
|
245
|
+
pg_catalog.current_setting('opengeni.task_note_knowledge_promotion_capability', true), ''
|
|
246
|
+
)::uuid
|
|
247
|
+
AND capability.account_id = NEW.account_id
|
|
248
|
+
AND capability.workspace_id = NEW.scope_workspace_id
|
|
249
|
+
AND capability.note_id = NEW.task_note_id
|
|
250
|
+
AND capability.root_session_id = NEW.task_note_root_session_id
|
|
251
|
+
AND capability.note_version = NEW.task_note_version
|
|
252
|
+
AND capability.note_text_hash = NEW.content_hash
|
|
253
|
+
AND capability.evidence_operation_id = NEW.operation_id
|
|
254
|
+
AND capability.actor_subject_id = NEW.actor_subject_id
|
|
255
|
+
AND capability.initiating_human_subject_id = NEW.initiating_human_subject_id;
|
|
256
|
+
IF NOT FOUND THEN
|
|
257
|
+
RAISE EXCEPTION 'Task-note Knowledge evidence requires exact promotion capability'
|
|
258
|
+
USING ERRCODE = '42501';
|
|
259
|
+
END IF;
|
|
260
|
+
|
|
261
|
+
SELECT note.* INTO note_row
|
|
262
|
+
FROM task_notes note
|
|
263
|
+
WHERE note.id = NEW.task_note_id
|
|
264
|
+
AND note.account_id = NEW.account_id
|
|
265
|
+
AND note.workspace_id = NEW.scope_workspace_id;
|
|
266
|
+
IF NOT FOUND
|
|
267
|
+
OR NEW.task_note_root_session_id IS DISTINCT FROM note_row.root_session_id
|
|
268
|
+
OR NEW.task_note_version IS DISTINCT FROM note_row.version
|
|
269
|
+
OR NEW.content_hash IS DISTINCT FROM note_row.text_hash
|
|
270
|
+
THEN
|
|
271
|
+
RAISE EXCEPTION 'Knowledge evidence does not match the exact Task-note source receipt'
|
|
272
|
+
USING ERRCODE = '23514';
|
|
273
|
+
END IF;
|
|
274
|
+
IF NOT EXISTS (
|
|
275
|
+
SELECT 1
|
|
276
|
+
FROM knowledge_claims claim
|
|
277
|
+
JOIN knowledge_facts fact
|
|
278
|
+
ON fact.account_id = claim.account_id
|
|
279
|
+
AND fact.id = claim.fact_id
|
|
280
|
+
AND fact.scope_key = claim.scope_key
|
|
281
|
+
WHERE claim.id = NEW.claim_id
|
|
282
|
+
AND claim.account_id = NEW.account_id
|
|
283
|
+
AND claim.scope_kind = 'workspace'
|
|
284
|
+
AND claim.scope_workspace_id = NEW.scope_workspace_id
|
|
285
|
+
AND claim.scope_subject_id IS NULL
|
|
286
|
+
AND claim.operation_id = capability_row.claim_operation_id
|
|
287
|
+
AND claim.actor_kind = NEW.actor_kind
|
|
288
|
+
AND claim.actor_subject_id = capability_row.actor_subject_id
|
|
289
|
+
AND claim.initiating_human_subject_id = capability_row.initiating_human_subject_id
|
|
290
|
+
AND claim.extraction_method = 'task-note-promotion-v1'
|
|
291
|
+
AND claim.extraction_metadata = pg_catalog.jsonb_build_object(
|
|
292
|
+
'taskNoteId', note_row.id,
|
|
293
|
+
'taskNoteRootSessionId', note_row.root_session_id,
|
|
294
|
+
'taskNoteVersion', note_row.version,
|
|
295
|
+
'taskNoteTextHash', note_row.text_hash
|
|
296
|
+
)
|
|
297
|
+
AND fact.scope_kind = 'workspace'
|
|
298
|
+
AND fact.scope_workspace_id = NEW.scope_workspace_id
|
|
299
|
+
AND fact.scope_subject_id IS NULL
|
|
300
|
+
AND fact.object_kind = 'text'
|
|
301
|
+
AND fact.object_entity_id IS NULL
|
|
302
|
+
AND fact.object_value = pg_catalog.to_jsonb(note_row.text)
|
|
303
|
+
AND fact.actor_kind = NEW.actor_kind
|
|
304
|
+
AND fact.actor_subject_id = capability_row.actor_subject_id
|
|
305
|
+
AND fact.initiating_human_subject_id = capability_row.initiating_human_subject_id
|
|
306
|
+
) THEN
|
|
307
|
+
RAISE EXCEPTION 'Task-note Knowledge evidence claim/fact is outside the admitted promotion lineage'
|
|
308
|
+
USING ERRCODE = '42501';
|
|
309
|
+
END IF;
|
|
310
|
+
DELETE FROM task_note_knowledge_promotion_capabilities capability
|
|
311
|
+
WHERE capability.backend_pid = capability_row.backend_pid
|
|
312
|
+
AND capability.transaction_id = capability_row.transaction_id
|
|
313
|
+
AND capability.capability_id = capability_row.capability_id;
|
|
314
|
+
PERFORM pg_catalog.set_config('opengeni.task_note_knowledge_promotion_capability', '', true);
|
|
315
|
+
RETURN NEW;
|
|
316
|
+
END;
|
|
317
|
+
$$;
|
|
318
|
+
|
|
319
|
+
CREATE TRIGGER knowledge_claim_evidence_15_validate_task_note
|
|
320
|
+
BEFORE INSERT ON "knowledge_claim_evidence"
|
|
321
|
+
FOR EACH ROW EXECUTE FUNCTION validate_task_note_knowledge_evidence();
|
|
322
|
+
|
|
323
|
+
CREATE OR REPLACE FUNCTION resolve_task_note_knowledge_promotion_source(
|
|
324
|
+
p_account_id uuid,
|
|
325
|
+
p_workspace_id uuid,
|
|
326
|
+
p_session_id uuid,
|
|
327
|
+
p_turn_id uuid,
|
|
328
|
+
p_attempt_id uuid,
|
|
329
|
+
p_execution_generation integer,
|
|
330
|
+
p_note_id uuid,
|
|
331
|
+
p_expected_note_version integer,
|
|
332
|
+
p_evidence_operation_id text,
|
|
333
|
+
p_claim_operation_id text,
|
|
334
|
+
p_actor_subject_id text
|
|
335
|
+
) RETURNS TABLE (
|
|
336
|
+
note_id uuid,
|
|
337
|
+
root_session_id uuid,
|
|
338
|
+
note_version integer,
|
|
339
|
+
note_text text,
|
|
340
|
+
note_text_hash text,
|
|
341
|
+
note_created_at timestamptz,
|
|
342
|
+
initiating_human_subject_id text
|
|
343
|
+
)
|
|
344
|
+
LANGUAGE plpgsql
|
|
345
|
+
SECURITY DEFINER
|
|
346
|
+
SET search_path FROM CURRENT
|
|
347
|
+
AS $$
|
|
348
|
+
DECLARE
|
|
349
|
+
authority record;
|
|
350
|
+
note_row task_notes%ROWTYPE;
|
|
351
|
+
learning_policy_snapshot_id uuid;
|
|
352
|
+
effective_learning_mode text;
|
|
353
|
+
previous_subject_id text := pg_catalog.current_setting('opengeni.subject_id', true);
|
|
354
|
+
previous_initiating_human_subject_id text := pg_catalog.current_setting(
|
|
355
|
+
'opengeni.initiating_human_subject_id', true
|
|
356
|
+
);
|
|
357
|
+
write_capability_id uuid := pg_catalog.gen_random_uuid();
|
|
358
|
+
previous_write_capability text := pg_catalog.current_setting(
|
|
359
|
+
'opengeni.task_note_knowledge_promotion_capability', true
|
|
360
|
+
);
|
|
361
|
+
BEGIN
|
|
362
|
+
IF p_note_id IS NULL
|
|
363
|
+
OR p_expected_note_version IS DISTINCT FROM 1
|
|
364
|
+
OR p_evidence_operation_id IS NULL
|
|
365
|
+
OR p_claim_operation_id IS NULL
|
|
366
|
+
OR length(btrim(coalesce(p_actor_subject_id, ''))) NOT BETWEEN 1 AND 1024
|
|
367
|
+
THEN
|
|
368
|
+
RAISE EXCEPTION 'Task-note promotion requires exact active version one'
|
|
369
|
+
USING ERRCODE = '23514';
|
|
370
|
+
END IF;
|
|
371
|
+
|
|
372
|
+
SELECT * INTO authority
|
|
373
|
+
FROM resolve_task_note_attempt_authority(
|
|
374
|
+
p_account_id, p_workspace_id, p_session_id, p_turn_id,
|
|
375
|
+
p_attempt_id, p_execution_generation
|
|
376
|
+
);
|
|
377
|
+
IF authority.initiating_human_subject_id IS NULL THEN
|
|
378
|
+
RAISE EXCEPTION 'Task-note promotion requires an immutable initiating human'
|
|
379
|
+
USING ERRCODE = '42501';
|
|
380
|
+
END IF;
|
|
381
|
+
|
|
382
|
+
SELECT snapshot.id,
|
|
383
|
+
coalesce(
|
|
384
|
+
(
|
|
385
|
+
SELECT override.value->>'mode'
|
|
386
|
+
FROM pg_catalog.jsonb_array_elements(snapshot.source_overrides) override(value)
|
|
387
|
+
WHERE override.value->>'kind' = 'task-note'
|
|
388
|
+
AND override.value->>'id' = p_note_id::text
|
|
389
|
+
LIMIT 1
|
|
390
|
+
),
|
|
391
|
+
snapshot.workspace_mode
|
|
392
|
+
)
|
|
393
|
+
INTO learning_policy_snapshot_id, effective_learning_mode
|
|
394
|
+
FROM workspace_learning_policy_snapshots snapshot
|
|
395
|
+
WHERE snapshot.account_id = p_account_id
|
|
396
|
+
AND snapshot.workspace_id = p_workspace_id
|
|
397
|
+
AND snapshot.session_id = p_session_id
|
|
398
|
+
AND snapshot.turn_id = p_turn_id
|
|
399
|
+
AND snapshot.attempt_id = p_attempt_id
|
|
400
|
+
AND snapshot.execution_generation = p_execution_generation;
|
|
401
|
+
IF learning_policy_snapshot_id IS NULL
|
|
402
|
+
OR effective_learning_mode NOT IN ('suggest', 'automatic')
|
|
403
|
+
THEN
|
|
404
|
+
RAISE EXCEPTION 'Task-note promotion is disabled by the exact learning-policy snapshot'
|
|
405
|
+
USING ERRCODE = '42501';
|
|
406
|
+
END IF;
|
|
407
|
+
|
|
408
|
+
PERFORM pg_catalog.set_config(
|
|
409
|
+
'opengeni.subject_id', authority.initiating_human_subject_id, true
|
|
410
|
+
);
|
|
411
|
+
PERFORM pg_catalog.set_config(
|
|
412
|
+
'opengeni.initiating_human_subject_id', authority.initiating_human_subject_id, true
|
|
413
|
+
);
|
|
414
|
+
SELECT note.* INTO note_row
|
|
415
|
+
FROM task_notes note
|
|
416
|
+
WHERE note.account_id = p_account_id
|
|
417
|
+
AND note.workspace_id = p_workspace_id
|
|
418
|
+
AND note.root_session_id = authority.root_session_id
|
|
419
|
+
AND note.id = p_note_id
|
|
420
|
+
AND note.status = 'active'
|
|
421
|
+
AND note.version = p_expected_note_version
|
|
422
|
+
AND note.expires_at > statement_timestamp()
|
|
423
|
+
FOR SHARE;
|
|
424
|
+
|
|
425
|
+
PERFORM pg_catalog.set_config(
|
|
426
|
+
'opengeni.subject_id', coalesce(previous_subject_id, ''), true
|
|
427
|
+
);
|
|
428
|
+
PERFORM pg_catalog.set_config(
|
|
429
|
+
'opengeni.initiating_human_subject_id',
|
|
430
|
+
coalesce(previous_initiating_human_subject_id, ''), true
|
|
431
|
+
);
|
|
432
|
+
IF note_row.id IS NULL THEN
|
|
433
|
+
RAISE EXCEPTION 'Task note is unavailable, archived, expired, or outside this root tree'
|
|
434
|
+
USING ERRCODE = '42501';
|
|
435
|
+
END IF;
|
|
436
|
+
|
|
437
|
+
INSERT INTO task_note_knowledge_promotion_capabilities (
|
|
438
|
+
backend_pid, transaction_id, capability_id,
|
|
439
|
+
account_id, workspace_id, note_id, root_session_id, note_version,
|
|
440
|
+
note_text_hash, evidence_operation_id, claim_operation_id,
|
|
441
|
+
actor_subject_id, initiating_human_subject_id, learning_policy_snapshot_id
|
|
442
|
+
) VALUES (
|
|
443
|
+
pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), write_capability_id,
|
|
444
|
+
p_account_id, p_workspace_id, note_row.id, note_row.root_session_id, note_row.version,
|
|
445
|
+
note_row.text_hash, p_evidence_operation_id, p_claim_operation_id,
|
|
446
|
+
p_actor_subject_id, authority.initiating_human_subject_id, learning_policy_snapshot_id
|
|
447
|
+
);
|
|
448
|
+
PERFORM pg_catalog.set_config(
|
|
449
|
+
'opengeni.task_note_knowledge_promotion_capability', write_capability_id::text, true
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
RETURN QUERY SELECT
|
|
453
|
+
note_row.id,
|
|
454
|
+
note_row.root_session_id,
|
|
455
|
+
note_row.version,
|
|
456
|
+
note_row.text,
|
|
457
|
+
note_row.text_hash,
|
|
458
|
+
note_row.created_at,
|
|
459
|
+
authority.initiating_human_subject_id;
|
|
460
|
+
EXCEPTION WHEN OTHERS THEN
|
|
461
|
+
DELETE FROM task_note_knowledge_promotion_capabilities capability
|
|
462
|
+
WHERE capability.backend_pid = pg_catalog.pg_backend_pid()
|
|
463
|
+
AND capability.transaction_id = pg_catalog.pg_current_xact_id()
|
|
464
|
+
AND capability.capability_id = write_capability_id;
|
|
465
|
+
PERFORM pg_catalog.set_config(
|
|
466
|
+
'opengeni.task_note_knowledge_promotion_capability',
|
|
467
|
+
coalesce(previous_write_capability, ''), true
|
|
468
|
+
);
|
|
469
|
+
PERFORM pg_catalog.set_config(
|
|
470
|
+
'opengeni.subject_id', coalesce(previous_subject_id, ''), true
|
|
471
|
+
);
|
|
472
|
+
PERFORM pg_catalog.set_config(
|
|
473
|
+
'opengeni.initiating_human_subject_id',
|
|
474
|
+
coalesce(previous_initiating_human_subject_id, ''), true
|
|
475
|
+
);
|
|
476
|
+
RAISE;
|
|
477
|
+
END;
|
|
478
|
+
$$;
|
|
479
|
+
|
|
480
|
+
CREATE OR REPLACE FUNCTION replace_task_note_for_attempt(
|
|
481
|
+
p_account_id uuid,
|
|
482
|
+
p_workspace_id uuid,
|
|
483
|
+
p_session_id uuid,
|
|
484
|
+
p_turn_id uuid,
|
|
485
|
+
p_attempt_id uuid,
|
|
486
|
+
p_execution_generation integer,
|
|
487
|
+
p_operation_id uuid,
|
|
488
|
+
p_archive_operation_id uuid,
|
|
489
|
+
p_create_operation_id uuid,
|
|
490
|
+
p_replaced_note_id uuid,
|
|
491
|
+
p_expected_replaced_version integer,
|
|
492
|
+
p_replacement_kind text,
|
|
493
|
+
p_replacement_text text,
|
|
494
|
+
p_replacement_expires_in_days integer,
|
|
495
|
+
p_reason text
|
|
496
|
+
) RETURNS TABLE (
|
|
497
|
+
operation_id uuid,
|
|
498
|
+
input_hash text,
|
|
499
|
+
replaced_note_id uuid,
|
|
500
|
+
replaced_note_version integer,
|
|
501
|
+
replacement_note_id uuid,
|
|
502
|
+
root_session_id uuid,
|
|
503
|
+
replacement_kind text,
|
|
504
|
+
replacement_text text,
|
|
505
|
+
replacement_status text,
|
|
506
|
+
replacement_version integer,
|
|
507
|
+
replacement_expires_at timestamptz,
|
|
508
|
+
replacement_created_at timestamptz,
|
|
509
|
+
replacement_updated_at timestamptz,
|
|
510
|
+
replacement_archived_at timestamptz,
|
|
511
|
+
replacement_actor_kind text,
|
|
512
|
+
replacement_source_session_id uuid,
|
|
513
|
+
replacement_source_turn_id uuid,
|
|
514
|
+
replayed boolean
|
|
515
|
+
)
|
|
516
|
+
LANGUAGE plpgsql
|
|
517
|
+
SECURITY DEFINER
|
|
518
|
+
SET search_path FROM CURRENT
|
|
519
|
+
AS $$
|
|
520
|
+
DECLARE
|
|
521
|
+
authority record;
|
|
522
|
+
receipt_row task_note_replacement_receipts%ROWTYPE;
|
|
523
|
+
replaced_row task_notes%ROWTYPE;
|
|
524
|
+
replacement_row task_notes%ROWTYPE;
|
|
525
|
+
archived_result record;
|
|
526
|
+
created_result record;
|
|
527
|
+
calculated_replacement_text_hash text;
|
|
528
|
+
calculated_input_hash text;
|
|
529
|
+
BEGIN
|
|
530
|
+
SELECT * INTO STRICT authority FROM resolve_task_note_attempt_authority(
|
|
531
|
+
p_account_id, p_workspace_id, p_session_id, p_turn_id,
|
|
532
|
+
p_attempt_id, p_execution_generation
|
|
533
|
+
);
|
|
534
|
+
IF p_operation_id IS NULL
|
|
535
|
+
OR p_archive_operation_id IS NULL
|
|
536
|
+
OR p_create_operation_id IS NULL
|
|
537
|
+
OR p_operation_id = p_archive_operation_id
|
|
538
|
+
OR p_operation_id = p_create_operation_id
|
|
539
|
+
OR p_archive_operation_id = p_create_operation_id
|
|
540
|
+
OR p_replaced_note_id IS NULL
|
|
541
|
+
OR p_expected_replaced_version IS DISTINCT FROM 1
|
|
542
|
+
OR p_replacement_kind NOT IN ('finding','decision','blocker','ownership','artifact','handoff')
|
|
543
|
+
OR p_replacement_text IS NULL
|
|
544
|
+
OR octet_length(p_replacement_text) NOT BETWEEN 1 AND 4096
|
|
545
|
+
OR p_replacement_text <> btrim(p_replacement_text)
|
|
546
|
+
OR p_replacement_expires_in_days IS NULL
|
|
547
|
+
OR p_replacement_expires_in_days NOT BETWEEN 1 AND 30
|
|
548
|
+
OR p_reason IS NULL
|
|
549
|
+
OR octet_length(p_reason) NOT BETWEEN 1 AND 2048
|
|
550
|
+
OR p_reason <> btrim(p_reason)
|
|
551
|
+
THEN
|
|
552
|
+
RAISE EXCEPTION 'Task-note replacement input is invalid' USING ERRCODE = '22023';
|
|
553
|
+
END IF;
|
|
554
|
+
|
|
555
|
+
calculated_replacement_text_hash := encode(
|
|
556
|
+
sha256(convert_to(p_replacement_text, 'UTF8')), 'hex'
|
|
557
|
+
);
|
|
558
|
+
calculated_input_hash := encode(sha256(convert_to(jsonb_build_object(
|
|
559
|
+
'accountId', p_account_id,
|
|
560
|
+
'workspaceId', p_workspace_id,
|
|
561
|
+
'rootSessionId', authority.root_session_id,
|
|
562
|
+
'sessionId', p_session_id,
|
|
563
|
+
'turnId', p_turn_id,
|
|
564
|
+
'attemptId', p_attempt_id,
|
|
565
|
+
'executionGeneration', p_execution_generation,
|
|
566
|
+
'operationId', p_operation_id,
|
|
567
|
+
'archiveOperationId', p_archive_operation_id,
|
|
568
|
+
'createOperationId', p_create_operation_id,
|
|
569
|
+
'replacedNoteId', p_replaced_note_id,
|
|
570
|
+
'expectedReplacedVersion', p_expected_replaced_version,
|
|
571
|
+
'replacementKind', p_replacement_kind,
|
|
572
|
+
'replacementTextHash', calculated_replacement_text_hash,
|
|
573
|
+
'replacementExpiresInDays', p_replacement_expires_in_days,
|
|
574
|
+
'reason', p_reason
|
|
575
|
+
)::text, 'UTF8')), 'hex');
|
|
576
|
+
|
|
577
|
+
SELECT receipt.* INTO receipt_row
|
|
578
|
+
FROM task_note_replacement_receipts receipt
|
|
579
|
+
WHERE receipt.workspace_id = p_workspace_id
|
|
580
|
+
AND receipt.operation_id = p_operation_id
|
|
581
|
+
FOR SHARE;
|
|
582
|
+
IF FOUND THEN
|
|
583
|
+
IF receipt_row.account_id IS DISTINCT FROM p_account_id
|
|
584
|
+
OR receipt_row.root_session_id IS DISTINCT FROM authority.root_session_id
|
|
585
|
+
OR receipt_row.input_hash IS DISTINCT FROM calculated_input_hash
|
|
586
|
+
OR receipt_row.replaced_note_id IS DISTINCT FROM p_replaced_note_id
|
|
587
|
+
OR receipt_row.archive_operation_id IS DISTINCT FROM p_archive_operation_id
|
|
588
|
+
OR receipt_row.create_operation_id IS DISTINCT FROM p_create_operation_id
|
|
589
|
+
OR receipt_row.actor_session_id IS DISTINCT FROM p_session_id
|
|
590
|
+
OR receipt_row.actor_turn_id IS DISTINCT FROM p_turn_id
|
|
591
|
+
OR receipt_row.actor_attempt_id IS DISTINCT FROM p_attempt_id
|
|
592
|
+
OR receipt_row.actor_execution_generation IS DISTINCT FROM p_execution_generation
|
|
593
|
+
OR receipt_row.actor_kind IS DISTINCT FROM authority.actor_kind
|
|
594
|
+
OR receipt_row.actor_subject_id IS DISTINCT FROM authority.actor_subject_id
|
|
595
|
+
OR receipt_row.initiating_human_subject_id
|
|
596
|
+
IS DISTINCT FROM authority.initiating_human_subject_id
|
|
597
|
+
THEN
|
|
598
|
+
RAISE EXCEPTION 'Task-note replacement operation conflicts with another input or attempt'
|
|
599
|
+
USING ERRCODE = '23505';
|
|
600
|
+
END IF;
|
|
601
|
+
SELECT note.* INTO STRICT replacement_row
|
|
602
|
+
FROM task_notes note
|
|
603
|
+
WHERE note.workspace_id = p_workspace_id
|
|
604
|
+
AND note.root_session_id = authority.root_session_id
|
|
605
|
+
AND note.id = receipt_row.replacement_note_id;
|
|
606
|
+
replayed := true;
|
|
607
|
+
ELSE
|
|
608
|
+
SELECT note.* INTO replaced_row
|
|
609
|
+
FROM task_notes note
|
|
610
|
+
WHERE note.workspace_id = p_workspace_id
|
|
611
|
+
AND note.root_session_id = authority.root_session_id
|
|
612
|
+
AND note.id = p_replaced_note_id
|
|
613
|
+
FOR UPDATE;
|
|
614
|
+
IF NOT FOUND THEN
|
|
615
|
+
RAISE EXCEPTION 'Task note is unavailable for replacement' USING ERRCODE = 'P0002';
|
|
616
|
+
END IF;
|
|
617
|
+
IF replaced_row.status <> 'active'
|
|
618
|
+
OR replaced_row.version <> p_expected_replaced_version
|
|
619
|
+
OR replaced_row.expires_at <= transaction_timestamp()
|
|
620
|
+
THEN
|
|
621
|
+
RAISE EXCEPTION 'Task-note replacement version or lifecycle conflict'
|
|
622
|
+
USING ERRCODE = '40001';
|
|
623
|
+
END IF;
|
|
624
|
+
|
|
625
|
+
SELECT * INTO STRICT archived_result FROM archive_task_note_for_attempt(
|
|
626
|
+
p_account_id, p_workspace_id, p_session_id, p_turn_id,
|
|
627
|
+
p_attempt_id, p_execution_generation, p_archive_operation_id,
|
|
628
|
+
p_replaced_note_id, p_expected_replaced_version, p_reason
|
|
629
|
+
);
|
|
630
|
+
SELECT * INTO STRICT created_result FROM create_task_note_for_attempt(
|
|
631
|
+
p_account_id, p_workspace_id, p_session_id, p_turn_id,
|
|
632
|
+
p_attempt_id, p_execution_generation, p_create_operation_id,
|
|
633
|
+
p_replacement_kind, p_replacement_text, p_replacement_expires_in_days
|
|
634
|
+
);
|
|
635
|
+
IF archived_result.note_id IS DISTINCT FROM p_replaced_note_id
|
|
636
|
+
OR archived_result.status IS DISTINCT FROM 'archived'
|
|
637
|
+
OR archived_result.version IS DISTINCT FROM 2
|
|
638
|
+
OR created_result.status IS DISTINCT FROM 'active'
|
|
639
|
+
OR created_result.version IS DISTINCT FROM 1
|
|
640
|
+
OR created_result.root_session_id IS DISTINCT FROM authority.root_session_id
|
|
641
|
+
THEN
|
|
642
|
+
RAISE EXCEPTION 'Task-note replacement lifecycle returned an invalid projection'
|
|
643
|
+
USING ERRCODE = '23514';
|
|
644
|
+
END IF;
|
|
645
|
+
SELECT note.* INTO STRICT replacement_row
|
|
646
|
+
FROM task_notes note
|
|
647
|
+
WHERE note.workspace_id = p_workspace_id
|
|
648
|
+
AND note.root_session_id = authority.root_session_id
|
|
649
|
+
AND note.id = created_result.note_id;
|
|
650
|
+
|
|
651
|
+
INSERT INTO task_note_replacement_receipts (
|
|
652
|
+
account_id, workspace_id, root_session_id, operation_id, input_hash,
|
|
653
|
+
replaced_note_id, replaced_note_version, replacement_note_id,
|
|
654
|
+
replacement_note_version, archive_operation_id, create_operation_id,
|
|
655
|
+
actor_kind, actor_subject_id, initiating_human_subject_id,
|
|
656
|
+
actor_session_id, actor_turn_id, actor_attempt_id, actor_execution_generation
|
|
657
|
+
) VALUES (
|
|
658
|
+
p_account_id, p_workspace_id, authority.root_session_id,
|
|
659
|
+
p_operation_id, calculated_input_hash, p_replaced_note_id, 2,
|
|
660
|
+
replacement_row.id, 1, p_archive_operation_id, p_create_operation_id,
|
|
661
|
+
authority.actor_kind, authority.actor_subject_id,
|
|
662
|
+
authority.initiating_human_subject_id, p_session_id, p_turn_id,
|
|
663
|
+
p_attempt_id, p_execution_generation
|
|
664
|
+
) RETURNING * INTO STRICT receipt_row;
|
|
665
|
+
replayed := false;
|
|
666
|
+
END IF;
|
|
667
|
+
|
|
668
|
+
operation_id := receipt_row.operation_id;
|
|
669
|
+
input_hash := receipt_row.input_hash;
|
|
670
|
+
replaced_note_id := receipt_row.replaced_note_id;
|
|
671
|
+
replaced_note_version := receipt_row.replaced_note_version;
|
|
672
|
+
replacement_note_id := replacement_row.id;
|
|
673
|
+
root_session_id := replacement_row.root_session_id;
|
|
674
|
+
replacement_kind := replacement_row.kind;
|
|
675
|
+
replacement_text := replacement_row.text;
|
|
676
|
+
replacement_status := replacement_row.status;
|
|
677
|
+
replacement_version := replacement_row.version;
|
|
678
|
+
replacement_expires_at := replacement_row.expires_at;
|
|
679
|
+
replacement_created_at := replacement_row.created_at;
|
|
680
|
+
replacement_updated_at := replacement_row.updated_at;
|
|
681
|
+
replacement_archived_at := replacement_row.archived_at;
|
|
682
|
+
replacement_actor_kind := replacement_row.created_by_actor_kind;
|
|
683
|
+
replacement_source_session_id := replacement_row.created_by_session_id;
|
|
684
|
+
replacement_source_turn_id := replacement_row.created_by_turn_id;
|
|
685
|
+
RETURN NEXT;
|
|
686
|
+
END;
|
|
687
|
+
$$;
|
|
688
|
+
|
|
689
|
+
DO $function_access$
|
|
690
|
+
DECLARE
|
|
691
|
+
data_schema text := current_schema();
|
|
692
|
+
required_routine text;
|
|
693
|
+
BEGIN
|
|
694
|
+
-- Migration 0239 predates the explicit pg_temp-last posture. Its lifecycle
|
|
695
|
+
-- functions are invoked by both 0260 entry points, while their RLS path also
|
|
696
|
+
-- invokes the 0225 session-reference/private-actor helpers. A caller with
|
|
697
|
+
-- database TEMP privilege must not be able to shadow any authority relation
|
|
698
|
+
-- reached through that nested closure. Fail closed if the exact predecessor
|
|
699
|
+
-- signatures are absent, then repair only their persisted search paths.
|
|
700
|
+
FOREACH required_routine IN ARRAY ARRAY[
|
|
701
|
+
'guard_task_note_mutation()',
|
|
702
|
+
'guard_task_note_event_mutation()',
|
|
703
|
+
'resolve_task_note_attempt_authority(uuid,uuid,uuid,uuid,uuid,integer)',
|
|
704
|
+
'create_task_note_for_attempt(uuid,uuid,uuid,uuid,uuid,integer,uuid,text,text,integer)',
|
|
705
|
+
'archive_task_note_for_attempt(uuid,uuid,uuid,uuid,uuid,integer,uuid,uuid,integer,text)',
|
|
706
|
+
'list_task_notes_for_attempt(uuid,uuid,uuid,uuid,uuid,integer,boolean,integer)',
|
|
707
|
+
'session_private_actor_visible(uuid,uuid,uuid,text)',
|
|
708
|
+
'session_reference_visible(uuid,uuid,uuid)'
|
|
709
|
+
]
|
|
710
|
+
LOOP
|
|
711
|
+
IF pg_catalog.to_regprocedure(
|
|
712
|
+
pg_catalog.format('%I.%s', data_schema, required_routine)
|
|
713
|
+
) IS NULL THEN
|
|
714
|
+
RAISE EXCEPTION 'Task-note authority closure routine is missing: %.%',
|
|
715
|
+
data_schema, required_routine
|
|
716
|
+
USING ERRCODE = '42883';
|
|
717
|
+
END IF;
|
|
718
|
+
END LOOP;
|
|
719
|
+
|
|
720
|
+
EXECUTE format(
|
|
721
|
+
'ALTER FUNCTION %I.guard_task_note_mutation() '
|
|
722
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
723
|
+
data_schema, data_schema
|
|
724
|
+
);
|
|
725
|
+
EXECUTE format(
|
|
726
|
+
'ALTER FUNCTION %I.guard_task_note_event_mutation() '
|
|
727
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
728
|
+
data_schema, data_schema
|
|
729
|
+
);
|
|
730
|
+
EXECUTE format(
|
|
731
|
+
'ALTER FUNCTION %I.resolve_task_note_attempt_authority('
|
|
732
|
+
|| 'uuid,uuid,uuid,uuid,uuid,integer) '
|
|
733
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
734
|
+
data_schema, data_schema
|
|
735
|
+
);
|
|
736
|
+
EXECUTE format(
|
|
737
|
+
'ALTER FUNCTION %I.create_task_note_for_attempt('
|
|
738
|
+
|| 'uuid,uuid,uuid,uuid,uuid,integer,uuid,text,text,integer) '
|
|
739
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
740
|
+
data_schema, data_schema
|
|
741
|
+
);
|
|
742
|
+
EXECUTE format(
|
|
743
|
+
'ALTER FUNCTION %I.archive_task_note_for_attempt('
|
|
744
|
+
|| 'uuid,uuid,uuid,uuid,uuid,integer,uuid,uuid,integer,text) '
|
|
745
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
746
|
+
data_schema, data_schema
|
|
747
|
+
);
|
|
748
|
+
EXECUTE format(
|
|
749
|
+
'ALTER FUNCTION %I.list_task_notes_for_attempt('
|
|
750
|
+
|| 'uuid,uuid,uuid,uuid,uuid,integer,boolean,integer) '
|
|
751
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
752
|
+
data_schema, data_schema
|
|
753
|
+
);
|
|
754
|
+
EXECUTE format(
|
|
755
|
+
'ALTER FUNCTION %I.session_private_actor_visible(uuid,uuid,uuid,text) '
|
|
756
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
757
|
+
data_schema, data_schema
|
|
758
|
+
);
|
|
759
|
+
EXECUTE format(
|
|
760
|
+
'ALTER FUNCTION %I.session_reference_visible(uuid,uuid,uuid) '
|
|
761
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
762
|
+
data_schema, data_schema
|
|
763
|
+
);
|
|
764
|
+
|
|
765
|
+
EXECUTE format(
|
|
766
|
+
'REVOKE ALL ON FUNCTION %I.validate_task_note_knowledge_evidence() FROM PUBLIC',
|
|
767
|
+
data_schema
|
|
768
|
+
);
|
|
769
|
+
EXECUTE format(
|
|
770
|
+
'REVOKE ALL ON FUNCTION %I.reject_task_note_replacement_receipt_mutation() FROM PUBLIC',
|
|
771
|
+
data_schema
|
|
772
|
+
);
|
|
773
|
+
EXECUTE format(
|
|
774
|
+
'REVOKE ALL ON FUNCTION %I.replace_task_note_for_attempt('
|
|
775
|
+
|| 'uuid,uuid,uuid,uuid,uuid,integer,uuid,uuid,uuid,uuid,integer,text,text,integer,text) '
|
|
776
|
+
|| 'FROM PUBLIC',
|
|
777
|
+
data_schema
|
|
778
|
+
);
|
|
779
|
+
EXECUTE format(
|
|
780
|
+
'REVOKE ALL ON FUNCTION %I.resolve_task_note_knowledge_promotion_source('
|
|
781
|
+
|| 'uuid,uuid,uuid,uuid,uuid,integer,uuid,integer,text,text,text) FROM PUBLIC',
|
|
782
|
+
data_schema
|
|
783
|
+
);
|
|
784
|
+
EXECUTE format(
|
|
785
|
+
'ALTER FUNCTION %I.validate_task_note_knowledge_evidence() '
|
|
786
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
787
|
+
data_schema, data_schema
|
|
788
|
+
);
|
|
789
|
+
EXECUTE format(
|
|
790
|
+
'ALTER FUNCTION %I.reject_task_note_replacement_receipt_mutation() '
|
|
791
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
792
|
+
data_schema, data_schema
|
|
793
|
+
);
|
|
794
|
+
EXECUTE format(
|
|
795
|
+
'ALTER FUNCTION %I.replace_task_note_for_attempt('
|
|
796
|
+
|| 'uuid,uuid,uuid,uuid,uuid,integer,uuid,uuid,uuid,uuid,integer,text,text,integer,text) '
|
|
797
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
798
|
+
data_schema, data_schema
|
|
799
|
+
);
|
|
800
|
+
EXECUTE format(
|
|
801
|
+
'ALTER FUNCTION %I.resolve_task_note_knowledge_promotion_source('
|
|
802
|
+
|| 'uuid,uuid,uuid,uuid,uuid,integer,uuid,integer,text,text,text) '
|
|
803
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
804
|
+
data_schema, data_schema
|
|
805
|
+
);
|
|
806
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
807
|
+
EXECUTE format(
|
|
808
|
+
'GRANT EXECUTE ON FUNCTION %I.resolve_task_note_knowledge_promotion_source('
|
|
809
|
+
|| 'uuid,uuid,uuid,uuid,uuid,integer,uuid,integer,text,text,text) TO opengeni_app',
|
|
810
|
+
data_schema
|
|
811
|
+
);
|
|
812
|
+
EXECUTE format(
|
|
813
|
+
'GRANT EXECUTE ON FUNCTION %I.replace_task_note_for_attempt('
|
|
814
|
+
|| 'uuid,uuid,uuid,uuid,uuid,integer,uuid,uuid,uuid,uuid,integer,text,text,integer,text) '
|
|
815
|
+
|| 'TO opengeni_app',
|
|
816
|
+
data_schema
|
|
817
|
+
);
|
|
818
|
+
END IF;
|
|
819
|
+
END
|
|
820
|
+
$function_access$;
|