@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
|
@@ -13,8 +13,10 @@ import {
|
|
|
13
13
|
IntegrationFacetBindingOwnershipConflictError,
|
|
14
14
|
IntegrationFacetBindingVersionConflictError,
|
|
15
15
|
listIntegrationFacetBindingOwners,
|
|
16
|
+
listIntegrationFacetBindingOwnersForBindings,
|
|
16
17
|
removeIntegrationFacetBindingOwner,
|
|
17
18
|
upsertIntegrationFacetBinding,
|
|
19
|
+
type IntegrationFacetBindingOwner,
|
|
18
20
|
} from "./integration-bindings";
|
|
19
21
|
import * as schema from "./schema";
|
|
20
22
|
|
|
@@ -39,6 +41,8 @@ export type IntegrationFacetBindingSummary = {
|
|
|
39
41
|
lastErrorCode: string | null;
|
|
40
42
|
createdAt: string;
|
|
41
43
|
updatedAt: string;
|
|
44
|
+
directlyOwned: boolean;
|
|
45
|
+
owners: IntegrationFacetBindingOwner[];
|
|
42
46
|
};
|
|
43
47
|
|
|
44
48
|
export type IntegrationFacetDefinitionSummary = {
|
|
@@ -96,6 +100,72 @@ export class IntegrationFacetOperationIdempotencyError extends Error {
|
|
|
96
100
|
readonly name = "IntegrationFacetOperationIdempotencyError";
|
|
97
101
|
}
|
|
98
102
|
|
|
103
|
+
type IntegrationFacetOperationKind = "configure" | "update" | "disconnect";
|
|
104
|
+
|
|
105
|
+
type IntegrationFacetOperationIdentity = {
|
|
106
|
+
accountId: string;
|
|
107
|
+
workspaceId: string;
|
|
108
|
+
subjectId: string;
|
|
109
|
+
capabilityId: string;
|
|
110
|
+
instanceKey: string;
|
|
111
|
+
facetKey: string;
|
|
112
|
+
idempotencyKey: string;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export function integrationFacetConfigureRequestDigest(input: {
|
|
116
|
+
capabilityId: string;
|
|
117
|
+
instanceKey: string;
|
|
118
|
+
facetKey: string;
|
|
119
|
+
displayName: string;
|
|
120
|
+
config: Record<string, unknown>;
|
|
121
|
+
expectedVersion?: number;
|
|
122
|
+
}): string {
|
|
123
|
+
return sha256(
|
|
124
|
+
stableJson({
|
|
125
|
+
action: "configure",
|
|
126
|
+
capabilityId: input.capabilityId,
|
|
127
|
+
instanceKey: input.instanceKey,
|
|
128
|
+
facetKey: input.facetKey,
|
|
129
|
+
displayName: input.displayName,
|
|
130
|
+
config: input.config,
|
|
131
|
+
expectedVersion: input.expectedVersion ?? null,
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Replays only an exact completed Integration Facet receipt. This intentionally
|
|
138
|
+
* runs before mutable instance/Connection/provider validation at HTTP edges.
|
|
139
|
+
*/
|
|
140
|
+
export async function replayCompletedIntegrationFacetOperation<T extends Record<string, unknown>>(
|
|
141
|
+
db: Database,
|
|
142
|
+
input: IntegrationFacetOperationIdentity & {
|
|
143
|
+
kind: IntegrationFacetOperationKind;
|
|
144
|
+
expectedRequestDigest: string | ((result: T) => string);
|
|
145
|
+
},
|
|
146
|
+
): Promise<T | null> {
|
|
147
|
+
return await withRlsContext(
|
|
148
|
+
db,
|
|
149
|
+
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
150
|
+
async (scopedDb) => {
|
|
151
|
+
await setSubjectRlsContext(scopedDb, input.subjectId);
|
|
152
|
+
return await scopedDb.transaction(async (txRaw) => {
|
|
153
|
+
const tx = txRaw as unknown as Database;
|
|
154
|
+
await lockFacetOperation(tx, input);
|
|
155
|
+
const existing = await loadFacetOperation(tx, input);
|
|
156
|
+
if (!existing) return null;
|
|
157
|
+
const result = replayFacetOperation<T>(
|
|
158
|
+
existing,
|
|
159
|
+
input,
|
|
160
|
+
input.kind,
|
|
161
|
+
input.expectedRequestDigest,
|
|
162
|
+
);
|
|
163
|
+
return await hydrateFacetOperationResult(tx, input, result);
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
99
169
|
type IntegrationInstanceContext = {
|
|
100
170
|
accountId: string;
|
|
101
171
|
integrationFacetInstallationId: string;
|
|
@@ -164,6 +234,10 @@ export async function listIntegrationInstanceFacets(
|
|
|
164
234
|
asc(schema.integrationFacetDefinitions.kind),
|
|
165
235
|
asc(schema.integrationFacetDefinitions.facetKey),
|
|
166
236
|
);
|
|
237
|
+
const ownersByBindingId = await listIntegrationFacetBindingOwnersForBindings(
|
|
238
|
+
scopedDb,
|
|
239
|
+
rows.flatMap((row) => (row.bindingId ? [row.bindingId] : [])),
|
|
240
|
+
);
|
|
167
241
|
return {
|
|
168
242
|
capabilityId,
|
|
169
243
|
instanceKey,
|
|
@@ -177,22 +251,26 @@ export async function listIntegrationInstanceFacets(
|
|
|
177
251
|
capabilities: row.capabilities,
|
|
178
252
|
},
|
|
179
253
|
binding: row.bindingId
|
|
180
|
-
? bindingSummary(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
254
|
+
? bindingSummary(
|
|
255
|
+
{
|
|
256
|
+
id: row.bindingId,
|
|
257
|
+
facetKey: row.facetKey,
|
|
258
|
+
kind: row.kind,
|
|
259
|
+
bindingKey: row.bindingKey!,
|
|
260
|
+
displayName: row.displayName!,
|
|
261
|
+
connectionId: row.connectionId ?? null,
|
|
262
|
+
status: row.status!,
|
|
263
|
+
config: row.config!,
|
|
264
|
+
cursor: row.cursor!,
|
|
265
|
+
version: row.version!,
|
|
266
|
+
lastSuccessAt: row.lastSuccessAt ?? null,
|
|
267
|
+
lastErrorCode: row.lastErrorCode ?? null,
|
|
268
|
+
createdAt: row.createdAt!,
|
|
269
|
+
updatedAt: row.updatedAt!,
|
|
270
|
+
},
|
|
271
|
+
ownersByBindingId.get(row.bindingId) ?? [],
|
|
272
|
+
{ capabilityId, instanceKey, facetKey: row.facetKey },
|
|
273
|
+
)
|
|
196
274
|
: null,
|
|
197
275
|
})),
|
|
198
276
|
};
|
|
@@ -214,17 +292,7 @@ export async function configureIntegrationFacet(
|
|
|
214
292
|
idempotencyKey: string;
|
|
215
293
|
},
|
|
216
294
|
): Promise<IntegrationFacetMutationResult> {
|
|
217
|
-
const requestDigest =
|
|
218
|
-
stableJson({
|
|
219
|
-
action: "configure",
|
|
220
|
-
capabilityId: input.capabilityId,
|
|
221
|
-
instanceKey: input.instanceKey,
|
|
222
|
-
facetKey: input.facetKey,
|
|
223
|
-
displayName: input.displayName,
|
|
224
|
-
config: input.config,
|
|
225
|
-
expectedVersion: input.expectedVersion ?? null,
|
|
226
|
-
}),
|
|
227
|
-
);
|
|
295
|
+
const requestDigest = integrationFacetConfigureRequestDigest(input);
|
|
228
296
|
return await withFacetOperation(db, input, requestDigest, "configure", async (tx) => {
|
|
229
297
|
const context = await requireMutationContext(tx, input);
|
|
230
298
|
const definition = await requireFacetDefinition(tx, context, input.facetKey);
|
|
@@ -244,16 +312,21 @@ export async function configureIntegrationFacet(
|
|
|
244
312
|
owner: facetOwner(input.capabilityId, input.instanceKey, input.facetKey),
|
|
245
313
|
...(input.expectedVersion !== undefined ? { expectedVersion: input.expectedVersion } : {}),
|
|
246
314
|
});
|
|
315
|
+
const owners = await listIntegrationFacetBindingOwners(tx, result.row.id);
|
|
247
316
|
return {
|
|
248
317
|
capabilityId: input.capabilityId,
|
|
249
318
|
instanceKey: input.instanceKey,
|
|
250
319
|
facetKey: input.facetKey,
|
|
251
320
|
status: "configured",
|
|
252
|
-
binding: bindingSummary(
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
321
|
+
binding: bindingSummary(
|
|
322
|
+
{
|
|
323
|
+
...result.row,
|
|
324
|
+
facetKey: definition.facetKey,
|
|
325
|
+
kind: definition.kind,
|
|
326
|
+
},
|
|
327
|
+
owners,
|
|
328
|
+
input,
|
|
329
|
+
),
|
|
257
330
|
};
|
|
258
331
|
});
|
|
259
332
|
}
|
|
@@ -312,16 +385,21 @@ export async function setIntegrationFacetLifecycle(
|
|
|
312
385
|
if (!updated) throw new Error("Failed to update Integration facet lifecycle");
|
|
313
386
|
row = updated;
|
|
314
387
|
}
|
|
388
|
+
const owners = await listIntegrationFacetBindingOwners(tx, row.id);
|
|
315
389
|
return {
|
|
316
390
|
capabilityId: input.capabilityId,
|
|
317
391
|
instanceKey: input.instanceKey,
|
|
318
392
|
facetKey: input.facetKey,
|
|
319
393
|
status: input.action === "pause" ? "paused" : "active",
|
|
320
|
-
binding: bindingSummary(
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
394
|
+
binding: bindingSummary(
|
|
395
|
+
{
|
|
396
|
+
...row,
|
|
397
|
+
facetKey: definition.facetKey,
|
|
398
|
+
kind: definition.kind,
|
|
399
|
+
},
|
|
400
|
+
owners,
|
|
401
|
+
input,
|
|
402
|
+
),
|
|
325
403
|
};
|
|
326
404
|
});
|
|
327
405
|
}
|
|
@@ -377,11 +455,15 @@ export async function removeIntegrationFacet(
|
|
|
377
455
|
instanceKey: input.instanceKey,
|
|
378
456
|
facetKey: input.facetKey,
|
|
379
457
|
status: "not_configured",
|
|
380
|
-
binding: bindingSummary(
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
458
|
+
binding: bindingSummary(
|
|
459
|
+
{
|
|
460
|
+
...binding,
|
|
461
|
+
facetKey: definition.facetKey,
|
|
462
|
+
kind: definition.kind,
|
|
463
|
+
},
|
|
464
|
+
owners,
|
|
465
|
+
input,
|
|
466
|
+
),
|
|
385
467
|
remainingOwners: owners,
|
|
386
468
|
};
|
|
387
469
|
}
|
|
@@ -391,17 +473,24 @@ export async function removeIntegrationFacet(
|
|
|
391
473
|
owner,
|
|
392
474
|
expectedVersion: input.expectedVersion,
|
|
393
475
|
});
|
|
476
|
+
const effectiveRemainingOwners = removed.binding
|
|
477
|
+
? await listIntegrationFacetBindingOwners(tx, removed.binding.id)
|
|
478
|
+
: [];
|
|
394
479
|
return {
|
|
395
480
|
capabilityId: input.capabilityId,
|
|
396
481
|
instanceKey: input.instanceKey,
|
|
397
482
|
facetKey: input.facetKey,
|
|
398
483
|
status: removed.remainingOwners.length > 0 ? "retained_by_other_owners" : "removed",
|
|
399
484
|
binding: removed.binding
|
|
400
|
-
? bindingSummary(
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
485
|
+
? bindingSummary(
|
|
486
|
+
{
|
|
487
|
+
...removed.binding,
|
|
488
|
+
facetKey: definition.facetKey,
|
|
489
|
+
kind: definition.kind,
|
|
490
|
+
},
|
|
491
|
+
effectiveRemainingOwners,
|
|
492
|
+
input,
|
|
493
|
+
)
|
|
405
494
|
: null,
|
|
406
495
|
remainingOwners: removed.remainingOwners,
|
|
407
496
|
};
|
|
@@ -410,17 +499,9 @@ export async function removeIntegrationFacet(
|
|
|
410
499
|
|
|
411
500
|
async function withFacetOperation<T extends Record<string, unknown>>(
|
|
412
501
|
db: Database,
|
|
413
|
-
input:
|
|
414
|
-
accountId: string;
|
|
415
|
-
workspaceId: string;
|
|
416
|
-
subjectId: string;
|
|
417
|
-
capabilityId: string;
|
|
418
|
-
instanceKey: string;
|
|
419
|
-
facetKey: string;
|
|
420
|
-
idempotencyKey: string;
|
|
421
|
-
},
|
|
502
|
+
input: IntegrationFacetOperationIdentity,
|
|
422
503
|
requestDigest: string,
|
|
423
|
-
kind:
|
|
504
|
+
kind: IntegrationFacetOperationKind,
|
|
424
505
|
execute: (tx: Database) => Promise<T>,
|
|
425
506
|
): Promise<T> {
|
|
426
507
|
return await withRlsContext(
|
|
@@ -430,30 +511,11 @@ async function withFacetOperation<T extends Record<string, unknown>>(
|
|
|
430
511
|
await setSubjectRlsContext(scopedDb, input.subjectId);
|
|
431
512
|
return await scopedDb.transaction(async (txRaw) => {
|
|
432
513
|
const tx = txRaw as unknown as Database;
|
|
433
|
-
await tx
|
|
434
|
-
|
|
435
|
-
);
|
|
436
|
-
const [existing] = await tx
|
|
437
|
-
.select()
|
|
438
|
-
.from(schema.capabilityOperations)
|
|
439
|
-
.where(
|
|
440
|
-
and(
|
|
441
|
-
eq(schema.capabilityOperations.workspaceId, input.workspaceId),
|
|
442
|
-
eq(schema.capabilityOperations.idempotencyKey, input.idempotencyKey),
|
|
443
|
-
),
|
|
444
|
-
)
|
|
445
|
-
.for("update")
|
|
446
|
-
.limit(1);
|
|
514
|
+
await lockFacetOperation(tx, input);
|
|
515
|
+
const existing = await loadFacetOperation(tx, input);
|
|
447
516
|
if (existing) {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
"Integration facet idempotency key was reused",
|
|
451
|
-
);
|
|
452
|
-
}
|
|
453
|
-
if (existing.status === "completed" && existing.result) return existing.result as T;
|
|
454
|
-
throw new IntegrationFacetOperationIdempotencyError(
|
|
455
|
-
"Integration facet operation is already in progress",
|
|
456
|
-
);
|
|
517
|
+
const result = replayFacetOperation<T>(existing, input, kind, requestDigest);
|
|
518
|
+
return await hydrateFacetOperationResult(tx, input, result);
|
|
457
519
|
}
|
|
458
520
|
const result = await execute(tx);
|
|
459
521
|
await tx.insert(schema.capabilityOperations).values({
|
|
@@ -463,9 +525,7 @@ async function withFacetOperation<T extends Record<string, unknown>>(
|
|
|
463
525
|
requestDigest,
|
|
464
526
|
kind,
|
|
465
527
|
targetKind: "facet_binding",
|
|
466
|
-
targetId:
|
|
467
|
-
`${input.capabilityId}\0${input.instanceKey}\0${input.facetKey}`,
|
|
468
|
-
)}`,
|
|
528
|
+
targetId: facetOperationTargetId(input),
|
|
469
529
|
status: "completed",
|
|
470
530
|
phase: "completed",
|
|
471
531
|
result,
|
|
@@ -478,6 +538,140 @@ async function withFacetOperation<T extends Record<string, unknown>>(
|
|
|
478
538
|
);
|
|
479
539
|
}
|
|
480
540
|
|
|
541
|
+
async function lockFacetOperation(
|
|
542
|
+
db: Database,
|
|
543
|
+
input: Pick<IntegrationFacetOperationIdentity, "workspaceId" | "idempotencyKey">,
|
|
544
|
+
): Promise<void> {
|
|
545
|
+
await db.execute(
|
|
546
|
+
sql`select pg_advisory_xact_lock(hashtextextended(${`capability-operation:${input.workspaceId}:${input.idempotencyKey}`}, 0))`,
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
async function loadFacetOperation(
|
|
551
|
+
db: Database,
|
|
552
|
+
input: Pick<IntegrationFacetOperationIdentity, "accountId" | "workspaceId" | "idempotencyKey">,
|
|
553
|
+
) {
|
|
554
|
+
const [existing] = await db
|
|
555
|
+
.select()
|
|
556
|
+
.from(schema.capabilityOperations)
|
|
557
|
+
.where(
|
|
558
|
+
and(
|
|
559
|
+
eq(schema.capabilityOperations.accountId, input.accountId),
|
|
560
|
+
eq(schema.capabilityOperations.workspaceId, input.workspaceId),
|
|
561
|
+
eq(schema.capabilityOperations.idempotencyKey, input.idempotencyKey),
|
|
562
|
+
),
|
|
563
|
+
)
|
|
564
|
+
.for("update")
|
|
565
|
+
.limit(1);
|
|
566
|
+
return existing;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function replayFacetOperation<T extends Record<string, unknown>>(
|
|
570
|
+
existing: typeof schema.capabilityOperations.$inferSelect,
|
|
571
|
+
input: IntegrationFacetOperationIdentity,
|
|
572
|
+
kind: IntegrationFacetOperationKind,
|
|
573
|
+
expectedRequestDigest: string | ((result: T) => string),
|
|
574
|
+
): T {
|
|
575
|
+
if (
|
|
576
|
+
existing.createdBySubjectId !== input.subjectId ||
|
|
577
|
+
existing.kind !== kind ||
|
|
578
|
+
existing.targetKind !== "facet_binding" ||
|
|
579
|
+
existing.targetId !== facetOperationTargetId(input)
|
|
580
|
+
) {
|
|
581
|
+
throw new IntegrationFacetOperationIdempotencyError(
|
|
582
|
+
"Integration facet idempotency key was reused",
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
if (
|
|
586
|
+
typeof expectedRequestDigest === "string" &&
|
|
587
|
+
existing.requestDigest !== expectedRequestDigest
|
|
588
|
+
) {
|
|
589
|
+
throw new IntegrationFacetOperationIdempotencyError(
|
|
590
|
+
"Integration facet idempotency key was reused",
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
if (existing.status !== "completed" || !existing.result) {
|
|
594
|
+
throw new IntegrationFacetOperationIdempotencyError(
|
|
595
|
+
"Integration facet operation is already in progress",
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
const result = existing.result as T;
|
|
599
|
+
const requestDigest =
|
|
600
|
+
typeof expectedRequestDigest === "string"
|
|
601
|
+
? expectedRequestDigest
|
|
602
|
+
: expectedRequestDigest(result);
|
|
603
|
+
if (existing.requestDigest !== requestDigest) {
|
|
604
|
+
throw new IntegrationFacetOperationIdempotencyError(
|
|
605
|
+
"Integration facet idempotency key was reused",
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
return result;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
function facetOperationTargetId(
|
|
612
|
+
input: Pick<IntegrationFacetOperationIdentity, "capabilityId" | "instanceKey" | "facetKey">,
|
|
613
|
+
): string {
|
|
614
|
+
return `facet:${sha256(`${input.capabilityId}\0${input.instanceKey}\0${input.facetKey}`)}`;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
async function hydrateFacetOperationResult<T extends Record<string, unknown>>(
|
|
618
|
+
db: Database,
|
|
619
|
+
input: { capabilityId: string; instanceKey: string; facetKey: string },
|
|
620
|
+
result: T,
|
|
621
|
+
): Promise<T> {
|
|
622
|
+
const binding = recordValue(result.binding);
|
|
623
|
+
if (!binding) return result;
|
|
624
|
+
if (typeof binding.directlyOwned === "boolean" && Array.isArray(binding.owners)) return result;
|
|
625
|
+
|
|
626
|
+
const expectedOwner = facetOwner(input.capabilityId, input.instanceKey, input.facetKey);
|
|
627
|
+
let owners =
|
|
628
|
+
typeof binding.id === "string" ? await listIntegrationFacetBindingOwners(db, binding.id) : [];
|
|
629
|
+
if (owners.length === 0) {
|
|
630
|
+
owners = capabilityComponentOwners(result.remainingOwners);
|
|
631
|
+
}
|
|
632
|
+
if (
|
|
633
|
+
owners.length === 0 &&
|
|
634
|
+
(result.status === "configured" || result.status === "paused" || result.status === "active")
|
|
635
|
+
) {
|
|
636
|
+
owners = [expectedOwner];
|
|
637
|
+
}
|
|
638
|
+
return {
|
|
639
|
+
...result,
|
|
640
|
+
binding: {
|
|
641
|
+
...binding,
|
|
642
|
+
directlyOwned: owners.some(
|
|
643
|
+
(owner) => owner.kind === expectedOwner.kind && owner.id === expectedOwner.id,
|
|
644
|
+
),
|
|
645
|
+
owners,
|
|
646
|
+
},
|
|
647
|
+
} as T;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
function capabilityComponentOwners(value: unknown): IntegrationFacetBindingOwner[] {
|
|
651
|
+
if (!Array.isArray(value)) return [];
|
|
652
|
+
return value.flatMap((entry) => {
|
|
653
|
+
const owner = recordValue(entry);
|
|
654
|
+
if (
|
|
655
|
+
!owner ||
|
|
656
|
+
(owner.kind !== "direct" &&
|
|
657
|
+
owner.kind !== "plugin" &&
|
|
658
|
+
owner.kind !== "pack" &&
|
|
659
|
+
owner.kind !== "migration") ||
|
|
660
|
+
typeof owner.id !== "string" ||
|
|
661
|
+
typeof owner.removable !== "boolean"
|
|
662
|
+
) {
|
|
663
|
+
return [];
|
|
664
|
+
}
|
|
665
|
+
return [{ kind: owner.kind, id: owner.id, removable: owner.removable }];
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
function recordValue(value: unknown): Record<string, unknown> | null {
|
|
670
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
671
|
+
? (value as Record<string, unknown>)
|
|
672
|
+
: null;
|
|
673
|
+
}
|
|
674
|
+
|
|
481
675
|
async function requireMutationContext(
|
|
482
676
|
db: Database,
|
|
483
677
|
input: {
|
|
@@ -705,7 +899,12 @@ type BindingSummaryRow = Pick<
|
|
|
705
899
|
kind: string;
|
|
706
900
|
};
|
|
707
901
|
|
|
708
|
-
function bindingSummary(
|
|
902
|
+
function bindingSummary(
|
|
903
|
+
row: BindingSummaryRow,
|
|
904
|
+
owners: IntegrationFacetBindingOwner[],
|
|
905
|
+
identity: { capabilityId: string; instanceKey: string; facetKey: string },
|
|
906
|
+
): IntegrationFacetBindingSummary {
|
|
907
|
+
const expectedOwner = facetOwner(identity.capabilityId, identity.instanceKey, identity.facetKey);
|
|
709
908
|
return {
|
|
710
909
|
id: row.id,
|
|
711
910
|
facetKey: row.facetKey,
|
|
@@ -721,6 +920,10 @@ function bindingSummary(row: BindingSummaryRow): IntegrationFacetBindingSummary
|
|
|
721
920
|
lastErrorCode: row.lastErrorCode,
|
|
722
921
|
createdAt: row.createdAt.toISOString(),
|
|
723
922
|
updatedAt: row.updatedAt.toISOString(),
|
|
923
|
+
directlyOwned: owners.some(
|
|
924
|
+
(owner) => owner.kind === expectedOwner.kind && owner.id === expectedOwner.id,
|
|
925
|
+
),
|
|
926
|
+
owners,
|
|
724
927
|
};
|
|
725
928
|
}
|
|
726
929
|
|