@capybara-hq/kernel 0.1.0-rc.24 → 0.1.0-rc.25

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 (140) hide show
  1. package/dist/admin/admin.module.js +2 -0
  2. package/dist/admin/health.service.d.ts +2 -2
  3. package/dist/admin/health.service.js +6 -2
  4. package/dist/agents/agents.module.js +3 -0
  5. package/dist/agents/agents.service.d.ts +6 -1
  6. package/dist/agents/agents.service.js +11 -2
  7. package/dist/catalog/catalog-import.module.js +0 -4
  8. package/dist/catalog/catalog-scope.service.d.ts +63 -26
  9. package/dist/catalog/catalog-scope.service.js +146 -71
  10. package/dist/catalog/catalog.module.js +4 -3
  11. package/dist/catalog/catalog.service.d.ts +11 -4
  12. package/dist/catalog/catalog.service.js +21 -5
  13. package/dist/catalog/cli.d.ts +4 -3
  14. package/dist/catalog/cli.js +8 -13
  15. package/dist/catalog/job-ids.d.ts +8 -20
  16. package/dist/catalog/job-ids.js +11 -16
  17. package/dist/catalog/marketplaces.service.d.ts +1 -1
  18. package/dist/catalog/org-plugin-uploads.d.ts +11 -4
  19. package/dist/catalog/org-plugin-uploads.js +21 -6
  20. package/dist/catalog/owned-items.d.ts +6 -13
  21. package/dist/catalog/owned-items.js +11 -29
  22. package/dist/catalog/owned-plugin-cleanup.d.ts +8 -17
  23. package/dist/catalog/owned-plugin-cleanup.js +12 -66
  24. package/dist/catalog/platform-components.d.ts +56 -34
  25. package/dist/catalog/platform-components.js +68 -78
  26. package/dist/catalog/plugin-import.d.ts +28 -25
  27. package/dist/catalog/plugin-import.js +90 -76
  28. package/dist/catalog/plugin-upgrade.d.ts +4 -4
  29. package/dist/catalog/plugin-upgrade.js +7 -19
  30. package/dist/catalog/scope-jobs.d.ts +59 -0
  31. package/dist/catalog/scope-jobs.js +65 -0
  32. package/dist/catalog/scope-sync-workers.d.ts +22 -0
  33. package/dist/catalog/scope-sync-workers.js +58 -2
  34. package/dist/catalog/scope-sync.d.ts +40 -65
  35. package/dist/catalog/scope-sync.js +114 -122
  36. package/dist/channels/inbound.js +2 -2
  37. package/dist/channels/threads.d.ts +4 -3
  38. package/dist/channels/threads.js +4 -3
  39. package/dist/conversations/conversations.controller.js +4 -2
  40. package/dist/conversations/conversations.service.d.ts +17 -5
  41. package/dist/conversations/conversations.service.js +17 -5
  42. package/dist/conversations/events.d.ts +21 -0
  43. package/dist/conversations/events.js +24 -1
  44. package/dist/conversations/source.d.ts +10 -0
  45. package/dist/conversations/source.js +17 -0
  46. package/dist/conversations/tree.d.ts +10 -0
  47. package/dist/conversations/tree.js +35 -0
  48. package/dist/db/kernel-schema.d.ts +9 -14
  49. package/dist/devices/devices.service.d.ts +11 -8
  50. package/dist/devices/devices.service.js +16 -23
  51. package/dist/evals/run-replay.d.ts +13 -2
  52. package/dist/evals/run-replay.js +28 -1
  53. package/dist/evals/snapshot.d.ts +7 -1
  54. package/dist/evals/snapshot.js +2 -1
  55. package/dist/extensions/hooks.d.ts +22 -3
  56. package/dist/extensions/hooks.js +15 -1
  57. package/dist/extensions/lifecycle-hooks.d.ts +99 -0
  58. package/dist/extensions/lifecycle-hooks.js +273 -0
  59. package/dist/extensions/org-config.d.ts +13 -1
  60. package/dist/extensions/org-config.js +19 -2
  61. package/dist/extensions/permission-view.d.ts +9 -5
  62. package/dist/extensions/permission-view.js +9 -4
  63. package/dist/extensions/point-defaults.d.ts +28 -1
  64. package/dist/extensions/point-defaults.js +44 -13
  65. package/dist/inbox/inbox.service.d.ts +6 -20
  66. package/dist/inbox/inbox.service.js +0 -3
  67. package/dist/inbox/org-notices.d.ts +1 -1
  68. package/dist/inbox/platform-inbox.service.d.ts +3 -32
  69. package/dist/inbox/platform-inbox.service.js +5 -54
  70. package/dist/infra/outbox/registry.d.ts +124 -0
  71. package/dist/infra/outbox/registry.js +126 -0
  72. package/dist/infra/queue/queue-names.d.ts +1 -1
  73. package/dist/infra/queue/queue-names.js +1 -0
  74. package/dist/orgs/directory-sync.js +1 -1
  75. package/dist/orgs/members.service.js +1 -1
  76. package/dist/orgs/offboarding.d.ts +50 -57
  77. package/dist/orgs/offboarding.js +117 -162
  78. package/dist/orgs/orgs.module.js +3 -0
  79. package/dist/orgs/orgs.service.d.ts +11 -5
  80. package/dist/orgs/orgs.service.js +15 -6
  81. package/dist/overrides.d.ts +3 -0
  82. package/dist/overrides.js +2 -0
  83. package/dist/platform/ops/inbox.ops.js +4 -20
  84. package/dist/platform/ops/platform.ops.d.ts +1 -0
  85. package/dist/platform/ops/platform.ops.js +6 -3
  86. package/dist/roles/worker-role.d.ts +10 -5
  87. package/dist/roles/worker-role.js +19 -9
  88. package/dist/roles/worker.module.js +2 -4
  89. package/dist/runtime/context/build.d.ts +3 -0
  90. package/dist/runtime/context/build.js +15 -0
  91. package/dist/runtime/context/plugin-context.d.ts +20 -0
  92. package/dist/runtime/context/plugin-context.js +30 -0
  93. package/dist/runtime/langgraph-loop.js +4 -0
  94. package/dist/runtime/loop.d.ts +8 -0
  95. package/dist/runtime/maintenance.d.ts +5 -3
  96. package/dist/runtime/maintenance.js +36 -11
  97. package/dist/runtime/model-call.d.ts +6 -1
  98. package/dist/runtime/model-call.js +1 -0
  99. package/dist/runtime/plugin-context.service.d.ts +69 -0
  100. package/dist/runtime/plugin-context.service.js +208 -0
  101. package/dist/runtime/run-control.d.ts +6 -1
  102. package/dist/runtime/run-control.js +13 -0
  103. package/dist/runtime/run-queue.d.ts +13 -0
  104. package/dist/runtime/run-queue.js +63 -0
  105. package/dist/runtime/run-worker.d.ts +22 -1
  106. package/dist/runtime/run-worker.js +107 -10
  107. package/dist/runtime/runtime.module.js +2 -0
  108. package/dist/runtime/subagents/dispatch.js +1 -0
  109. package/dist/runtime/subagents/skill-fork.js +3 -0
  110. package/dist/sandbox/jobs.d.ts +20 -10
  111. package/dist/sandbox/jobs.js +23 -17
  112. package/dist/schedules/fire.d.ts +25 -4
  113. package/dist/schedules/fire.js +87 -13
  114. package/dist/schedules/job-ids.d.ts +66 -17
  115. package/dist/schedules/job-ids.js +81 -13
  116. package/dist/schedules/run-tracker.js +2 -1
  117. package/dist/schedules/scan.job.d.ts +13 -32
  118. package/dist/schedules/scan.job.js +35 -144
  119. package/dist/schedules/scheduled-tasks.service.d.ts +6 -6
  120. package/dist/schedules/scheduled-tasks.service.js +17 -14
  121. package/dist/schedules/schedules.module.js +0 -4
  122. package/dist/skills/changes.controller.d.ts +1 -1
  123. package/dist/skills/changes.controller.js +1 -1
  124. package/dist/tools/approvals.service.d.ts +15 -4
  125. package/dist/tools/approvals.service.js +26 -10
  126. package/dist/tools/pipeline.d.ts +11 -2
  127. package/dist/tools/pipeline.js +5 -0
  128. package/dist/tools/questions.service.d.ts +15 -4
  129. package/dist/tools/questions.service.js +21 -19
  130. package/dist/tools/registry.d.ts +8 -1
  131. package/dist/tools/registry.js +9 -0
  132. package/package.json +3 -3
  133. package/src/migrations/0121_drop_platform_migration_runs.sql +12 -0
  134. package/src/migrations/0122_drop_scheduled_task_runs_rechecked_at.sql +5 -0
  135. package/src/migrations/0123_pgvector.sql +27 -0
  136. package/src/migrations/0124_conversation_source.sql +36 -0
  137. package/dist/catalog/platform-migration.d.ts +0 -115
  138. package/dist/catalog/platform-migration.js +0 -583
  139. package/dist/infra/queue/add-job-once.d.ts +0 -14
  140. package/dist/infra/queue/add-job-once.js +0 -16
@@ -10,6 +10,7 @@ import { ChannelsModule } from "../channels/channels.module.js";
10
10
  import { TitlesModule } from "../conversations/titles.js";
11
11
  import { EvalsModule } from "../evals/evals.module.js";
12
12
  import { ExtensionsModule } from "../extensions/extensions.module.js";
13
+ import { LifecycleHooksModule } from "../extensions/lifecycle-hooks.js";
13
14
  import { IdentityModule } from "../identity/identity.module.js";
14
15
  import { InboxModule } from "../inbox/inbox.module.js";
15
16
  import { ModelsModule } from "../models/models.module.js";
@@ -48,6 +49,7 @@ AdminModule = __decorate([
48
49
  TitlesModule,
49
50
  UsageReportModule,
50
51
  EvalsModule,
52
+ LifecycleHooksModule,
51
53
  // the price table of the usage aggregate
52
54
  ModelsModule,
53
55
  ],
@@ -4,7 +4,7 @@ import { KernelDb } from "../infra/database/kernel-db.js";
4
4
  import { type LiveReplica, ReplicaPresence } from "../infra/presence/replica-presence.js";
5
5
  import type { KernelLogger } from "../log.js";
6
6
  /** The kernel's own queues, in the order the overview lists them (extension queues are not read). */
7
- export declare const KERNEL_QUEUE_NAMES: readonly ["cap-kernel-runs", "cap-kernel-subagent-runs", "cap-kernel-channels", "cap-kernel-maintenance", "cap-kernel-plugin-scope", "cap-kernel-titles", "cap-kernel-usage-report", "cap-kernel-evals"];
7
+ export declare const KERNEL_QUEUE_NAMES: readonly ["cap-kernel-runs", "cap-kernel-subagent-runs", "cap-kernel-channels", "cap-kernel-maintenance", "cap-kernel-plugin-scope", "cap-kernel-titles", "cap-kernel-usage-report", "cap-kernel-evals", "cap-kernel-lifecycle"];
8
8
  /** How long each source's reads may take before the answer marks it unavailable. */
9
9
  export declare const HEALTH_READ_TIMEOUT_MS = 3000;
10
10
  /** A live replica as the overview shows it. */
@@ -97,7 +97,7 @@ export declare class AdminHealthService {
97
97
  private readonly redis;
98
98
  private readonly log;
99
99
  private readonly queues;
100
- constructor(presence: Pick<ReplicaPresence, "live">, db: KernelDb, redis: Pick<Redis, "zcount" | "status">, log: Pick<KernelLogger, "warn">, runs: Queue, subagentRuns: Queue, channels: Queue, maintenance: Queue, pluginScope: Queue, titles: Queue, usageReport: Queue, evals: Queue);
100
+ constructor(presence: Pick<ReplicaPresence, "live">, db: KernelDb, redis: Pick<Redis, "zcount" | "status">, log: Pick<KernelLogger, "warn">, runs: Queue, subagentRuns: Queue, channels: Queue, maintenance: Queue, pluginScope: Queue, titles: Queue, usageReport: Queue, evals: Queue, lifecycle: Queue);
101
101
  read(): Promise<AdminHealth>;
102
102
  private readRedis;
103
103
  private readDb;
@@ -14,6 +14,7 @@ import { PLUGIN_SCOPE_QUEUE } from "../catalog/scope-sync.js";
14
14
  import { CHANNEL_QUEUE_NAME } from "../channels/jobs.js";
15
15
  import { TITLE_QUEUE } from "../conversations/titles.js";
16
16
  import { EVAL_QUEUE_NAME } from "../evals/jobs.js";
17
+ import { LIFECYCLE_QUEUE } from "../extensions/lifecycle-hooks.js";
17
18
  import { KernelDb } from "../infra/database/kernel-db.js";
18
19
  import { ReplicaPresence } from "../infra/presence/replica-presence.js";
19
20
  import { KERNEL_LOGGER, REDIS } from "../infra/tokens.js";
@@ -31,6 +32,7 @@ export const KERNEL_QUEUE_NAMES = [
31
32
  TITLE_QUEUE,
32
33
  USAGE_REPORT_QUEUE,
33
34
  EVAL_QUEUE_NAME,
35
+ LIFECYCLE_QUEUE,
34
36
  ];
35
37
  /** How long each source's reads may take before the answer marks it unavailable. */
36
38
  export const HEALTH_READ_TIMEOUT_MS = 3_000;
@@ -58,7 +60,7 @@ let AdminHealthService = class AdminHealthService {
58
60
  redis;
59
61
  log;
60
62
  queues;
61
- constructor(presence, db, redis, log, runs, subagentRuns, channels, maintenance, pluginScope, titles, usageReport, evals) {
63
+ constructor(presence, db, redis, log, runs, subagentRuns, channels, maintenance, pluginScope, titles, usageReport, evals, lifecycle) {
62
64
  this.presence = presence;
63
65
  this.db = db;
64
66
  this.redis = redis;
@@ -73,6 +75,7 @@ let AdminHealthService = class AdminHealthService {
73
75
  titles,
74
76
  usageReport,
75
77
  evals,
78
+ lifecycle,
76
79
  ];
77
80
  }
78
81
  async read() {
@@ -241,6 +244,7 @@ AdminHealthService = __decorate([
241
244
  __param(8, Inject(getQueueToken(PLUGIN_SCOPE_QUEUE))),
242
245
  __param(9, Inject(getQueueToken(TITLE_QUEUE))),
243
246
  __param(10, Inject(getQueueToken(USAGE_REPORT_QUEUE))),
244
- __param(11, Inject(getQueueToken(EVAL_QUEUE_NAME)))
247
+ __param(11, Inject(getQueueToken(EVAL_QUEUE_NAME))),
248
+ __param(12, Inject(getQueueToken(LIFECYCLE_QUEUE)))
245
249
  ], AdminHealthService);
246
250
  export { AdminHealthService };
@@ -8,6 +8,7 @@ import { Module } from "@nestjs/common";
8
8
  import { AttachmentsModule } from "../conversations/attachments.module.js";
9
9
  import { EvalBudgetModule } from "../evals/budget.js";
10
10
  import { ExtensionsModule } from "../extensions/extensions.module.js";
11
+ import { LifecycleHooksModule } from "../extensions/lifecycle-hooks.js";
11
12
  import { ModelsModule } from "../models/models.module.js";
12
13
  import { OrgLockModule } from "../orgs/org-lock.js";
13
14
  import { ProvidersModule } from "../runtime/providers.js";
@@ -48,6 +49,8 @@ AgentsModule = __decorate([
48
49
  // creating from a template: the extension tools and the tier purposes (rulings P4-4, P4-5)
49
50
  ExtensionsModule,
50
51
  ModelsModule,
52
+ // the agent delete records `agent.deleted` deliveries
53
+ LifecycleHooksModule,
51
54
  ],
52
55
  providers: [
53
56
  AgentsService,
@@ -1,5 +1,6 @@
1
1
  import type { KernelSchemaDb } from "../db/kernel-schema.js";
2
2
  import { EvalBudget } from "../evals/budget.js";
3
+ import { LifecycleHooks } from "../extensions/lifecycle-hooks.js";
3
4
  import type { WriteActor } from "../identity/write-actor.js";
4
5
  import { KernelDb } from "../infra/database/kernel-db.js";
5
6
  import { TransactionHost } from "../infra/database/transaction-host.js";
@@ -92,6 +93,8 @@ export declare class AgentsService {
92
93
  private readonly evalBudget;
93
94
  /** Settles the agent's connector setup request when its pending connectors change (P4-7). */
94
95
  private readonly setupRequests;
96
+ /** Records `agent.deleted` for the subscribing plugins in the delete's transaction. */
97
+ private readonly lifecycle;
95
98
  constructor(db: KernelDb, lookup: AgentLookup, tools: Pick<ToolRegistry, "checkDisabled">,
96
99
  /**
97
100
  * Cancels the agent's pending skill requests: all of them when it is deleted, share requests
@@ -105,7 +108,9 @@ export declare class AgentsService {
105
108
  /** Cancels the deleted agent's running eval runs (in the delete's transaction). */
106
109
  evalBudget: Pick<EvalBudget, "cancelRuns">,
107
110
  /** Settles the agent's connector setup request when its pending connectors change (P4-7). */
108
- setupRequests: Pick<PendingConnectorRequests, "settleIn" | "retargetIn">);
111
+ setupRequests: Pick<PendingConnectorRequests, "settleIn" | "retargetIn">,
112
+ /** Records `agent.deleted` for the subscribing plugins in the delete's transaction. */
113
+ lifecycle: Pick<LifecycleHooks, "recordIn">);
109
114
  /**
110
115
  * Checks the turned-off tools and the policies (tools default-on spec §2): `disabledTools` must
111
116
  * name existing builtins, extensions and connectors (`ToolRegistry.checkDisabled`); `toolPolicies`
@@ -13,7 +13,9 @@ import { Inject, Injectable } from "@nestjs/common";
13
13
  import { sql } from "kysely";
14
14
  import { ApiError } from "../errors.js";
15
15
  import { EvalBudget } from "../evals/budget.js";
16
+ import { LifecycleHooks } from "../extensions/lifecycle-hooks.js";
16
17
  import { audit } from "../identity/audit.js";
18
+ import { afterCommit } from "../infra/database/after-commit.js";
17
19
  import { KernelDb } from "../infra/database/kernel-db.js";
18
20
  import { TransactionHost } from "../infra/database/transaction-host.js";
19
21
  import { Transactional } from "../infra/database/transactional.decorator.js";
@@ -279,6 +281,7 @@ let AgentsService = class AgentsService {
279
281
  txHost;
280
282
  evalBudget;
281
283
  setupRequests;
284
+ lifecycle;
282
285
  constructor(db, lookup, tools,
283
286
  /**
284
287
  * Cancels the agent's pending skill requests: all of them when it is deleted, share requests
@@ -292,7 +295,9 @@ let AgentsService = class AgentsService {
292
295
  /** Cancels the deleted agent's running eval runs (in the delete's transaction). */
293
296
  evalBudget,
294
297
  /** Settles the agent's connector setup request when its pending connectors change (P4-7). */
295
- setupRequests) {
298
+ setupRequests,
299
+ /** Records `agent.deleted` for the subscribing plugins in the delete's transaction. */
300
+ lifecycle) {
296
301
  this.db = db;
297
302
  this.lookup = lookup;
298
303
  this.tools = tools;
@@ -302,6 +307,7 @@ let AgentsService = class AgentsService {
302
307
  this.txHost = txHost;
303
308
  this.evalBudget = evalBudget;
304
309
  this.setupRequests = setupRequests;
310
+ this.lifecycle = lifecycle;
305
311
  }
306
312
  /**
307
313
  * Checks the turned-off tools and the policies (tools default-on spec §2): `disabledTools` must
@@ -746,6 +752,8 @@ let AgentsService = class AgentsService {
746
752
  });
747
753
  // 评测集的 agent 删除后其评测运行不再花钱:显式取消(审计带原因)
748
754
  await this.evalBudget.cancelRuns({ orgId, agentId }, { accountId: actorAccountId, ...(actorTokenId !== undefined && { tokenId: actorTokenId }) }, "agent_deleted");
755
+ // plugins learn of the delete durably: owed here, delivered by the outbox after the commit
756
+ await this.lifecycle.recordIn("agent.deleted", { orgId, agentId });
749
757
  // joins this transaction (mandatory: it relies on the agent row lock taken above)
750
758
  return this.skillChanges.cancelPendingForAgent(orgId, agentId, actorAccountId, "agent_deleted", actorTokenId);
751
759
  }
@@ -907,6 +915,7 @@ AgentsService = __decorate([
907
915
  __param(5, Inject(ProviderRegistry)),
908
916
  __param(6, Inject(TransactionHost)),
909
917
  __param(7, Inject(EvalBudget)),
910
- __param(8, Inject(PendingConnectorRequests))
918
+ __param(8, Inject(PendingConnectorRequests)),
919
+ __param(9, Inject(LifecycleHooks))
911
920
  ], AgentsService);
912
921
  export { AgentsService };
@@ -8,9 +8,7 @@ import { Module } from "@nestjs/common";
8
8
  import { ClientModule } from "../client/client.module.js";
9
9
  import { ExtensionsModule } from "../extensions/extensions.module.js";
10
10
  import { SuperAdminLockModule } from "../identity/super-admin.js";
11
- import { QueueModule } from "../infra/queue/queue.module.js";
12
11
  import { OrgLockModule } from "../orgs/org-lock.js";
13
- import { MAINTENANCE_QUEUE_NAME } from "../runtime/maintenance-queue.js";
14
12
  import { StorageModule } from "../storage/storage.module.js";
15
13
  import { CatalogService } from "./catalog.service.js";
16
14
  import { ComponentPromotion } from "./component-promotion.js";
@@ -37,8 +35,6 @@ CatalogImportModule = __decorate([
37
35
  StorageModule,
38
36
  // the client build prefix goes with an expired org upload's package (`PluginImport`)
39
37
  ClientModule,
40
- // a failed post-import platform sync enqueues the migration job (`PluginImport.syncPlatform`)
41
- QueueModule.registerQueue(MAINTENANCE_QUEUE_NAME),
42
38
  ],
43
39
  providers: [
44
40
  CatalogSourceLock,
@@ -1,4 +1,3 @@
1
- import type { Queue } from "bullmq";
2
1
  import { ApiError } from "../errors.js";
3
2
  import { ExtensionAdminOps } from "../extensions/admin-ops.js";
4
3
  import { ExtensionAdmin } from "../extensions/admin-view.js";
@@ -7,11 +6,14 @@ import { PluginInstallLock } from "../extensions/locks.js";
7
6
  import { SuperAdminLock } from "../identity/super-admin.js";
8
7
  import { KernelDb } from "../infra/database/kernel-db.js";
9
8
  import { TransactionHost } from "../infra/database/transaction-host.js";
9
+ import { OutboxService } from "../infra/outbox/outbox.service.js";
10
10
  import type { KernelLogger } from "../log.js";
11
11
  import { OrgLock } from "../orgs/org-lock.js";
12
12
  import { type ThemePreview } from "../themes/theme-usage.js";
13
13
  import { type ActorOpts, type CatalogItemView, CatalogService } from "./catalog.service.js";
14
14
  import { type ComponentKind } from "./component-state.js";
15
+ import { CatalogItemLock } from "./locks.js";
16
+ import { PlatformComponents } from "./platform-components.js";
15
17
  import { type PluginConfirmResult, PluginImport } from "./plugin-import.js";
16
18
  import { PluginInstaller } from "./plugin-install.js";
17
19
  import { PlatformPluginUpdater } from "./plugin-upgrade.js";
@@ -85,10 +87,10 @@ export type ScopeTarget = {
85
87
  export declare function conflictsError(conflicts: ScopePreview["conflicts"]): ApiError;
86
88
  /**
87
89
  * The super admin's plugin scope and deployment-level disable (plugin and component management
88
- * spec §4.1, §5 rules 2-4 and 8), and the import confirm that enqueues the scope sync of the item it
90
+ * spec §4.1, §5 rules 2-4 and 8), and the import confirm that owes the scope sync of the item it
89
91
  * wrote. A change is previewed, then confirmed with the preview's `scopeHash`, recomputed under the
90
92
  * item row lock (a difference -> 409 `plugin.scope_stale`); it bumps `scope_version`, audits
91
- * `catalog.scope_changed` and, after the commit, enqueues the item's scope sync, which installs or
93
+ * `catalog.scope_changed` and owes the item's scope sync in the same transaction, which installs or
92
94
  * uninstalls in every org. Disabling keeps the scope, its org list and the org switches, so
93
95
  * re-enabling (no hash needed) reinstalls where it was on. Builtin items -> 409 `plugin.builtin`.
94
96
  * Stateless, shared by every replica.
@@ -98,6 +100,10 @@ export declare class CatalogScopeService {
98
100
  private readonly adminLock;
99
101
  private readonly catalog;
100
102
  private readonly pluginImport;
103
+ /** A confirmed first version's platform components (written in the confirming commit). */
104
+ private readonly platform;
105
+ /** The import's item name lock, taken by the confirming commit before the item row. */
106
+ private readonly itemLock;
101
107
  private readonly installer;
102
108
  private readonly extensions;
103
109
  private readonly ops;
@@ -109,23 +115,27 @@ export declare class CatalogScopeService {
109
115
  private readonly installLock;
110
116
  /** This replica's reconcile once a confirmed extension is enabled (before the scope sync). */
111
117
  private readonly lifecycle;
112
- /** The removed org plugin's cleanup job, backing the take-out of P3-21 (pre-flight F9). */
113
- private readonly maintenance;
118
+ /** Owes the scope syncs and the removed org plugin's cleanup (P3-21, pre-flight F9). */
119
+ private readonly outbox;
114
120
  private readonly log;
115
121
  readonly txHost: TransactionHost;
116
- constructor(kdb: KernelDb, adminLock: SuperAdminLock, catalog: CatalogService, pluginImport: PluginImport, installer: PluginInstaller, extensions: ExtensionAdmin, ops: ExtensionAdminOps, sync: PluginScopeSync, updater: PlatformPluginUpdater,
122
+ constructor(kdb: KernelDb, adminLock: SuperAdminLock, catalog: CatalogService, pluginImport: PluginImport,
123
+ /** A confirmed first version's platform components (written in the confirming commit). */
124
+ platform: PlatformComponents,
125
+ /** The import's item name lock, taken by the confirming commit before the item row. */
126
+ itemLock: CatalogItemLock, installer: PluginInstaller, extensions: ExtensionAdmin, ops: ExtensionAdminOps, sync: PluginScopeSync, updater: PlatformPluginUpdater,
117
127
  /** The owner org's lock: an org admin withdrawing its pending upload (ruling P3-10). */
118
128
  orgLock: OrgLock,
119
129
  /** The per-name install lock a reject / withdraw releases the name claim under (M1). */
120
130
  installLock: PluginInstallLock,
121
131
  /** This replica's reconcile once a confirmed extension is enabled (before the scope sync). */
122
132
  lifecycle: ExtensionLifecycle,
123
- /** The removed org plugin's cleanup job, backing the take-out of P3-21 (pre-flight F9). */
124
- maintenance: Pick<Queue, "add">, log: KernelLogger, txHost: TransactionHost);
133
+ /** Owes the scope syncs and the removed org plugin's cleanup (P3-21, pre-flight F9). */
134
+ outbox: Pick<OutboxService, "add">, log: KernelLogger, txHost: TransactionHost);
125
135
  private get db();
126
136
  /**
127
137
  * Confirms a staged import ({@link PluginImport.confirm}: installs and enables the extension,
128
- * writes the new item's scope), then enqueues the item's scope sync when its scope turns it on
138
+ * writes the new item's scope), then owes the item's scope sync when its scope turns it on
129
139
  * by itself (`all` or `named`; an `optional` item is on only where an org admin switches it on).
130
140
  */
131
141
  confirmImport(actor: string, stagingId: string, input: Parameters<PluginImport["confirm"]>[2], opts?: ActorOpts): Promise<PluginConfirmResult>;
@@ -148,9 +158,10 @@ export declare class CatalogScopeService {
148
158
  * pending version (withdrawn, rejected, replaced by one without an extension) -> 409
149
159
  * `extension.not_pending`.
150
160
  *
151
- * A first version: its extension installed, its permissions approved, enabled, then (one
152
- * transaction) the item stops waiting and the owner is told (`upload_confirmed`); after the
153
- * commit its platform components are written and the scope sync enqueued. Each step re-reads
161
+ * A first version: its platform components planned and their files copied (keyed by content),
162
+ * its extension installed, its permissions approved, enabled, then (one transaction) the item
163
+ * stops waiting, its platform component rows are written and the owner is told
164
+ * (`upload_confirmed`); after the commit the scope sync is owed. Each step re-reads
154
165
  * the item under its row lock: removed meanwhile -> 409 `catalog.item_removed`, the pending
155
166
  * version replaced -> `extension.approval_stale`; the extension this confirmation installed is
156
167
  * then taken out again. A new version: the platform update to it
@@ -160,8 +171,8 @@ export declare class CatalogScopeService {
160
171
  */
161
172
  private confirmOrgUpload;
162
173
  /**
163
- * {@link confirmOrgUpload} under the item lock; returns the confirmed first version (its
164
- * platform components and scope sync follow after), null for a new version.
174
+ * {@link confirmOrgUpload} under the item lock; returns the confirmed first version (its scope
175
+ * sync follows after), null for a new version.
165
176
  */
166
177
  private confirmLocked;
167
178
  /** The item is live and its first version confirmed (no longer awaiting). */
@@ -186,18 +197,33 @@ export declare class CatalogScopeService {
186
197
  /**
187
198
  * An extension a confirmation installed whose item was removed or replaced meanwhile is taken
188
199
  * out again (disabled, uninstalled; P3-21), and the name claim released when the item is gone
189
- * (ruling P3-37). Inline and best effort (a failure is logged); a removed item's cleanup job
190
- * (`owned-plugin-cleanup-<itemId>`, idempotent) is enqueued as well, so a failed take-out is
191
- * retried (pre-flight F9).
200
+ * (ruling P3-37), in one transaction ({@link takeOutIn}). Inline (a failure is logged): when the
201
+ * take-out fails, a removed item's cleanup job (`owned-plugin-cleanup-<itemId>`, idempotent) is
202
+ * owed instead, so the job retries it (pre-flight F9). That owe is the last resort: when it
203
+ * fails too (PG unavailable) nothing retries the take-out, and it is logged as an error.
192
204
  */
193
205
  private takeOut;
194
- /** Releases the name claim of a removed item (nothing installed under it any more). */
195
- private releaseIfGone;
206
+ /**
207
+ * {@link takeOut}'s transaction, in the global lock order (ruling P3-50): the super admin lock,
208
+ * the item row, then the extension's install lock (taken by the disable): disabled,
209
+ * uninstalled, and the name claim released when the item is gone.
210
+ */
211
+ private takeOutIn;
212
+ /**
213
+ * Owes the cleanup of a removed item; a live item owes nothing (a removal committing later owes
214
+ * its own).
215
+ */
216
+ private oweCleanupIfGone;
196
217
  /** The item is still live and pending with `version` (row lock), else 409 (P3-21). */
197
218
  private stillPending;
198
219
  /** {@link stillPending} in the caller's transaction; returns the owner org. */
199
220
  private pendingRow;
200
- /** A confirmed first version: the item stops waiting, the owner is told (`upload_confirmed`). */
221
+ /**
222
+ * A confirmed first version: the item stops waiting, its platform component rows are written
223
+ * from `components` (a component changed since they were planned -> 409
224
+ * `extension.approval_stale`: confirm again), the owner is told (`upload_confirmed`). The
225
+ * import's item name lock before the item row, as an import's commit takes them (ruling P3-50).
226
+ */
201
227
  private finishFirstVersion;
202
228
  /**
203
229
  * The super admin rejects an org upload's pending version (ruling P3-10, `reason` shown to the
@@ -238,8 +264,8 @@ export declare class CatalogScopeService {
238
264
  /**
239
265
  * Writes an org-owned plugin's 可共享 flag and copies it to its component rows (ruling P3-2).
240
266
  * Turning it off narrows an `optional` / `all` plugin, and each component with its own such
241
- * scope, to the owner plus the orgs where it is on now (ruling P3-25), and enqueues the item's
242
- * scope sync after the commit. The caller authorizes (the owner org's admin, Task 7). A platform
267
+ * scope, to the owner plus the orgs where it is on now (ruling P3-25), and owes the item's
268
+ * scope sync with it. The caller authorizes (the owner org's admin, Task 7). A platform
243
269
  * item (no owner) or a missing one -> 404.
244
270
  */
245
271
  setShareable(itemId: string, shareable: boolean, actor?: string | null): Promise<void>;
@@ -247,19 +273,30 @@ export declare class CatalogScopeService {
247
273
  * Adds one org to a `named` item's list in the caller's transaction (an approved `access`
248
274
  * request, spec §5.1 rule 2): nobody loses access, so no preview. The item row is locked; it
249
275
  * must be live and not builtin (404 / `plugin.builtin`). Bumps `scope_version`, audits
250
- * `catalog.scope_changed` and enqueues the item's scope sync after the commit. Returns whether
276
+ * `catalog.scope_changed` and owes the item's scope sync in that transaction. Returns whether
251
277
  * the list changed (false: not `named`, or listed already).
252
278
  */
253
279
  addOrg(actor: string, itemId: string, orgId: string, opts?: ActorOpts & {
254
280
  requestId?: string;
255
281
  }): Promise<boolean>;
256
282
  /**
257
- * Enqueues the item's scope sync after a commit made elsewhere (an org upload's confirm,
258
- * `OrgPluginUploads`); a failure only warns.
283
+ * Owes the item's scope sync in the caller's transaction (an ownership transfer, an org upload's
284
+ * confirm in `OrgPluginUploads`).
259
285
  */
260
286
  enqueueSync(itemId: string): Promise<void>;
261
- /** Enqueues the item's scope sync; a failure only warns (the next change or org sync converges). */
287
+ /** Owes the item's scope sync in the transaction that changes its scope (outbox spec §8.1). */
262
288
  private enqueue;
289
+ /**
290
+ * Owes the item's scope sync in a transaction of its own, after a confirmation whose last write
291
+ * (the extension's deploy, or the platform components) committed outside the scope service: the
292
+ * sync must not run before the extension it installs is enabled.
293
+ */
294
+ private oweSync;
295
+ /**
296
+ * Owes the delayed backstop of the item's sync in a transaction of its own (ruling R24): a
297
+ * permissions confirm writes nothing of the scope service's before its enable.
298
+ */
299
+ private oweBackstop;
263
300
  /**
264
301
  * 409 `theme.platform_default` when a live theme of the item is the platform default and `after`
265
302
  * says the change leaves it narrower than `all` or gone (themes spec §7). In the caller's