@opengeni/db 0.31.1 → 0.36.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.
Files changed (122) hide show
  1. package/dist/browser-auth.d.ts +209 -1
  2. package/dist/browser-downloads.d.ts +51 -0
  3. package/dist/browser-identities.d.ts +11 -2
  4. package/dist/browser-sessions.d.ts +83 -1
  5. package/dist/browser-state-artifacts.d.ts +75 -1
  6. package/dist/canonical-human-identities.d.ts +48 -0
  7. package/dist/canonical-human-identities.js +28 -0
  8. package/dist/canonical-human-identities.js.map +1 -0
  9. package/dist/capability-integrations.d.ts +8 -6
  10. package/dist/{chunk-MWDVXQOL.js → chunk-5KTIEDX7.js} +5773 -4212
  11. package/dist/chunk-5KTIEDX7.js.map +1 -0
  12. package/dist/{chunk-NBE6CHRI.js → chunk-CQZ4QSP5.js} +49 -9
  13. package/dist/chunk-CQZ4QSP5.js.map +1 -0
  14. package/dist/chunk-F32YT7MP.js +117 -0
  15. package/dist/chunk-F32YT7MP.js.map +1 -0
  16. package/dist/{chunk-ISI2TIUG.js → chunk-JC5QPLUM.js} +30 -3
  17. package/dist/chunk-JC5QPLUM.js.map +1 -0
  18. package/dist/{chunk-F5FT7BEZ.js → chunk-P3RE4D2B.js} +2 -2
  19. package/dist/chunk-TAUTWOS5.js +259 -0
  20. package/dist/chunk-TAUTWOS5.js.map +1 -0
  21. package/dist/{chunk-YHZXQ7HP.js → chunk-VKLB2ZGI.js} +446 -19
  22. package/dist/chunk-VKLB2ZGI.js.map +1 -0
  23. package/dist/database.d.ts +5 -0
  24. package/dist/editable-artifact-durable-export.js +2 -2
  25. package/dist/editable-artifacts.js +3 -3
  26. package/dist/index.d.ts +438 -29
  27. package/dist/index.js +35640 -28969
  28. package/dist/index.js.map +1 -1
  29. package/dist/insights.d.ts +23 -7
  30. package/dist/integration-bindings.d.ts +24 -24
  31. package/dist/integration-facets.d.ts +99 -0
  32. package/dist/interaction-revisions.d.ts +11 -0
  33. package/dist/interaction-schema.d.ts +698 -34
  34. package/dist/provision-roles.js +1 -1
  35. package/dist/runtime-posture.d.ts +8 -7
  36. package/dist/schema.d.ts +9464 -5412
  37. package/dist/schema.js +51 -9
  38. package/dist/session-control.d.ts +29 -3
  39. package/dist/session-tenancy.d.ts +44 -0
  40. package/dist/session-tenancy.js +16 -0
  41. package/dist/session-tenancy.js.map +1 -0
  42. package/dist/slack-task-policy-schema.d.ts +847 -0
  43. package/dist/slack-task-policy.d.ts +65 -0
  44. package/dist/task-notes-schema.d.ts +924 -0
  45. package/dist/task-notes.d.ts +85 -0
  46. package/dist/video-generation.d.ts +9 -0
  47. package/dist/video-generation.js +5 -3
  48. package/dist/xai-subscription.d.ts +326 -0
  49. package/drizzle/0212_browser_state_transfer_hardening.sql +560 -0
  50. package/drizzle/0213_browser_interaction_authority.sql +67 -0
  51. package/drizzle/0214_browser_download_saves.sql +34 -0
  52. package/drizzle/0215_browser_controller_host.sql +385 -0
  53. package/drizzle/0216_browser_auth_health_evidence.sql +137 -0
  54. package/drizzle/0217_external_browser_auth_operations.sql +22 -0
  55. package/drizzle/0218_organization_tenancy_foundation.sql +299 -0
  56. package/drizzle/0219_organization_tenancy_managed_human_provisioning.sql +317 -0
  57. package/drizzle/0219_site_auth_maintenance_sessions.sql +234 -0
  58. package/drizzle/0220_memory_slack_append_only_cascade.sql +38 -0
  59. package/drizzle/0220_session_channels.sql +54 -0
  60. package/drizzle/0221_sessions_channel_index.sql +5 -0
  61. package/drizzle/0222_session_visibility_authority_epochs.sql +158 -0
  62. package/drizzle/0222_sessions_channel_fk.sql +89 -0
  63. package/drizzle/0223_pending_tool_event_output.sql +55 -0
  64. package/drizzle/0223_sessions_channel_fk_validate.sql +118 -0
  65. package/drizzle/0224_slack_post_outcome_reconciliation.sql +123 -0
  66. package/drizzle/0225_session_visibility_fork_activation.sql +1363 -0
  67. package/drizzle/0226_personal_codex_authority_foundation.sql +365 -0
  68. package/drizzle/0227_slack_native_actions.sql +145 -0
  69. package/drizzle/0228_interaction_controller_data_plane.sql +14 -0
  70. package/drizzle/0228_slack_task_policy.sql +400 -0
  71. package/drizzle/0229_slack_inbox_file_fact.sql +10 -0
  72. package/drizzle/0230_user_scoped_variable_sets_rigs.sql +84 -0
  73. package/drizzle/0231_integration_definition_identity_cutover.sql +271 -0
  74. package/drizzle/0232_integration_facet_authority_cutover.sql +610 -0
  75. package/drizzle/0233_skill_and_integration_authority_cutover.sql +1162 -0
  76. package/drizzle/0234_xai_subscription_authority.sql +1139 -0
  77. package/drizzle/0235_canonical_human_login_bindings.sql +920 -0
  78. package/drizzle/0236_browser_identity_lifecycle.sql +39 -0
  79. package/drizzle/0236_session_visibility_slack_policy.sql +72 -0
  80. package/drizzle/0237_interaction_transition_reaper.sql +263 -0
  81. package/drizzle/0238_goal_persistence_policy.sql +471 -0
  82. package/drizzle/0238_supergrok_realtime_model.sql +29 -0
  83. package/drizzle/0239_supergrok_video_funding.sql +50 -0
  84. package/drizzle/0239_task_tree_notes.sql +990 -0
  85. package/package.json +13 -5
  86. package/src/browser-auth.ts +2600 -123
  87. package/src/browser-downloads.ts +517 -0
  88. package/src/browser-identities.ts +220 -3
  89. package/src/browser-sessions.ts +334 -45
  90. package/src/browser-state-artifacts.ts +402 -12
  91. package/src/canonical-human-identities.ts +317 -0
  92. package/src/capability-integrations.ts +121 -213
  93. package/src/database.ts +41 -1
  94. package/src/index.ts +4157 -394
  95. package/src/insights.ts +109 -28
  96. package/src/integration-bindings.ts +101 -101
  97. package/src/{integration-features.ts → integration-facets.ts} +187 -184
  98. package/src/interaction-revisions.ts +33 -3
  99. package/src/interaction-schema.ts +311 -8
  100. package/src/pack-components.ts +43 -43
  101. package/src/pack-installations.ts +0 -43
  102. package/src/plugin-packages.ts +9 -9
  103. package/src/provision-roles.ts +232 -0
  104. package/src/runtime-posture.ts +227 -14
  105. package/src/schema.ts +1188 -75
  106. package/src/session-control.ts +122 -37
  107. package/src/session-queue-commands.ts +78 -1
  108. package/src/session-tenancy.ts +188 -0
  109. package/src/session-tool-call-settlement.ts +9 -3
  110. package/src/slack-task-policy-schema.ts +130 -0
  111. package/src/slack-task-policy.ts +341 -0
  112. package/src/task-notes-schema.ts +135 -0
  113. package/src/task-notes.ts +178 -0
  114. package/src/video-generation.ts +90 -12
  115. package/src/workspace-artifacts.ts +1 -1
  116. package/src/xai-subscription.ts +1887 -0
  117. package/dist/chunk-ISI2TIUG.js.map +0 -1
  118. package/dist/chunk-MWDVXQOL.js.map +0 -1
  119. package/dist/chunk-NBE6CHRI.js.map +0 -1
  120. package/dist/chunk-YHZXQ7HP.js.map +0 -1
  121. package/dist/integration-features.d.ts +0 -99
  122. /package/dist/{chunk-F5FT7BEZ.js.map → chunk-P3RE4D2B.js.map} +0 -0
@@ -16,14 +16,14 @@ import {
16
16
  type Database,
17
17
  } from "./database";
18
18
  import {
19
- ensureIntegrationFeatureFacet,
19
+ ensureIntegrationFacetDefinition,
20
20
  integrationBindingKey,
21
21
  integrationDefinitionHasBindingOwner,
22
22
  integrationRuntimeKey,
23
- listIntegrationFeatureBindingOwners,
24
- removeIntegrationFeatureBindingOwner,
25
- upsertIntegrationFeatureBinding,
26
- type IntegrationFeatureBindingOwner,
23
+ listIntegrationFacetBindingOwners,
24
+ removeIntegrationFacetBindingOwner,
25
+ upsertIntegrationFacetBinding,
26
+ type IntegrationFacetBindingOwner,
27
27
  } from "./integration-bindings";
28
28
  import * as schema from "./schema";
29
29
 
@@ -31,8 +31,8 @@ export type ApiIntegrationProtocol = "openapi" | "graphql";
31
31
  export type ApiIntegrationToolSafety = "read" | "write" | "destructive";
32
32
  export type ApiIntegrationApprovalMode = "never" | "ask";
33
33
 
34
- export type ApiIntegrationFeatureDefinition = {
35
- readonly featureKey: string;
34
+ export type ApiIntegrationFacetDefinition = {
35
+ readonly facetKey: string;
36
36
  readonly kind: "knowledge_source" | "inbound_trigger" | "delivery_destination" | "identity_link";
37
37
  readonly configSchema: Readonly<Record<string, unknown>>;
38
38
  readonly capabilities: Readonly<Record<string, unknown>>;
@@ -52,7 +52,7 @@ export type ApiIntegrationToolDefinition = {
52
52
 
53
53
  type StoredApiIntegrationRevisionBase = {
54
54
  readonly id: string;
55
- readonly integrationId: string;
55
+ readonly definitionId: string;
56
56
  readonly contentSha256: string;
57
57
  readonly source: {
58
58
  readonly url?: string;
@@ -116,7 +116,8 @@ export type InstallApiIntegrationInput = {
116
116
  description?: string | null;
117
117
  category?: string;
118
118
  tags?: string[];
119
- presetId?: string | null;
119
+ definitionId: string;
120
+ definitionProvenance: "curated" | "workspace";
120
121
  provider?: string;
121
122
  providerDomain: string;
122
123
  protocol: ApiIntegrationProtocol;
@@ -130,7 +131,7 @@ export type InstallApiIntegrationInput = {
130
131
  requiredScopes?: string[];
131
132
  ownership?: "workspace" | "subject" | "either";
132
133
  allowedTools?: string[];
133
- featureDefinitions?: readonly ApiIntegrationFeatureDefinition[];
134
+ facetDefinitions?: readonly ApiIntegrationFacetDefinition[];
134
135
  revision: StoredApiIntegrationRevision;
135
136
  owner?: ApiIntegrationOwner;
136
137
  };
@@ -167,7 +168,8 @@ export type ApiIntegrationRuntime = {
167
168
  name: string;
168
169
  description: string | null;
169
170
  protocol: ApiIntegrationProtocol;
170
- presetId: string | null;
171
+ definitionId: string;
172
+ definitionProvenance: "curated" | "workspace";
171
173
  baseUrl: string;
172
174
  sourceUrl: string | null;
173
175
  providerDomain: string;
@@ -291,7 +293,8 @@ export async function installApiIntegration(
291
293
  capabilityId: input.capabilityId,
292
294
  serverId: input.serverId,
293
295
  protocol: input.protocol,
294
- presetId: input.presetId ?? null,
296
+ definitionId: input.definitionId,
297
+ definitionProvenance: input.definitionProvenance,
295
298
  provider: input.provider ?? null,
296
299
  providerDomain: input.providerDomain,
297
300
  baseUrl: input.baseUrl,
@@ -391,7 +394,7 @@ export async function installApiIntegration(
391
394
  )
392
395
  .onConflictDoNothing();
393
396
 
394
- const owner: IntegrationFeatureBindingOwner = input.owner ?? {
397
+ const owner: IntegrationFacetBindingOwner = input.owner ?? {
395
398
  kind: "direct",
396
399
  id: input.capabilityId,
397
400
  removable: true,
@@ -401,9 +404,9 @@ export async function installApiIntegration(
401
404
  const displayName =
402
405
  input.displayName?.trim() ||
403
406
  (instanceKey === "default" ? input.name : `${input.name} — connected account`);
404
- const toolsFeature = await ensureIntegrationFeatureFacet(tx as unknown as Database, {
407
+ const toolsFacet = await ensureIntegrationFacetDefinition(tx as unknown as Database, {
405
408
  integrationFacetId: integrationFacet.id,
406
- featureKey: "tools",
409
+ facetKey: "tools",
407
410
  kind: "tools",
408
411
  configSchema: {
409
412
  type: "object",
@@ -415,18 +418,19 @@ export async function installApiIntegration(
415
418
  },
416
419
  capabilities: { protocol: input.protocol, runtime: "mcp" },
417
420
  });
418
- const featureFacets = new Map<string, typeof schema.integrationFeatureFacets.$inferSelect>([
419
- [toolsFeature.featureKey, toolsFeature],
420
- ]);
421
- for (const feature of input.featureDefinitions ?? []) {
422
- const facet = await ensureIntegrationFeatureFacet(tx as unknown as Database, {
421
+ const facetDefinitions = new Map<
422
+ string,
423
+ typeof schema.integrationFacetDefinitions.$inferSelect
424
+ >([[toolsFacet.facetKey, toolsFacet]]);
425
+ for (const definition of input.facetDefinitions ?? []) {
426
+ const facet = await ensureIntegrationFacetDefinition(tx as unknown as Database, {
423
427
  integrationFacetId: integrationFacet.id,
424
- featureKey: feature.featureKey,
425
- kind: feature.kind,
426
- configSchema: { ...feature.configSchema },
427
- capabilities: { ...feature.capabilities },
428
+ facetKey: definition.facetKey,
429
+ kind: definition.kind,
430
+ configSchema: { ...definition.configSchema },
431
+ capabilities: { ...definition.capabilities },
428
432
  });
429
- featureFacets.set(facet.featureKey, facet);
433
+ facetDefinitions.set(facet.facetKey, facet);
430
434
  }
431
435
 
432
436
  let [pluginInstallation] = await tx
@@ -521,7 +525,7 @@ export async function installApiIntegration(
521
525
  oldFacetInstallations,
522
526
  integrationFacetInstallationId: integrationFacetInstallation.id,
523
527
  apiFacetInstallationId: apiFacetInstallation.id,
524
- featureFacets,
528
+ facetDefinitions,
525
529
  excludedRuntimeKey: runtimeServerId,
526
530
  revision: input.revision,
527
531
  });
@@ -529,11 +533,11 @@ export async function installApiIntegration(
529
533
  const approvalRequiredTools = input.revision.tools
530
534
  .filter((tool) => selectedTools.includes(tool.id) && tool.approvalMode === "ask")
531
535
  .map((tool) => tool.id);
532
- const bindingResult = await upsertIntegrationFeatureBinding(tx as unknown as Database, {
536
+ const bindingResult = await upsertIntegrationFacetBinding(tx as unknown as Database, {
533
537
  accountId: input.accountId,
534
538
  workspaceId: input.workspaceId,
535
539
  integrationFacetInstallationId: integrationFacetInstallation.id,
536
- featureFacetId: toolsFeature.id,
540
+ facetDefinitionId: toolsFacet.id,
537
541
  bindingKey: instanceKey,
538
542
  displayName,
539
543
  runtimeKey: runtimeServerId,
@@ -592,101 +596,6 @@ export async function installApiIntegration(
592
596
  );
593
597
  }
594
598
 
595
- const compatibilityMetadata = {
596
- platformVersion: 2,
597
- protocol: input.protocol,
598
- provider: input.provider ?? null,
599
- providerDomain: input.providerDomain,
600
- pluginId: plugin.id,
601
- pluginVersionId: pluginVersion.id,
602
- integrationFacetId: integrationFacet.id,
603
- apiFacetId: apiFacet.id,
604
- revisionId: input.revision.id,
605
- contentSha256: input.revision.contentSha256,
606
- baseServerId: input.serverId,
607
- multiInstance: true,
608
- provenance: "workspace_import",
609
- };
610
- await tx
611
- .insert(schema.capabilityCatalogItems)
612
- .values({
613
- id: input.capabilityId,
614
- accountId: input.accountId,
615
- workspaceId: input.workspaceId,
616
- kind: "api",
617
- source: "manual",
618
- name: input.name,
619
- description: input.description ?? null,
620
- category: input.category ?? "integrations",
621
- tags: normalizedStrings(input.tags ?? ["integration", input.protocol], 64),
622
- homepageUrl: input.sourceUrl ?? input.baseUrl,
623
- endpointUrl: input.baseUrl,
624
- authModel: objectValue(input.authScheme ?? {}).kind
625
- ? String(objectValue(input.authScheme ?? {}).kind)
626
- : null,
627
- providerDomain: input.providerDomain,
628
- surfaceType: "api",
629
- authKind: connection ? connection.kind : "none",
630
- provenance: "workspace_import",
631
- tier: "community",
632
- metadata: compatibilityMetadata,
633
- updatedAt: now,
634
- })
635
- .onConflictDoUpdate({
636
- target: [schema.capabilityCatalogItems.workspaceId, schema.capabilityCatalogItems.id],
637
- set: {
638
- name: input.name,
639
- description: input.description ?? null,
640
- tags: normalizedStrings(input.tags ?? ["integration", input.protocol], 64),
641
- homepageUrl: input.sourceUrl ?? input.baseUrl,
642
- endpointUrl: input.baseUrl,
643
- authModel: objectValue(input.authScheme ?? {}).kind
644
- ? String(objectValue(input.authScheme ?? {}).kind)
645
- : null,
646
- providerDomain: input.providerDomain,
647
- surfaceType: "api",
648
- authKind: connection ? connection.kind : "none",
649
- metadata: compatibilityMetadata,
650
- updatedAt: now,
651
- },
652
- });
653
- await tx
654
- .insert(schema.capabilityInstallations)
655
- .values({
656
- accountId: input.accountId,
657
- workspaceId: input.workspaceId,
658
- capabilityId: input.capabilityId,
659
- kind: "api",
660
- status: "active",
661
- config: { baseServerId: input.serverId, multiInstance: true },
662
- metadata: {
663
- ...compatibilityMetadata,
664
- pluginInstallationId: pluginInstallation.id,
665
- integrationFacetInstallationId: integrationFacetInstallation.id,
666
- apiFacetInstallationId: apiFacetInstallation.id,
667
- },
668
- enabledAt: now,
669
- updatedAt: now,
670
- })
671
- .onConflictDoUpdate({
672
- target: [
673
- schema.capabilityInstallations.workspaceId,
674
- schema.capabilityInstallations.capabilityId,
675
- ],
676
- set: {
677
- status: "active",
678
- config: { baseServerId: input.serverId, multiInstance: true },
679
- metadata: {
680
- ...compatibilityMetadata,
681
- pluginInstallationId: pluginInstallation.id,
682
- integrationFacetInstallationId: integrationFacetInstallation.id,
683
- apiFacetInstallationId: apiFacetInstallation.id,
684
- },
685
- enabledAt: now,
686
- updatedAt: now,
687
- },
688
- });
689
-
690
599
  return {
691
600
  capabilityId: input.capabilityId,
692
601
  pluginId: plugin.id,
@@ -756,32 +665,32 @@ export async function listInstalledApiIntegrationsInRlsContext(
756
665
  authScheme: schema.capabilityApiFacets.authScheme,
757
666
  providerDomain: schema.capabilityIntegrationFacets.providerDomain,
758
667
  requiredScopes: schema.capabilityIntegrationFacets.requiredScopes,
759
- instanceId: schema.integrationFeatureBindings.id,
760
- instanceKey: schema.integrationFeatureBindings.bindingKey,
761
- displayName: schema.integrationFeatureBindings.displayName,
762
- instanceVersion: schema.integrationFeatureBindings.version,
763
- runtimeKey: schema.integrationFeatureBindings.runtimeKey,
764
- bindingConfig: schema.integrationFeatureBindings.config,
765
- connectionId: schema.integrationFeatureBindings.connectionId,
668
+ instanceId: schema.integrationFacetBindings.id,
669
+ instanceKey: schema.integrationFacetBindings.bindingKey,
670
+ displayName: schema.integrationFacetBindings.displayName,
671
+ instanceVersion: schema.integrationFacetBindings.version,
672
+ runtimeKey: schema.integrationFacetBindings.runtimeKey,
673
+ bindingConfig: schema.integrationFacetBindings.config,
674
+ connectionId: schema.integrationFacetBindings.connectionId,
766
675
  revision: schema.integrationSpecRevisions.spec,
767
676
  })
768
- .from(schema.integrationFeatureBindings)
677
+ .from(schema.integrationFacetBindings)
769
678
  .innerJoin(
770
- schema.integrationFeatureFacets,
771
- eq(schema.integrationFeatureFacets.id, schema.integrationFeatureBindings.featureFacetId),
679
+ schema.integrationFacetDefinitions,
680
+ eq(schema.integrationFacetDefinitions.id, schema.integrationFacetBindings.facetDefinitionId),
772
681
  )
773
682
  .innerJoin(
774
683
  schema.capabilityIntegrationFacets,
775
684
  eq(
776
685
  schema.capabilityIntegrationFacets.facetId,
777
- schema.integrationFeatureFacets.integrationFacetId,
686
+ schema.integrationFacetDefinitions.integrationFacetId,
778
687
  ),
779
688
  )
780
689
  .innerJoin(
781
690
  schema.capabilityFacetInstallations,
782
691
  eq(
783
692
  schema.capabilityFacetInstallations.id,
784
- schema.integrationFeatureBindings.integrationFacetInstallationId,
693
+ schema.integrationFacetBindings.integrationFacetInstallationId,
785
694
  ),
786
695
  )
787
696
  .innerJoin(
@@ -815,17 +724,17 @@ export async function listInstalledApiIntegrationsInRlsContext(
815
724
  eq(schema.capabilityPluginInstallations.workspaceId, workspaceId),
816
725
  eq(schema.capabilityPluginInstallations.status, "active"),
817
726
  eq(schema.capabilityFacetInstallations.status, "active"),
818
- eq(schema.integrationFeatureFacets.kind, "tools"),
819
- eq(schema.integrationFeatureBindings.status, "active"),
820
- sql`${schema.integrationFeatureBindings.runtimeKey} is not null`,
727
+ eq(schema.integrationFacetDefinitions.kind, "tools"),
728
+ eq(schema.integrationFacetBindings.status, "active"),
729
+ sql`${schema.integrationFacetBindings.runtimeKey} is not null`,
821
730
  sql`exists (
822
731
  select 1 from ${schema.capabilityComponentOwners} owner
823
732
  where owner.facet_installation_id = ${schema.capabilityFacetInstallations.id}
824
733
  and ${effectiveCapabilityOwnerSql(sql`owner.owner_kind`, sql`owner.owner_id`)}
825
734
  )`,
826
735
  sql`exists (
827
- select 1 from ${schema.integrationFeatureBindingOwners} owner
828
- where owner.binding_id = ${schema.integrationFeatureBindings.id}
736
+ select 1 from ${schema.integrationFacetBindingOwners} owner
737
+ where owner.binding_id = ${schema.integrationFacetBindings.id}
829
738
  and ${effectiveCapabilityOwnerSql(sql`owner.owner_kind`, sql`owner.owner_id`)}
830
739
  )`,
831
740
  sql`exists (
@@ -836,18 +745,18 @@ export async function listInstalledApiIntegrationsInRlsContext(
836
745
  )`,
837
746
  subjectId
838
747
  ? sql`(
839
- ${schema.integrationFeatureBindings.connectionId} is null
748
+ ${schema.integrationFacetBindings.connectionId} is null
840
749
  or exists (
841
750
  select 1 from ${schema.connections} connection
842
- where connection.id = ${schema.integrationFeatureBindings.connectionId}
751
+ where connection.id = ${schema.integrationFacetBindings.connectionId}
843
752
  and (connection.subject_id is null or connection.subject_id = ${subjectId})
844
753
  )
845
754
  )`
846
755
  : sql`(
847
- ${schema.integrationFeatureBindings.connectionId} is null
756
+ ${schema.integrationFacetBindings.connectionId} is null
848
757
  or exists (
849
758
  select 1 from ${schema.connections} connection
850
- where connection.id = ${schema.integrationFeatureBindings.connectionId}
759
+ where connection.id = ${schema.integrationFacetBindings.connectionId}
851
760
  and connection.subject_id is null
852
761
  )
853
762
  )`,
@@ -855,8 +764,8 @@ export async function listInstalledApiIntegrationsInRlsContext(
855
764
  )
856
765
  .orderBy(
857
766
  asc(schema.capabilityPlugins.name),
858
- asc(schema.integrationFeatureBindings.displayName),
859
- asc(schema.integrationFeatureBindings.bindingKey),
767
+ asc(schema.integrationFacetBindings.displayName),
768
+ asc(schema.integrationFacetBindings.bindingKey),
860
769
  );
861
770
 
862
771
  return rows.flatMap((row): ApiIntegrationRuntime[] => {
@@ -864,9 +773,16 @@ export async function listInstalledApiIntegrationsInRlsContext(
864
773
  const config = objectValue(row.bindingConfig);
865
774
  const manifest = objectValue(row.manifest);
866
775
  const capabilityId = stringValue(manifest.capabilityId);
867
- const presetId = stringValue(manifest.presetId) ?? null;
776
+ const definitionId = stringValue(manifest.definitionId);
777
+ const definitionProvenance = stringValue(manifest.definitionProvenance);
868
778
  const serverId = row.runtimeKey;
869
- if (!capabilityId || !serverId || row.protocol !== revision.protocol) {
779
+ if (
780
+ !capabilityId ||
781
+ !definitionId ||
782
+ (definitionProvenance !== "curated" && definitionProvenance !== "workspace") ||
783
+ !serverId ||
784
+ row.protocol !== revision.protocol
785
+ ) {
870
786
  throw new Error(`Installed API Integration ${row.pluginKey} has invalid immutable metadata`);
871
787
  }
872
788
  const allowedTools = stringArray(config.allowedTools) ?? revision.tools.map((tool) => tool.id);
@@ -904,7 +820,8 @@ export async function listInstalledApiIntegrationsInRlsContext(
904
820
  name: row.displayName,
905
821
  description: row.pluginDescription,
906
822
  protocol: revision.protocol,
907
- presetId,
823
+ definitionId,
824
+ definitionProvenance,
908
825
  baseUrl: row.baseUrl,
909
826
  sourceUrl: row.sourceUrl,
910
827
  providerDomain: row.providerDomain,
@@ -947,7 +864,7 @@ export async function getApiIntegrationUninstallPreview(
947
864
  removesDefinition: false,
948
865
  };
949
866
  }
950
- const owners = await listIntegrationFeatureBindingOwners(scopedDb, context.instanceId);
867
+ const owners = await listIntegrationFacetBindingOwners(scopedDb, context.instanceId);
951
868
  const directOwner = owners.find(
952
869
  (owner) => owner.kind === "direct" && owner.id === capabilityId,
953
870
  );
@@ -1024,7 +941,7 @@ export async function uninstallApiIntegration(
1024
941
  context.installationVersion,
1025
942
  );
1026
943
  }
1027
- const bindingOwners = await listIntegrationFeatureBindingOwners(
944
+ const bindingOwners = await listIntegrationFacetBindingOwners(
1028
945
  tx as unknown as Database,
1029
946
  context.instanceId,
1030
947
  );
@@ -1039,7 +956,7 @@ export async function uninstallApiIntegration(
1039
956
  definitionStatus: "retained",
1040
957
  };
1041
958
  }
1042
- const removed = await removeIntegrationFeatureBindingOwner(tx as unknown as Database, {
959
+ const removed = await removeIntegrationFacetBindingOwner(tx as unknown as Database, {
1043
960
  workspaceId: input.workspaceId,
1044
961
  bindingId: context.instanceId,
1045
962
  owner: { kind: "direct", id: input.capabilityId },
@@ -1100,15 +1017,6 @@ export async function uninstallApiIntegration(
1100
1017
  updatedAt: now,
1101
1018
  })
1102
1019
  .where(eq(schema.capabilityPluginInstallations.id, context.pluginInstallationId));
1103
- await tx
1104
- .update(schema.capabilityInstallations)
1105
- .set({ status: "disabled", updatedAt: now })
1106
- .where(
1107
- and(
1108
- eq(schema.capabilityInstallations.workspaceId, input.workspaceId),
1109
- eq(schema.capabilityInstallations.capabilityId, input.capabilityId),
1110
- ),
1111
- );
1112
1020
  return {
1113
1021
  capabilityId: input.capabilityId,
1114
1022
  instanceKey: input.instanceKey,
@@ -1150,7 +1058,7 @@ async function migrateApiIntegrationFacetInstallations(
1150
1058
  oldFacetInstallations: InstalledFacetRow[];
1151
1059
  integrationFacetInstallationId: string;
1152
1060
  apiFacetInstallationId: string;
1153
- featureFacets: ReadonlyMap<string, typeof schema.integrationFeatureFacets.$inferSelect>;
1061
+ facetDefinitions: ReadonlyMap<string, typeof schema.integrationFacetDefinitions.$inferSelect>;
1154
1062
  excludedRuntimeKey: string;
1155
1063
  revision: StoredApiIntegrationRevision;
1156
1064
  },
@@ -1192,22 +1100,22 @@ async function migrateApiIntegrationFacetInstallations(
1192
1100
  if (!oldIntegration) return;
1193
1101
  const bindings = await db
1194
1102
  .select({
1195
- binding: schema.integrationFeatureBindings,
1196
- featureKey: schema.integrationFeatureFacets.featureKey,
1197
- featureKind: schema.integrationFeatureFacets.kind,
1103
+ binding: schema.integrationFacetBindings,
1104
+ facetKey: schema.integrationFacetDefinitions.facetKey,
1105
+ facetKind: schema.integrationFacetDefinitions.kind,
1198
1106
  })
1199
- .from(schema.integrationFeatureBindings)
1107
+ .from(schema.integrationFacetBindings)
1200
1108
  .innerJoin(
1201
- schema.integrationFeatureFacets,
1202
- eq(schema.integrationFeatureFacets.id, schema.integrationFeatureBindings.featureFacetId),
1109
+ schema.integrationFacetDefinitions,
1110
+ eq(schema.integrationFacetDefinitions.id, schema.integrationFacetBindings.facetDefinitionId),
1203
1111
  )
1204
1112
  .where(
1205
1113
  and(
1206
- eq(schema.integrationFeatureBindings.workspaceId, input.workspaceId),
1207
- eq(schema.integrationFeatureBindings.integrationFacetInstallationId, oldIntegration.id),
1114
+ eq(schema.integrationFacetBindings.workspaceId, input.workspaceId),
1115
+ eq(schema.integrationFacetBindings.integrationFacetInstallationId, oldIntegration.id),
1208
1116
  or(
1209
- sql`${schema.integrationFeatureBindings.runtimeKey} is null`,
1210
- ne(schema.integrationFeatureBindings.runtimeKey, input.excludedRuntimeKey),
1117
+ sql`${schema.integrationFacetBindings.runtimeKey} is null`,
1118
+ ne(schema.integrationFacetBindings.runtimeKey, input.excludedRuntimeKey),
1211
1119
  ),
1212
1120
  ),
1213
1121
  )
@@ -1215,12 +1123,12 @@ async function migrateApiIntegrationFacetInstallations(
1215
1123
  const available = new Set(input.revision.tools.map((tool) => tool.id));
1216
1124
  for (const row of bindings) {
1217
1125
  const binding = row.binding;
1218
- const targetFeature = input.featureFacets.get(row.featureKey);
1219
- if (!targetFeature || targetFeature.kind !== row.featureKind) {
1220
- throw new Error(`API Integration update would remove configured feature ${row.featureKey}`);
1126
+ const targetFacet = input.facetDefinitions.get(row.facetKey);
1127
+ if (!targetFacet || targetFacet.kind !== row.facetKind) {
1128
+ throw new Error(`API Integration update would remove configured facet ${row.facetKey}`);
1221
1129
  }
1222
1130
  const config = objectValue(binding.config);
1223
- const toolsConfig = row.featureKind === "tools";
1131
+ const toolsConfig = row.facetKind === "tools";
1224
1132
  const selected = toolsConfig
1225
1133
  ? (stringArray(config.allowedTools) ?? []).filter((tool) => available.has(tool))
1226
1134
  : [];
@@ -1230,10 +1138,10 @@ async function migrateApiIntegrationFacetInstallations(
1230
1138
  .map((tool) => tool.id)
1231
1139
  : [];
1232
1140
  await db
1233
- .update(schema.integrationFeatureBindings)
1141
+ .update(schema.integrationFacetBindings)
1234
1142
  .set({
1235
1143
  integrationFacetInstallationId: input.integrationFacetInstallationId,
1236
- featureFacetId: targetFeature.id,
1144
+ facetDefinitionId: targetFacet.id,
1237
1145
  config: toolsConfig ? { ...config, allowedTools: selected, requireApproval } : config,
1238
1146
  status: toolsConfig && selected.length === 0 ? "needs_attention" : binding.status,
1239
1147
  lastErrorCode:
@@ -1241,7 +1149,7 @@ async function migrateApiIntegrationFacetInstallations(
1241
1149
  version: binding.version + 1,
1242
1150
  updatedAt: new Date(),
1243
1151
  })
1244
- .where(eq(schema.integrationFeatureBindings.id, binding.id));
1152
+ .where(eq(schema.integrationFacetBindings.id, binding.id));
1245
1153
  }
1246
1154
  }
1247
1155
 
@@ -1414,22 +1322,22 @@ async function integrationInstanceContext(
1414
1322
  ): Promise<IntegrationInstanceContext | null> {
1415
1323
  let query = db
1416
1324
  .select({
1417
- instanceId: schema.integrationFeatureBindings.id,
1418
- instanceVersion: schema.integrationFeatureBindings.version,
1419
- displayName: schema.integrationFeatureBindings.displayName,
1325
+ instanceId: schema.integrationFacetBindings.id,
1326
+ instanceVersion: schema.integrationFacetBindings.version,
1327
+ displayName: schema.integrationFacetBindings.displayName,
1420
1328
  pluginInstallationId: schema.capabilityPluginInstallations.id,
1421
1329
  installationVersion: schema.capabilityPluginInstallations.version,
1422
1330
  })
1423
- .from(schema.integrationFeatureBindings)
1331
+ .from(schema.integrationFacetBindings)
1424
1332
  .innerJoin(
1425
- schema.integrationFeatureFacets,
1426
- eq(schema.integrationFeatureFacets.id, schema.integrationFeatureBindings.featureFacetId),
1333
+ schema.integrationFacetDefinitions,
1334
+ eq(schema.integrationFacetDefinitions.id, schema.integrationFacetBindings.facetDefinitionId),
1427
1335
  )
1428
1336
  .innerJoin(
1429
1337
  schema.capabilityFacetInstallations,
1430
1338
  eq(
1431
1339
  schema.capabilityFacetInstallations.id,
1432
- schema.integrationFeatureBindings.integrationFacetInstallationId,
1340
+ schema.integrationFacetBindings.integrationFacetInstallationId,
1433
1341
  ),
1434
1342
  )
1435
1343
  .innerJoin(
@@ -1445,15 +1353,15 @@ async function integrationInstanceContext(
1445
1353
  )
1446
1354
  .where(
1447
1355
  and(
1448
- eq(schema.integrationFeatureBindings.workspaceId, workspaceId),
1449
- eq(schema.integrationFeatureBindings.bindingKey, instanceKey),
1450
- eq(schema.integrationFeatureFacets.kind, "tools"),
1356
+ eq(schema.integrationFacetBindings.workspaceId, workspaceId),
1357
+ eq(schema.integrationFacetBindings.bindingKey, instanceKey),
1358
+ eq(schema.integrationFacetDefinitions.kind, "tools"),
1451
1359
  sql`${schema.capabilityPluginVersions.manifest} ->> 'capabilityId' = ${capabilityId}`,
1452
1360
  sql`(
1453
- ${schema.integrationFeatureBindings.connectionId} is null
1361
+ ${schema.integrationFacetBindings.connectionId} is null
1454
1362
  or exists (
1455
1363
  select 1 from ${schema.connections} connection
1456
- where connection.id = ${schema.integrationFeatureBindings.connectionId}
1364
+ where connection.id = ${schema.integrationFacetBindings.connectionId}
1457
1365
  and (connection.subject_id is null or connection.subject_id = ${subjectId})
1458
1366
  )
1459
1367
  )`,
@@ -1473,34 +1381,34 @@ async function integrationDefinitionHasOtherBindingOwner(
1473
1381
  workspaceId: string;
1474
1382
  pluginInstallationId: string;
1475
1383
  excludedBindingId: string;
1476
- owner: Pick<IntegrationFeatureBindingOwner, "kind" | "id">;
1384
+ owner: Pick<IntegrationFacetBindingOwner, "kind" | "id">;
1477
1385
  },
1478
1386
  ): Promise<boolean> {
1479
1387
  const [row] = await db
1480
- .select({ id: schema.integrationFeatureBindingOwners.id })
1481
- .from(schema.integrationFeatureBindingOwners)
1388
+ .select({ id: schema.integrationFacetBindingOwners.id })
1389
+ .from(schema.integrationFacetBindingOwners)
1482
1390
  .innerJoin(
1483
- schema.integrationFeatureBindings,
1484
- eq(schema.integrationFeatureBindings.id, schema.integrationFeatureBindingOwners.bindingId),
1391
+ schema.integrationFacetBindings,
1392
+ eq(schema.integrationFacetBindings.id, schema.integrationFacetBindingOwners.bindingId),
1485
1393
  )
1486
1394
  .innerJoin(
1487
1395
  schema.capabilityFacetInstallations,
1488
1396
  eq(
1489
1397
  schema.capabilityFacetInstallations.id,
1490
- schema.integrationFeatureBindings.integrationFacetInstallationId,
1398
+ schema.integrationFacetBindings.integrationFacetInstallationId,
1491
1399
  ),
1492
1400
  )
1493
1401
  .where(
1494
1402
  and(
1495
- eq(schema.integrationFeatureBindingOwners.workspaceId, input.workspaceId),
1496
- eq(schema.integrationFeatureBindingOwners.ownerKind, input.owner.kind),
1497
- eq(schema.integrationFeatureBindingOwners.ownerId, input.owner.id),
1498
- ne(schema.integrationFeatureBindingOwners.bindingId, input.excludedBindingId),
1403
+ eq(schema.integrationFacetBindingOwners.workspaceId, input.workspaceId),
1404
+ eq(schema.integrationFacetBindingOwners.ownerKind, input.owner.kind),
1405
+ eq(schema.integrationFacetBindingOwners.ownerId, input.owner.id),
1406
+ ne(schema.integrationFacetBindingOwners.bindingId, input.excludedBindingId),
1499
1407
  eq(schema.capabilityFacetInstallations.pluginInstallationId, input.pluginInstallationId),
1500
1408
  or(
1501
- eq(schema.integrationFeatureBindings.status, "active"),
1502
- eq(schema.integrationFeatureBindings.status, "needs_attention"),
1503
- eq(schema.integrationFeatureBindings.status, "paused"),
1409
+ eq(schema.integrationFacetBindings.status, "active"),
1410
+ eq(schema.integrationFacetBindings.status, "needs_attention"),
1411
+ eq(schema.integrationFacetBindings.status, "paused"),
1504
1412
  ),
1505
1413
  ),
1506
1414
  )
@@ -1563,6 +1471,9 @@ async function integrationOwners(
1563
1471
  function assertInstallInput(input: InstallApiIntegrationInput): void {
1564
1472
  if (input.revision.protocol !== input.protocol)
1565
1473
  throw new Error("API Integration protocol mismatch");
1474
+ if (!input.definitionId.trim() || input.revision.definitionId !== input.definitionId) {
1475
+ throw new Error("API Integration Definition identity mismatch");
1476
+ }
1566
1477
  if (
1567
1478
  input.revision.contentSha256.length !== 64 ||
1568
1479
  !/^[0-9a-f]+$/.test(input.revision.contentSha256)
@@ -1575,15 +1486,12 @@ function assertInstallInput(input: InstallApiIntegrationInput): void {
1575
1486
  if (new Set(input.revision.tools.map((tool) => tool.id)).size !== input.revision.tools.length) {
1576
1487
  throw new Error("API Integration revision has duplicate tool ids");
1577
1488
  }
1578
- const featureDefinitions = input.featureDefinitions ?? [];
1579
- if (featureDefinitions.length > 128) {
1580
- throw new Error("API Integration exposes too many feature definitions");
1489
+ const facetDefinitions = input.facetDefinitions ?? [];
1490
+ if (facetDefinitions.length > 128) {
1491
+ throw new Error("API Integration exposes too many facet definitions");
1581
1492
  }
1582
- if (
1583
- new Set(featureDefinitions.map((feature) => feature.featureKey)).size !==
1584
- featureDefinitions.length
1585
- ) {
1586
- throw new Error("API Integration has duplicate feature keys");
1493
+ if (new Set(facetDefinitions.map((facet) => facet.facetKey)).size !== facetDefinitions.length) {
1494
+ throw new Error("API Integration has duplicate facet keys");
1587
1495
  }
1588
1496
  const base = new URL(input.baseUrl);
1589
1497
  if (base.protocol !== "https:" || base.username || base.password || base.hash) {
@@ -1620,7 +1528,7 @@ function storedRevision(value: Record<string, unknown>): StoredApiIntegrationRev
1620
1528
  if (
1621
1529
  (protocol !== "openapi" && protocol !== "graphql") ||
1622
1530
  typeof value.id !== "string" ||
1623
- typeof value.integrationId !== "string" ||
1531
+ typeof value.definitionId !== "string" ||
1624
1532
  typeof value.contentSha256 !== "string" ||
1625
1533
  typeof value.title !== "string" ||
1626
1534
  !Array.isArray(tools) ||