@opengeni/db 5.0.1 → 6.0.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 (212) hide show
  1. package/dist/automations.d.ts +0 -2
  2. package/dist/canonical-human-identities.d.ts +4 -0
  3. package/dist/canonical-human-identities.js +3 -3
  4. package/dist/capability-components.d.ts +5 -13
  5. package/dist/capability-integrations.d.ts +23 -8
  6. package/dist/capability-reconciliation.d.ts +5 -0
  7. package/dist/capability-reconciliation.js +21 -0
  8. package/dist/capability-reconciliation.js.map +1 -0
  9. package/dist/{chunk-6T2GGYWE.js → chunk-4UJCXBR2.js} +4 -5800
  10. package/dist/chunk-4UJCXBR2.js.map +1 -0
  11. package/dist/{chunk-MWMXWHJD.js → chunk-7JCDSMX2.js} +2 -2
  12. package/dist/chunk-AJA2ZIUW.js +219 -0
  13. package/dist/chunk-AJA2ZIUW.js.map +1 -0
  14. package/dist/chunk-CDAT6EKW.js +247 -0
  15. package/dist/chunk-CDAT6EKW.js.map +1 -0
  16. package/dist/{chunk-DPONPYJD.js → chunk-CJI6G254.js} +70 -18
  17. package/dist/chunk-CJI6G254.js.map +1 -0
  18. package/dist/chunk-G32NVMRJ.js +276 -0
  19. package/dist/chunk-G32NVMRJ.js.map +1 -0
  20. package/dist/chunk-GABXCG3N.js +5811 -0
  21. package/dist/chunk-GABXCG3N.js.map +1 -0
  22. package/dist/{chunk-ERKVSPDX.js → chunk-LVY33EWL.js} +3 -3
  23. package/dist/{chunk-45CP2YKY.js → chunk-MAMBI2HR.js} +9 -3
  24. package/dist/{chunk-45CP2YKY.js.map → chunk-MAMBI2HR.js.map} +1 -1
  25. package/dist/{chunk-F73UKJY6.js → chunk-MN5PZMEK.js} +91 -108
  26. package/dist/chunk-MN5PZMEK.js.map +1 -0
  27. package/dist/chunk-PJI4MUZ7.js +131 -0
  28. package/dist/chunk-PJI4MUZ7.js.map +1 -0
  29. package/dist/{chunk-T6BWIGWJ.js → chunk-RIYHP2WU.js} +2 -2
  30. package/dist/{chunk-7HMK3B45.js → chunk-RL2MUXM3.js} +16 -7
  31. package/dist/chunk-RL2MUXM3.js.map +1 -0
  32. package/dist/{chunk-HQDVI2DB.js → chunk-SYKHLPTK.js} +4 -3
  33. package/dist/{chunk-HQDVI2DB.js.map → chunk-SYKHLPTK.js.map} +1 -1
  34. package/dist/{chunk-T6YLHJLS.js → chunk-XIXVVBW2.js} +198 -51
  35. package/dist/chunk-XIXVVBW2.js.map +1 -0
  36. package/dist/chunk-ZPJ6V2VG.js +156 -0
  37. package/dist/chunk-ZPJ6V2VG.js.map +1 -0
  38. package/dist/codex-capacity-recovery.d.ts +12 -0
  39. package/dist/codex-failure-eligibility.d.ts +9 -0
  40. package/dist/company-profile-schema.d.ts +4 -2
  41. package/dist/connect-attempts.d.ts +15 -0
  42. package/dist/connect-attempts.js +25 -0
  43. package/dist/connect-attempts.js.map +1 -0
  44. package/dist/connection-authority.d.ts +7 -63
  45. package/dist/connection-refresh-lock.d.ts +4 -0
  46. package/dist/connection-token-resolver.d.ts +8 -43
  47. package/dist/database-timing.d.ts +10 -0
  48. package/dist/database.d.ts +4 -0
  49. package/dist/editable-artifact-durable-export.js +2 -2
  50. package/dist/editable-artifacts.d.ts +9 -0
  51. package/dist/editable-artifacts.js +7 -5
  52. package/dist/index.d.ts +447 -78
  53. package/dist/index.js +12705 -12872
  54. package/dist/index.js.map +1 -1
  55. package/dist/insights-usage-bundle.d.ts +3 -0
  56. package/dist/integration-bindings.d.ts +1 -1
  57. package/dist/integration-facets.d.ts +18 -1
  58. package/dist/knowledge-entries-schema.d.ts +2 -0
  59. package/dist/knowledge-entries.d.ts +1 -0
  60. package/dist/knowledge-indexing.d.ts +1 -0
  61. package/dist/live-session-attempt.d.ts +35 -137
  62. package/dist/managed-auth-session-sets.js +3 -3
  63. package/dist/mcp-account-bindings.d.ts +4 -0
  64. package/dist/mcp-oauth.d.ts +11 -0
  65. package/dist/mcp-operations.js +2 -2
  66. package/dist/migrate.js +1 -1
  67. package/dist/organization-integration-policy.d.ts +51 -0
  68. package/dist/organization-integration-policy.js +18 -0
  69. package/dist/organization-integration-policy.js.map +1 -0
  70. package/dist/organization-usage.d.ts +20 -0
  71. package/dist/plugin-packages.d.ts +9 -12
  72. package/dist/pr-review.d.ts +0 -11
  73. package/dist/preference-registry-schema.d.ts +17 -0
  74. package/dist/provision-roles.js +1 -1
  75. package/dist/retained-provider-commands.d.ts +124 -6
  76. package/dist/retained-provider-commands.js +29 -97
  77. package/dist/retained-provider-commands.js.map +1 -1
  78. package/dist/retired-session-create-metadata.d.ts +4 -0
  79. package/dist/runtime-posture.d.ts +7 -5
  80. package/dist/schema.d.ts +876 -656
  81. package/dist/schema.js +5 -7
  82. package/dist/session-admission-block.d.ts +32 -0
  83. package/dist/session-attempt-writers.d.ts +4 -0
  84. package/dist/session-background-commands.js +5 -4
  85. package/dist/session-command-output.js +8 -126
  86. package/dist/session-command-output.js.map +1 -1
  87. package/dist/session-control.d.ts +5 -1
  88. package/dist/session-event-slices.d.ts +10 -0
  89. package/dist/session-event-slices.js +8 -222
  90. package/dist/session-event-slices.js.map +1 -1
  91. package/dist/session-file-attachments.d.ts +28 -0
  92. package/dist/session-goal-reports.d.ts +43 -0
  93. package/dist/session-mcp-approval.d.ts +4 -0
  94. package/dist/session-mcp-credential-rotation.js +5 -4
  95. package/dist/session-mcp-credential-rotation.js.map +1 -1
  96. package/dist/session-message-search.d.ts +22 -0
  97. package/dist/session-queue-commands.d.ts +2 -6
  98. package/dist/session-retry.d.ts +36 -0
  99. package/dist/session-tenancy.js +3 -3
  100. package/dist/skill-source-release-impact.d.ts +18 -0
  101. package/dist/skill-source-release.d.ts +9 -0
  102. package/dist/skills.d.ts +7 -1
  103. package/dist/user-resource-authority.d.ts +0 -8
  104. package/dist/video-generation.js +3 -3
  105. package/dist/workspace-tool-defaults.js +5 -4
  106. package/dist/workspace-tool-defaults.js.map +1 -1
  107. package/drizzle/0468_knowledge_relationship_projection.sql +30 -0
  108. package/drizzle/0469_knowledge_source_discovery.sql +85 -0
  109. package/drizzle/0470_organization_integration_policy.sql +151 -0
  110. package/drizzle/0471_usage_events_account_recent_index.sql +4 -0
  111. package/drizzle/0472_usage_events_workspace_recent_index.sql +4 -0
  112. package/drizzle/0473_organization_usage_analytical_capability.sql +237 -0
  113. package/drizzle/0474_goal_report_requirements.sql +156 -0
  114. package/drizzle/0475_session_event_history_statistics.sql +15 -0
  115. package/drizzle/0476_session_event_history_policy_planning.sql +29 -0
  116. package/drizzle/0477_managed_sign_in_methods.sql +303 -0
  117. package/drizzle/0478_sender_owned_connections.sql +2772 -0
  118. package/drizzle/0479_connection_create_idempotency.sql +16 -0
  119. package/drizzle/0480_private_session_organization_key_administration.sql +154 -0
  120. package/drizzle/0481_personal_connection_visibility_cleanup.sql +45 -0
  121. package/drizzle/0482_remove_packs.sql +417 -0
  122. package/drizzle/0483_preclaim_admission_block.sql +85 -0
  123. package/drizzle/0484_insights_usage_projection.sql +211 -0
  124. package/drizzle/0485_inherited_mcp_approval_policies.sql +6 -0
  125. package/drizzle/0486_reasoning_configuration_message_forks.sql +35 -0
  126. package/drizzle/0487_skill_catalog_message_forks.sql +26 -0
  127. package/drizzle/0488_permanent_skill_removal.sql +207 -0
  128. package/drizzle/0489_modal_command_byte_offsets.sql +17 -0
  129. package/drizzle/0490_periodic_capture_attempt_cadence.sql +6 -0
  130. package/drizzle/0491_warm_capture_holder_reclamation.sql +57 -0
  131. package/drizzle/0492_codex_accepted_source_authority.sql +249 -0
  132. package/drizzle/0493_stopping_command_error_containment.sql +58 -0
  133. package/drizzle/0494_mcp_account_bindings.sql +334 -0
  134. package/drizzle/0495_consented_sandbox_recovery.sql +220 -0
  135. package/drizzle/0496_supervised_command_settlement.sql +386 -0
  136. package/drizzle/0497_modal_inventory_owner_read_capability.sql +112 -0
  137. package/drizzle/0498_enrollment_membership_fence.sql +87 -0
  138. package/drizzle/0499_session_attachment_access.sql +224 -0
  139. package/drizzle/0500_session_execution_epoch.sql +37 -0
  140. package/drizzle/0501_session_sharing_execution.sql +591 -0
  141. package/drizzle/0502_active_message_boundary_forks.sql +30 -0
  142. package/package.json +17 -5
  143. package/src/automations.ts +17 -73
  144. package/src/canonical-human-identities.ts +17 -5
  145. package/src/capability-components.ts +7 -24
  146. package/src/capability-integrations.ts +301 -21
  147. package/src/capability-reconciliation.ts +19 -0
  148. package/src/codex-capacity-recovery.ts +47 -0
  149. package/src/codex-failure-eligibility.ts +93 -0
  150. package/src/connect-attempts.ts +49 -18
  151. package/src/connection-authority.ts +12 -158
  152. package/src/connection-refresh-lock.ts +22 -0
  153. package/src/connection-token-resolver.ts +58 -530
  154. package/src/database-timing.ts +43 -0
  155. package/src/database.ts +61 -26
  156. package/src/editable-artifacts.ts +1 -1
  157. package/src/index.ts +3578 -1273
  158. package/src/insights-model-bundle.ts +19 -7
  159. package/src/insights-usage-bundle.ts +16 -19
  160. package/src/integration-bindings.ts +2 -7
  161. package/src/integration-facets.ts +73 -6
  162. package/src/knowledge-entries.ts +8 -1
  163. package/src/live-session-attempt.ts +0 -22
  164. package/src/mcp-account-bindings.ts +12 -0
  165. package/src/mcp-oauth.ts +26 -0
  166. package/src/organization-integration-policy.ts +235 -0
  167. package/src/organization-usage.ts +83 -0
  168. package/src/plugin-packages.ts +226 -42
  169. package/src/pr-review.ts +7 -69
  170. package/src/preference-registry-schema.ts +1 -0
  171. package/src/provision-roles.ts +50 -37
  172. package/src/retained-provider-commands.ts +286 -9
  173. package/src/retired-session-create-metadata.ts +16 -0
  174. package/src/runtime-posture.ts +217 -13
  175. package/src/schema.ts +104 -120
  176. package/src/session-admission-block.ts +29 -0
  177. package/src/session-attempt-writers.ts +48 -0
  178. package/src/session-control.ts +21 -5
  179. package/src/session-event-slices.ts +76 -26
  180. package/src/session-file-attachments.ts +66 -0
  181. package/src/session-goal-reports.ts +255 -0
  182. package/src/session-mcp-approval.ts +30 -0
  183. package/src/session-message-search.ts +348 -0
  184. package/src/session-queue-commands.ts +60 -36
  185. package/src/session-retry.ts +319 -0
  186. package/src/skill-config-migration.ts +11 -2
  187. package/src/skill-source-release-impact.ts +33 -0
  188. package/src/skill-source-release.ts +67 -26
  189. package/src/skills.ts +44 -6
  190. package/src/user-resource-authority.ts +0 -56
  191. package/dist/chunk-6T2GGYWE.js.map +0 -1
  192. package/dist/chunk-7HMK3B45.js.map +0 -1
  193. package/dist/chunk-DPONPYJD.js.map +0 -1
  194. package/dist/chunk-F73UKJY6.js.map +0 -1
  195. package/dist/chunk-T6YLHJLS.js.map +0 -1
  196. package/dist/host-mcp-binding-match.d.ts +0 -5
  197. package/dist/host-mcp-bindings.d.ts +0 -79
  198. package/dist/host-mcp-resolvers.d.ts +0 -47
  199. package/dist/host-mcp-task-authority.d.ts +0 -43
  200. package/dist/host-selection-identity.d.ts +0 -6
  201. package/dist/pack-components.d.ts +0 -83
  202. package/dist/pack-installations.d.ts +0 -86
  203. package/src/host-mcp-binding-match.ts +0 -34
  204. package/src/host-mcp-bindings.ts +0 -777
  205. package/src/host-mcp-resolvers.ts +0 -266
  206. package/src/host-mcp-task-authority.ts +0 -384
  207. package/src/host-selection-identity.ts +0 -29
  208. package/src/pack-components.ts +0 -980
  209. package/src/pack-installations.ts +0 -950
  210. /package/dist/{chunk-MWMXWHJD.js.map → chunk-7JCDSMX2.js.map} +0 -0
  211. /package/dist/{chunk-ERKVSPDX.js.map → chunk-LVY33EWL.js.map} +0 -0
  212. /package/dist/{chunk-T6BWIGWJ.js.map → chunk-RIYHP2WU.js.map} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/db",
3
- "version": "5.0.1",
3
+ "version": "6.0.0",
4
4
  "description": "OpenGeni persistence: Drizzle schema, RLS-scoped query layer, the SQL migration runner, and role provisioning.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -19,6 +19,18 @@
19
19
  "module": "./dist/index.js",
20
20
  "types": "./dist/index.d.ts",
21
21
  "exports": {
22
+ "./connect-attempts": {
23
+ "types": "./dist/connect-attempts.d.ts",
24
+ "import": "./dist/connect-attempts.js"
25
+ },
26
+ "./capability-reconciliation": {
27
+ "types": "./dist/capability-reconciliation.d.ts",
28
+ "import": "./dist/capability-reconciliation.js"
29
+ },
30
+ "./organization-integration-policy": {
31
+ "types": "./dist/organization-integration-policy.d.ts",
32
+ "import": "./dist/organization-integration-policy.js"
33
+ },
22
34
  "./session-mcp-credential-rotation": {
23
35
  "types": "./dist/session-mcp-credential-rotation.d.ts",
24
36
  "import": "./dist/session-mcp-credential-rotation.js"
@@ -102,10 +114,10 @@
102
114
  "prepublishOnly": "bash ../../scripts/prepublish-guard"
103
115
  },
104
116
  "dependencies": {
105
- "@opengeni/codemode": "^0.5.9",
106
- "@opengeni/codex": "^0.2.23",
107
- "@opengeni/config": "^1.2.2",
108
- "@opengeni/contracts": "^4.1.0",
117
+ "@opengeni/codemode": "^0.6.0",
118
+ "@opengeni/codex": "^0.2.24",
119
+ "@opengeni/config": "^2.0.0",
120
+ "@opengeni/contracts": "^5.0.0",
109
121
  "@opengeni/network": "^0.3.1",
110
122
  "drizzle-orm": "^0.45.2",
111
123
  "postgres": "^3.4.7"
@@ -3,8 +3,6 @@ import {
3
3
  StoredAutomationAcceptedExecution,
4
4
  AutomationNormalizedEvent,
5
5
  StoredAutomationSessionTemplate,
6
- StoredCapabilityPack,
7
- stableJson,
8
6
  type AutomationRun,
9
7
  type AutomationSource,
10
8
  type AutomationTrigger,
@@ -13,7 +11,7 @@ import {
13
11
  type UpdateAutomationSourceRequest,
14
12
  type UpdateAutomationTriggerRequest,
15
13
  } from "@opengeni/contracts";
16
- import { and, desc, eq, inArray, isNull, sql } from "drizzle-orm";
14
+ import { and, desc, eq, inArray, ne, sql } from "drizzle-orm";
17
15
  import type { Database } from "./database";
18
16
  import { withWorkspaceRls } from "./database";
19
17
  import * as schema from "./schema";
@@ -85,10 +83,11 @@ export async function createAutomationSource(
85
83
  createdBySubjectId: string;
86
84
  request: CreateAutomationSourceRequest;
87
85
  webhookSecretEncrypted: string;
88
- packInstallationId?: string | null;
89
- packConnectorId?: string | null;
90
86
  },
91
87
  ): Promise<AutomationSource> {
88
+ if (input.request.adapterId === "source-control.pull-request.v1") {
89
+ throw new Error("PR Review automations require the PR Review setup API");
90
+ }
92
91
  return await withWorkspaceRls(
93
92
  db,
94
93
  input.workspaceId,
@@ -103,8 +102,7 @@ export async function createAutomationSource(
103
102
  adapterId: input.request.adapterId,
104
103
  configuration: input.request.configuration,
105
104
  webhookSecretEncrypted: input.webhookSecretEncrypted,
106
- packInstallationId: input.packInstallationId ?? null,
107
- packConnectorId: input.packConnectorId ?? null,
105
+
108
106
  createdBySubjectId: input.createdBySubjectId,
109
107
  })
110
108
  .returning();
@@ -208,7 +206,7 @@ export async function updateAutomationSource(
208
206
  and(
209
207
  eq(schema.automationSources.workspaceId, input.workspaceId),
210
208
  eq(schema.automationSources.id, input.sourceId),
211
- isNull(schema.automationSources.packInstallationId),
209
+ ne(schema.automationSources.adapterId, "source-control.pull-request.v1"),
212
210
  ),
213
211
  )
214
212
  .returning();
@@ -238,7 +236,6 @@ export async function createAutomationTrigger(
238
236
  id: schema.automationSources.id,
239
237
  adapterId: schema.automationSources.adapterId,
240
238
  status: schema.automationSources.status,
241
- packInstallationId: schema.automationSources.packInstallationId,
242
239
  })
243
240
  .from(schema.automationSources)
244
241
  .where(
@@ -254,44 +251,10 @@ export async function createAutomationTrigger(
254
251
  if (source.adapterId !== input.adapterId) {
255
252
  throw new Error("Automation source and trigger adapter do not match");
256
253
  }
257
- if (source.packInstallationId !== input.request.packInstallationId) {
258
- throw new Error("Automation source and trigger Pack ownership do not match");
259
- }
260
- if (input.request.packInstallationId) {
261
- const [installation] = await tx
262
- .select({
263
- status: schema.packInstallations.status,
264
- manifestSnapshot: schema.packInstallations.manifestSnapshot,
265
- })
266
- .from(schema.packInstallations)
267
- .where(
268
- and(
269
- eq(schema.packInstallations.workspaceId, input.workspaceId),
270
- eq(schema.packInstallations.id, input.request.packInstallationId),
271
- ),
272
- )
273
- .limit(1);
274
- const manifest = installation?.manifestSnapshot
275
- ? StoredCapabilityPack.safeParse(installation.manifestSnapshot)
276
- : null;
277
- if (!installation || installation.status !== "active" || !manifest?.success) {
278
- throw new Error("Automation Pack installation is not active");
279
- }
280
- const template = manifest.data.automationTemplates?.find(
281
- (candidate) => candidate.id === input.request.packTemplateId,
282
- );
283
- if (!template || template.adapterId !== input.adapterId) {
284
- throw new Error("Automation Pack template does not match the source adapter");
285
- }
286
- if (
287
- stableJson([...new Set(input.request.eventTypes)].sort()) !==
288
- stableJson([...new Set(template.eventTypes)].sort()) ||
289
- stableJson(input.request.configuration) !== stableJson(template.configuration) ||
290
- stableJson(input.request.sessionTemplate) !== stableJson(template.sessionTemplate)
291
- ) {
292
- throw new Error("Automation Pack trigger must use its frozen manifest template");
293
- }
254
+ if (source.adapterId === "source-control.pull-request.v1") {
255
+ throw new Error("PR Review automations require the PR Review setup API");
294
256
  }
257
+
295
258
  await input.beforeCreateCommit?.(tx);
296
259
  const [head] = await tx
297
260
  .insert(schema.automationTriggers)
@@ -301,8 +264,7 @@ export async function createAutomationTrigger(
301
264
  sourceId: input.request.sourceId,
302
265
  name: input.request.name,
303
266
  status: input.request.status,
304
- packInstallationId: input.request.packInstallationId,
305
- packTemplateId: input.request.packTemplateId,
267
+
306
268
  createdBySubjectId: input.createdBySubjectId,
307
269
  })
308
270
  .returning();
@@ -476,14 +438,13 @@ export async function updateAutomationTrigger(
476
438
  .for("update")
477
439
  .limit(1);
478
440
  if (!existing) return null;
441
+ if (existing.revision.adapterId === "source-control.pull-request.v1") {
442
+ throw new Error("PR Review automations require the PR Review setup API");
443
+ }
479
444
  if (existing.head.currentRevision !== input.request.expectedRevision) {
480
445
  throw new AutomationRevisionConflictError();
481
446
  }
482
- if (existing.head.packInstallationId) {
483
- throw new Error(
484
- "Pack-owned automation triggers must be managed through their Pack setup API",
485
- );
486
- }
447
+
487
448
  await input.beforeUpdateCommit?.(tx);
488
449
  const revisionNumber = existing.head.currentRevision + 1;
489
450
  const [head] = await tx
@@ -739,7 +700,6 @@ export async function assertAutomationRunAuthorityInTransaction(
739
700
  sourceVersion: schema.automationSources.version,
740
701
  triggerStatus: schema.automationTriggers.status,
741
702
  currentRevision: schema.automationTriggers.currentRevision,
742
- packInstallationId: schema.automationTriggers.packInstallationId,
743
703
  })
744
704
  .from(schema.automationRuns)
745
705
  .innerJoin(
@@ -775,21 +735,7 @@ export async function assertAutomationRunAuthorityInTransaction(
775
735
  if (row.currentRevision !== input.triggerRevision) {
776
736
  throw new AutomationAuthorityRevokedError("Automation trigger changed before dispatch");
777
737
  }
778
- if (row.packInstallationId) {
779
- const [installation] = await db
780
- .select({ status: schema.packInstallations.status })
781
- .from(schema.packInstallations)
782
- .where(
783
- and(
784
- eq(schema.packInstallations.workspaceId, input.workspaceId),
785
- eq(schema.packInstallations.id, row.packInstallationId),
786
- ),
787
- )
788
- .limit(1);
789
- if (!installation || installation.status !== "active") {
790
- throw new AutomationAuthorityRevokedError("Automation Pack is no longer active");
791
- }
792
- }
738
+
793
739
  await db
794
740
  .update(schema.automationRuns)
795
741
  .set({
@@ -838,8 +784,7 @@ function mapSource(row: SourceRow): AutomationSource {
838
784
  configuration: row.configuration,
839
785
  status: row.status as AutomationSource["status"],
840
786
  version: row.version,
841
- packInstallationId: row.packInstallationId,
842
- packConnectorId: row.packConnectorId,
787
+
843
788
  hasWebhookSecret: Boolean(row.webhookSecretEncrypted),
844
789
  webhookPath: `/v1/webhooks/automations/${row.endpointId}`,
845
790
  createdBySubjectId: row.createdBySubjectId,
@@ -866,8 +811,7 @@ function mapTrigger(
866
811
  sessionTemplate: StoredAutomationSessionTemplate.parse(revision.sessionTemplate),
867
812
  status: head.status as AutomationTrigger["status"],
868
813
  revision: revisionNumber,
869
- packInstallationId: head.packInstallationId,
870
- packTemplateId: head.packTemplateId,
814
+
871
815
  createdBySubjectId: head.createdBySubjectId,
872
816
  createdAt: head.createdAt.toISOString(),
873
817
  updatedAt: head.updatedAt.toISOString(),
@@ -217,6 +217,9 @@ export async function synchronizeCanonicalHumanLoginBindings(
217
217
  binding.providerId === account.providerId &&
218
218
  binding.providerAccountId === account.providerAccountId,
219
219
  );
220
+ // A revoked/recovery binding is not an invitation to relink. Reconnection
221
+ // belongs to the explicit OAuth-proof transaction, never a session hook.
222
+ if (existing && existing.status !== "active") break;
220
223
  if (existing?.status === "active") {
221
224
  authority = {
222
225
  identityId: projection.activeIdentity.id,
@@ -316,6 +319,7 @@ export type ApplyCanonicalHumanIdentityOperationInput = {
316
319
  providerId?: string | null;
317
320
  providerAccountId?: string | null;
318
321
  reason: string;
322
+ verifiedRecovery?: { authSessionId: string; requestDigest: string };
319
323
  actorFence?: {
320
324
  authorityHash: string;
321
325
  actorEpoch: string;
@@ -328,16 +332,24 @@ export async function applyCanonicalHumanIdentityOperation(
328
332
  input: ApplyCanonicalHumanIdentityOperationInput,
329
333
  ): Promise<CanonicalHumanIdentityMutationResponseType> {
330
334
  try {
331
- if (input.actorFence) {
335
+ if (input.actorFence || input.verifiedRecovery) {
332
336
  return await db.transaction(async (tx) => {
333
337
  const txDb = tx as unknown as Database;
334
- await rawRows(
335
- txDb,
336
- sql`select managed_auth_actor_mutation_fence(
338
+ if (input.actorFence)
339
+ await rawRows(
340
+ txDb,
341
+ sql`select managed_auth_actor_mutation_fence(
337
342
  ${input.actorFence!.authorityHash}, ${input.actorFence!.actorEpoch}::bigint,
338
343
  ${input.actorFence!.requestId}::uuid
339
344
  )`,
340
- );
345
+ );
346
+ if (input.verifiedRecovery)
347
+ await rawRows(
348
+ txDb,
349
+ sql`select assert_managed_sign_in_recovery(
350
+ ${input.authUserId},${input.verifiedRecovery.authSessionId},${input.bindingId}::uuid,
351
+ ${JSON.stringify({ operationId: input.operationId, expectedIdentityRevision: input.expectedIdentityRevision, requestDigest: input.verifiedRecovery.requestDigest })}::jsonb)`,
352
+ );
341
353
  return await applyCanonicalHumanIdentityOperationInner(txDb, input);
342
354
  });
343
355
  }
@@ -6,7 +6,7 @@ import { releaseOrphanedSkillHeads, type SkillSourceReleaseReceipt } from "./ski
6
6
  import * as schema from "./schema";
7
7
 
8
8
  export type CapabilityComponentOwnerIdentity = {
9
- kind: "direct" | "plugin" | "pack" | "migration";
9
+ kind: "direct" | "plugin" | "migration";
10
10
  id: string;
11
11
  };
12
12
 
@@ -19,17 +19,15 @@ export class CapabilityComponentVersionConflictError extends Error {
19
19
  }
20
20
 
21
21
  /**
22
- * An owner row is runtime-effective only while its lifecycle-owning Plugin or
23
- * v2 Pack installation is active. Direct, migration, and legacy textual Pack
24
- * ownership is intrinsic so the rolling migration does not hide pre-v2 shared
25
- * components before those Packs are reinstalled into the normalized ledger.
22
+ * Plugin ownership is effective only while its installation is active.
23
+ * Direct and migration ownership is intrinsic.
26
24
  */
27
25
  export function effectiveCapabilityOwnerSql(
28
26
  ownerKind: SQLWrapper,
29
27
  ownerId: SQLWrapper,
30
28
  ): ReturnType<typeof sql> {
31
29
  return sql`(
32
- ${ownerKind} not in ('plugin', 'pack')
30
+ ${ownerKind} in ('direct', 'migration')
33
31
  or (
34
32
  ${ownerKind} = 'plugin'
35
33
  and exists (
@@ -38,21 +36,10 @@ export function effectiveCapabilityOwnerSql(
38
36
  and owning_plugin.status = 'active'
39
37
  )
40
38
  )
41
- or (
42
- ${ownerKind} = 'pack'
43
- and (
44
- ${ownerId} !~ '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
45
- or exists (
46
- select 1 from ${schema.packInstallations} owning_pack
47
- where owning_pack.id::text = ${ownerId}
48
- and owning_pack.status = 'active'
49
- )
50
- )
51
- )
52
39
  )`;
53
40
  }
54
41
 
55
- /** Serialize one workspace-local component identity across direct, Plugin, and Pack installers. */
42
+ /** Serialize one workspace-local component identity across direct and Plugin installers. */
56
43
  export async function lockCapabilityComponentIdentity(
57
44
  db: Database,
58
45
  workspaceId: string,
@@ -104,17 +91,12 @@ export async function assertCapabilityComponentVersionCanChange(
104
91
  }
105
92
  }
106
93
 
107
- /**
108
- * Delete physically ownerless facet installations and disable now-empty child
109
- * components. Inactive lifecycle owners still preserve storage: a Pack may
110
- * have claimed a component while its installation is pending or repairing,
111
- * even though that owner is intentionally hidden from runtime reads.
112
- */
113
94
  export async function cleanupOrphanedCapabilityComponents(
114
95
  db: Database,
115
96
  workspaceId: string,
116
97
  facetInstallationIds: string[],
117
98
  skillActor?: SkillActor,
99
+ lockedSkillHeadIds?: readonly string[],
118
100
  ): Promise<SkillSourceReleaseReceipt[]> {
119
101
  const uniqueIds = [...new Set(facetInstallationIds)];
120
102
  if (uniqueIds.length === 0) return [];
@@ -147,6 +129,7 @@ export async function cleanupOrphanedCapabilityComponents(
147
129
  workspaceId,
148
130
  facetInstallationIds: orphanRows.map((row) => row.facetInstallationId),
149
131
  ...(skillActor ? { skillActor } : {}),
132
+ ...(lockedSkillHeadIds !== undefined ? { lockedHeadIds: lockedSkillHeadIds } : {}),
150
133
  });
151
134
  await db.delete(schema.capabilityFacetInstallations).where(
152
135
  inArray(