@aeolus-fleet/core 0.18.0 → 0.20.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 (118) hide show
  1. package/LICENSE +201 -0
  2. package/dist/adapters/prisma/generated/browser.d.ts +25 -0
  3. package/dist/adapters/prisma/generated/client.d.ts +25 -0
  4. package/dist/adapters/prisma/generated/internal/class.d.ts +44 -0
  5. package/dist/adapters/prisma/generated/internal/class.js +4 -4
  6. package/dist/adapters/prisma/generated/internal/class.js.map +1 -1
  7. package/dist/adapters/prisma/generated/internal/prismaNamespace.d.ts +338 -1
  8. package/dist/adapters/prisma/generated/internal/prismaNamespace.js +34 -1
  9. package/dist/adapters/prisma/generated/internal/prismaNamespace.js.map +1 -1
  10. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.d.ts +37 -0
  11. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js +34 -1
  12. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  13. package/dist/adapters/prisma/generated/models/CrewRequest.d.ts +103 -1
  14. package/dist/adapters/prisma/generated/models/Fleet.d.ts +860 -0
  15. package/dist/adapters/prisma/generated/models/Label.d.ts +1475 -0
  16. package/dist/adapters/prisma/generated/models/Label.js +2 -0
  17. package/dist/adapters/prisma/generated/models/Label.js.map +1 -0
  18. package/dist/adapters/prisma/generated/models/LabelValue.d.ts +1454 -0
  19. package/dist/adapters/prisma/generated/models/LabelValue.js +2 -0
  20. package/dist/adapters/prisma/generated/models/LabelValue.js.map +1 -0
  21. package/dist/adapters/prisma/generated/models/Ship.d.ts +1225 -70
  22. package/dist/adapters/prisma/generated/models/ShipLabel.d.ts +1431 -0
  23. package/dist/adapters/prisma/generated/models/ShipLabel.js +2 -0
  24. package/dist/adapters/prisma/generated/models/ShipLabel.js.map +1 -0
  25. package/dist/adapters/prisma/generated/models/WorktreeClearRequest.d.ts +1539 -0
  26. package/dist/adapters/prisma/generated/models/WorktreeClearRequest.js +2 -0
  27. package/dist/adapters/prisma/generated/models/WorktreeClearRequest.js.map +1 -0
  28. package/dist/adapters/prisma/generated/models.d.ts +4 -0
  29. package/dist/adapters/prisma/registry.d.ts +3 -1
  30. package/dist/adapters/prisma/registry.js +129 -9
  31. package/dist/adapters/prisma/registry.js.map +1 -1
  32. package/dist/adapters/prisma/rows.d.ts +10 -0
  33. package/dist/adapters/prisma/rows.js +41 -2
  34. package/dist/adapters/prisma/rows.js.map +1 -1
  35. package/dist/adapters/prisma/unit-of-work.d.ts +3 -1
  36. package/dist/adapters/prisma/unit-of-work.js +3 -1
  37. package/dist/adapters/prisma/unit-of-work.js.map +1 -1
  38. package/dist/adapters/trpc/console.d.ts +1 -1
  39. package/dist/adapters/trpc/context.d.ts +20 -0
  40. package/dist/adapters/trpc/fleet.d.ts +144 -8
  41. package/dist/adapters/trpc/fleet.js +149 -12
  42. package/dist/adapters/trpc/fleet.js.map +1 -1
  43. package/dist/adapters/trpc/router.d.ts +134 -8
  44. package/dist/adapters/trpc/ship-contract.js +10 -0
  45. package/dist/adapters/trpc/ship-contract.js.map +1 -1
  46. package/dist/adapters/trpc/trpc.d.ts +2 -2
  47. package/dist/adapters/trpc/trpc.js +16 -2
  48. package/dist/adapters/trpc/trpc.js.map +1 -1
  49. package/dist/domain/registry/assign-label.d.ts +32 -0
  50. package/dist/domain/registry/assign-label.js +39 -0
  51. package/dist/domain/registry/assign-label.js.map +1 -0
  52. package/dist/domain/registry/change-label-values.d.ts +33 -0
  53. package/dist/domain/registry/change-label-values.js +34 -0
  54. package/dist/domain/registry/change-label-values.js.map +1 -0
  55. package/dist/domain/registry/clear-request.d.ts +69 -0
  56. package/dist/domain/registry/clear-request.js +51 -0
  57. package/dist/domain/registry/clear-request.js.map +1 -0
  58. package/dist/domain/registry/confirm-worktree-cleared.d.ts +31 -0
  59. package/dist/domain/registry/confirm-worktree-cleared.js +30 -0
  60. package/dist/domain/registry/confirm-worktree-cleared.js.map +1 -0
  61. package/dist/domain/registry/crew-request.d.ts +9 -3
  62. package/dist/domain/registry/crew-request.js +9 -6
  63. package/dist/domain/registry/crew-request.js.map +1 -1
  64. package/dist/domain/registry/define-label.d.ts +33 -0
  65. package/dist/domain/registry/define-label.js +33 -0
  66. package/dist/domain/registry/define-label.js.map +1 -0
  67. package/dist/domain/registry/delete-label.d.ts +30 -0
  68. package/dist/domain/registry/delete-label.js +32 -0
  69. package/dist/domain/registry/delete-label.js.map +1 -0
  70. package/dist/domain/registry/find-label-value.d.ts +22 -0
  71. package/dist/domain/registry/find-label-value.js +19 -0
  72. package/dist/domain/registry/find-label-value.js.map +1 -0
  73. package/dist/domain/registry/get-ship.d.ts +1 -1
  74. package/dist/domain/registry/get-ship.js +2 -2
  75. package/dist/domain/registry/get-ship.js.map +1 -1
  76. package/dist/domain/registry/get-starting-prompt.js +3 -3
  77. package/dist/domain/registry/get-starting-prompt.js.map +1 -1
  78. package/dist/domain/registry/label.d.ts +197 -0
  79. package/dist/domain/registry/label.js +263 -0
  80. package/dist/domain/registry/label.js.map +1 -0
  81. package/dist/domain/registry/list-fleet.d.ts +13 -7
  82. package/dist/domain/registry/list-fleet.js +10 -5
  83. package/dist/domain/registry/list-fleet.js.map +1 -1
  84. package/dist/domain/registry/list-labels.d.ts +12 -0
  85. package/dist/domain/registry/list-labels.js +9 -0
  86. package/dist/domain/registry/list-labels.js.map +1 -0
  87. package/dist/domain/registry/ports.d.ts +59 -1
  88. package/dist/domain/registry/read-clear-requests.d.ts +15 -0
  89. package/dist/domain/registry/read-clear-requests.js +16 -0
  90. package/dist/domain/registry/read-clear-requests.js.map +1 -0
  91. package/dist/domain/registry/release-ship.d.ts +1 -1
  92. package/dist/domain/registry/release-ship.js +2 -2
  93. package/dist/domain/registry/release-ship.js.map +1 -1
  94. package/dist/domain/registry/report-crew-status.d.ts +6 -3
  95. package/dist/domain/registry/report-crew-status.js +11 -4
  96. package/dist/domain/registry/report-crew-status.js.map +1 -1
  97. package/dist/domain/registry/request-worktree-clear.d.ts +31 -0
  98. package/dist/domain/registry/request-worktree-clear.js +35 -0
  99. package/dist/domain/registry/request-worktree-clear.js.map +1 -0
  100. package/dist/domain/registry/retire-ship.d.ts +9 -3
  101. package/dist/domain/registry/retire-ship.js +27 -2
  102. package/dist/domain/registry/retire-ship.js.map +1 -1
  103. package/dist/domain/registry/ship.d.ts +1 -1
  104. package/dist/domain/registry/unassign-label.d.ts +30 -0
  105. package/dist/domain/registry/unassign-label.js +37 -0
  106. package/dist/domain/registry/unassign-label.js.map +1 -0
  107. package/dist/domain/shared/errors.d.ts +1 -1
  108. package/dist/domain/shared/errors.js.map +1 -1
  109. package/dist/wiring.d.ts +20 -0
  110. package/dist/wiring.js +21 -1
  111. package/dist/wiring.js.map +1 -1
  112. package/package.json +7 -5
  113. package/src/adapters/prisma/migrations/20261007020000_broad_crewing_scope_retired/migration.sql +8 -0
  114. package/src/adapters/prisma/migrations/20261007100000_labels/migration.sql +87 -0
  115. package/src/adapters/prisma/migrations/20261007110000_foreign_key_indexes/migration.sql +42 -0
  116. package/src/adapters/prisma/migrations/20261007120000_crew_status_attempt/migration.sql +4 -0
  117. package/src/adapters/prisma/migrations/20261007140000_worktree_clear_requests/migration.sql +32 -0
  118. package/src/adapters/prisma/schema.prisma +120 -0
@@ -1,8 +1,10 @@
1
- import type { DeliveryId, DeliveryState, FleetId, LeaseId, MessageId, ShipId } from '@aeolus-fleet/common';
1
+ import type { DeliveryId, DeliveryState, FleetId, LabelId, LabelValueId, LeaseId, MessageId, ShipId } from '@aeolus-fleet/common';
2
2
  import type { Recipient } from '../shared/selector.js';
3
+ import type { ClearRequest } from './clear-request.js';
3
4
  import type { CrewRequest } from './crew-request.js';
4
5
  import type { Fleet } from './fleet.js';
5
6
  import type { InstallationRequest } from './installation-request.js';
7
+ import type { CarriedLabel, Label, ListedLabel, ShipLabel } from './label.js';
6
8
  import type { FleetLimitSettings, InstallationSettings } from './limits.js';
7
9
  import type { Lease, Location } from './lease.js';
8
10
  import type { Ship } from './ship.js';
@@ -178,6 +180,58 @@ export interface CrewRequestRepository {
178
180
  /** The requests assigned to this trierarch ship, oldest ship first. */
179
181
  listAssignedTo(fleetId: FleetId, trierarchShipId: ShipId): Promise<CrewRequest[]>;
180
182
  }
183
+ /**
184
+ * Outbound port: the pending clear requests (decision 0032), one per
185
+ * trierarch, ship and repository, always within one fleet. Lock the
186
+ * trierarch ship first.
187
+ */
188
+ export interface ClearRequestRepository {
189
+ find(fleetId: FleetId, key: {
190
+ trierarchShipId: ShipId;
191
+ shipId: ShipId;
192
+ repository: string;
193
+ }): Promise<ClearRequest | undefined>;
194
+ save(request: ClearRequest): Promise<void>;
195
+ remove(fleetId: FleetId, key: {
196
+ trierarchShipId: ShipId;
197
+ shipId: ShipId;
198
+ repository: string;
199
+ }): Promise<void>;
200
+ /** Every trierarch's, by trierarch, oldest first. */
201
+ list(fleetId: FleetId): Promise<ClearRequest[]>;
202
+ /** One trierarch's, oldest first. */
203
+ listFor(fleetId: FleetId, trierarchShipId: ShipId): Promise<ClearRequest[]>;
204
+ }
205
+ /**
206
+ * Outbound port: the fleet's labels, their values and the values its ships
207
+ * carry, always within one fleet (decision 0031). A retired or deleted label
208
+ * is gone. Lock order: the ship being labelled, then the label.
209
+ */
210
+ export interface LabelRepository {
211
+ /** Holds the lock on this key in the fleet until the unit of work ends, so two definitions of one key never both find it free. */
212
+ lockKey(fleetId: FleetId, key: string): Promise<void>;
213
+ /** The label with this key, read without a lock. */
214
+ findByKey(fleetId: FleetId, key: string): Promise<Label | undefined>;
215
+ /** The label, read without a lock. */
216
+ find(fleetId: FleetId, labelId: LabelId): Promise<Label | undefined>;
217
+ /** The label, locked until the unit of work ends: changing its values. */
218
+ findForUpdate(fleetId: FleetId, labelId: LabelId): Promise<Label | undefined>;
219
+ /** The label that has this value, held until the unit of work ends against a change of its values, its deletion or its retirement, as an assignment holds it. */
220
+ findByValueForShare(fleetId: FleetId, valueId: LabelValueId): Promise<Label | undefined>;
221
+ /** The labels this ship owns, by key, each locked against assignments until the unit of work ends: they go. */
222
+ listOwnedByForUpdate(fleetId: FleetId, ownerShipId: ShipId): Promise<Label[]>;
223
+ /** Stores the label with its values, in their order, replacing the values it had. A removed value no ship carries by then. */
224
+ save(label: Label): Promise<void>;
225
+ /** The label goes, with its values. No ship carries any of them by then. */
226
+ remove(fleetId: FleetId, labelId: LabelId): Promise<void>;
227
+ /** The values the ship carries. */
228
+ carriedBy(fleetId: FleetId, shipId: ShipId): Promise<ShipLabel[]>;
229
+ /** Every ship's assignment of a value of this label, by ship. */
230
+ carriersOf(fleetId: FleetId, labelId: LabelId): Promise<ShipLabel[]>;
231
+ /** The ship carries the value, beside the values it carries. */
232
+ assign(assignment: ShipLabel): Promise<void>;
233
+ unassign(assignment: Pick<ShipLabel, 'fleetId' | 'shipId' | 'valueId'>): Promise<void>;
234
+ }
181
235
  /** A delivery a lease held in flight, pending again: which one, the message it carries, who it is for and its claims so far. */
182
236
  export interface ReturnedDelivery {
183
237
  deliveryId: DeliveryId;
@@ -236,6 +290,8 @@ export interface ShipFacts {
236
290
  id: ShipId;
237
291
  name: string;
238
292
  } | null;
293
+ /** The label values the ship carries, by key then value (decision 0031). */
294
+ labels: readonly CarriedLabel[];
239
295
  /**
240
296
  * The ship that got the starting prompt the open lease claimed with, by id
241
297
  * and name: the actor of the ship's last StartingPromptIssued before the
@@ -304,6 +360,8 @@ export interface InstallationFleets {
304
360
  }
305
361
  export interface FleetListing {
306
362
  ships(fleetId: FleetId): Promise<ShipFacts[]>;
363
+ /** The fleet's labels by key, each with its values and its owner by id and name (decision 0031). */
364
+ labels(fleetId: FleetId): Promise<ListedLabel[]>;
307
365
  /** One ship of the fleet, read the same way; undefined when the fleet has no such ship. */
308
366
  ship(fleetId: FleetId, shipId: ShipId): Promise<ShipFacts | undefined>;
309
367
  /**
@@ -0,0 +1,15 @@
1
+ import { type Caller } from '../shared/caller.js';
2
+ import type { ClearRequest } from './clear-request.js';
3
+ import type { ClearRequestRepository } from './ports.js';
4
+ /** A pending clear request as it is read: whose, which worktree, who asked and when. */
5
+ export type ListedClearRequest = Omit<ClearRequest, 'fleetId'>;
6
+ export type ReadClearRequests = (caller: Caller) => Promise<ListedClearRequest[]>;
7
+ /**
8
+ * Use case: the pending clear requests (decision 0032). A caller with
9
+ * fleet:read reads every trierarch's, so the console shows a worktree
10
+ * clearing; a trierarch with crew:run reads its own. One of the two scopes is
11
+ * checked before this runs.
12
+ */
13
+ export declare function createReadClearRequests(deps: {
14
+ clearRequests: Pick<ClearRequestRepository, 'list' | 'listFor'>;
15
+ }): ReadClearRequests;
@@ -0,0 +1,16 @@
1
+ import { hasScope } from '../shared/caller.js';
2
+ /**
3
+ * Use case: the pending clear requests (decision 0032). A caller with
4
+ * fleet:read reads every trierarch's, so the console shows a worktree
5
+ * clearing; a trierarch with crew:run reads its own. One of the two scopes is
6
+ * checked before this runs.
7
+ */
8
+ export function createReadClearRequests(deps) {
9
+ return async (caller) => {
10
+ const requests = hasScope(caller, 'fleet:read')
11
+ ? await deps.clearRequests.list(caller.fleetId)
12
+ : await deps.clearRequests.listFor(caller.fleetId, caller.shipId);
13
+ return requests.map(({ trierarchShipId, shipId, repository, requestedBy, requestedAt }) => ({ trierarchShipId, shipId, repository, requestedBy, requestedAt }));
14
+ };
15
+ }
16
+ //# sourceMappingURL=read-clear-requests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-clear-requests.js","sourceRoot":"","sources":["../../../src/domain/registry/read-clear-requests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAe,MAAM,qBAAqB,CAAC;AAS5D;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAyE;IAC/G,OAAO,KAAK,EAAE,MAAM,EAAE,EAAE;QACtB,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;YAC7C,CAAC,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;YAC/C,CAAC,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACpE,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,eAAe,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;IAClK,CAAC,CAAC;AACJ,CAAC"}
@@ -22,7 +22,7 @@ export type ReleaseShip = (caller: Caller, input: {
22
22
  * one unit of work: the secret is invalidated, the lease ends and with it the
23
23
  * crew token, and the deliveries the lease held in flight return to pending,
24
24
  * their attempts kept. The next crew needs a new starting prompt. The caller's
25
- * scope (fleet:manage, fleet:crew or crew:run) is checked before this runs;
25
+ * scope (fleet:manage or crew:run) is checked before this runs;
26
26
  * crew:run reaches only the ships whose crew requests are assigned to the
27
27
  * caller's ship.
28
28
  *
@@ -6,14 +6,14 @@ import { endLease } from './leases.js';
6
6
  import { checkReaches } from './crew-request.js';
7
7
  import { checkCanRelease } from './ship.js';
8
8
  /** The scopes that release every ship; crew:run releases only the ships assigned to the caller's ship. */
9
- const RELEASE_SCOPES = ['fleet:manage', 'fleet:crew'];
9
+ const RELEASE_SCOPES = ['fleet:manage'];
10
10
  /**
11
11
  * Use case: the caller releases a crewed ship of its fleet (Release): the
12
12
  * session crewing it loses it, and the ship awaits a new crew (ADR 0010). In
13
13
  * one unit of work: the secret is invalidated, the lease ends and with it the
14
14
  * crew token, and the deliveries the lease held in flight return to pending,
15
15
  * their attempts kept. The next crew needs a new starting prompt. The caller's
16
- * scope (fleet:manage, fleet:crew or crew:run) is checked before this runs;
16
+ * scope (fleet:manage or crew:run) is checked before this runs;
17
17
  * crew:run reaches only the ships whose crew requests are assigned to the
18
18
  * caller's ship.
19
19
  *
@@ -1 +1 @@
1
- {"version":3,"file":"release-ship.js","sourceRoot":"","sources":["../../../src/domain/registry/release-ship.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAqB,MAAM,uBAAuB,CAAC;AAG5E,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAgB,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,eAAe,EAAuB,MAAM,WAAW,CAAC;AASjE,0GAA0G;AAC1G,MAAM,cAAc,GAAG,CAAC,cAAc,EAAE,YAAY,CAAU,CAAC;AAO/D;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAIjC;IACC,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAkD,EAAE;QACxE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,MAAM,iBAAiB,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAC;QAClI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAE5B,MAAM,gBAAgB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9E,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QACxF,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAChB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAC3G,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"release-ship.js","sourceRoot":"","sources":["../../../src/domain/registry/release-ship.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAqB,MAAM,uBAAuB,CAAC;AAG5E,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAgB,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,eAAe,EAAuB,MAAM,WAAW,CAAC;AASjE,0GAA0G;AAC1G,MAAM,cAAc,GAAG,CAAC,cAAc,CAAU,CAAC;AAOjD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAIjC;IACC,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAkD,EAAE;QACxE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,MAAM,iBAAiB,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAC;QAClI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAE5B,MAAM,gBAAgB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9E,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QACxF,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAChB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAC3G,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -15,12 +15,15 @@ export type ReportCrewStatusRefusal = DomainError<'SHIP_NOT_FOUND' | 'CREW_REQUE
15
15
  export type ReportCrewStatus = (caller: Caller, input: {
16
16
  shipId: ShipId;
17
17
  status: CrewStatus;
18
+ attempt?: number;
19
+ startedAt?: string | null;
18
20
  }) => Promise<Result<undefined, ReportCrewStatusRefusal>>;
19
21
  /**
20
22
  * Use case: the trierarch a ship's crew request is assigned to writes how its
21
- * crew stands. Its scope (crew:run) is checked before this runs. In one unit
22
- * of work, locking the ship first: the status and, when it changed,
23
- * CrewStatusChanged.
23
+ * crew stands, with the restart attempt and when the session started (#332;
24
+ * left out, the first start with no session running). Its scope (crew:run)
25
+ * is checked before this runs. In one unit of work, locking the ship first:
26
+ * the status and, when anything of it changed, CrewStatusChanged.
24
27
  */
25
28
  export declare function createReportCrewStatus(deps: {
26
29
  uow: UnitOfWork<ReportCrewStatusTx>;
@@ -4,9 +4,10 @@ import { ok } from '../shared/result.js';
4
4
  import { reportCrewStatus } from './crew-request.js';
5
5
  /**
6
6
  * Use case: the trierarch a ship's crew request is assigned to writes how its
7
- * crew stands. Its scope (crew:run) is checked before this runs. In one unit
8
- * of work, locking the ship first: the status and, when it changed,
9
- * CrewStatusChanged.
7
+ * crew stands, with the restart attempt and when the session started (#332;
8
+ * left out, the first start with no session running). Its scope (crew:run)
9
+ * is checked before this runs. In one unit of work, locking the ship first:
10
+ * the status and, when anything of it changed, CrewStatusChanged.
10
11
  */
11
12
  export function createReportCrewStatus(deps) {
12
13
  return (caller, input) => deps.uow.run(async (tx) => {
@@ -14,7 +15,13 @@ export function createReportCrewStatus(deps) {
14
15
  if (!ship) {
15
16
  return refuse('SHIP_NOT_FOUND', `Ship ${input.shipId} does not exist`);
16
17
  }
17
- const reported = reportCrewStatus({ ship, current: await tx.crewRequests.find(caller.fleetId, ship.id), trierarchShipId: caller.shipId }, { status: input.status, at: deps.clock.now(), actor: shipActor(caller.shipId) });
18
+ const reported = reportCrewStatus({ ship, current: await tx.crewRequests.find(caller.fleetId, ship.id), trierarchShipId: caller.shipId }, {
19
+ status: input.status,
20
+ attempt: input.attempt ?? 0,
21
+ sessionStartedAt: input.startedAt === undefined || input.startedAt === null ? null : new Date(input.startedAt),
22
+ at: deps.clock.now(),
23
+ actor: shipActor(caller.shipId),
24
+ });
18
25
  if (!reported.isOk) {
19
26
  return reported;
20
27
  }
@@ -1 +1 @@
1
- {"version":3,"file":"report-crew-status.js","sourceRoot":"","sources":["../../../src/domain/registry/report-crew-status.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAerD;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAA6E;IAClH,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAuD,EAAE;QAC7E,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACxE,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,KAAK,CAAC,MAAM,iBAAiB,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,QAAQ,GAAG,gBAAgB,CAC/B,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,EACtG,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAChF,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrD,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"report-crew-status.js","sourceRoot":"","sources":["../../../src/domain/registry/report-crew-status.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAkBrD;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAA6E;IAClH,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAuD,EAAE;QAC7E,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACxE,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,KAAK,CAAC,MAAM,iBAAiB,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,QAAQ,GAAG,gBAAgB,CAC/B,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,EACtG;YACE,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,CAAC;YAC3B,gBAAgB,EAAE,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;YAC9G,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YACpB,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;SAChC,CACF,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrD,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { IdGenerator, ShipId } from '@aeolus-fleet/common';
2
+ import type { Caller } from '../shared/caller.js';
3
+ import type { Clock } from '../shared/clock.js';
4
+ import { type DomainError } from '../shared/errors.js';
5
+ import { type EventLog } from '../shared/events.js';
6
+ import { type Result } from '../shared/result.js';
7
+ import type { UnitOfWork } from '../shared/unit-of-work.js';
8
+ import { type RequestWorktreeClearRefusal } from './clear-request.js';
9
+ import type { ClearRequestRepository, ShipRepository } from './ports.js';
10
+ export interface RequestWorktreeClearTx {
11
+ ships: Pick<ShipRepository, 'find' | 'findForUpdate'>;
12
+ clearRequests: ClearRequestRepository;
13
+ events: EventLog;
14
+ }
15
+ export type RequestWorktreeClearUseCaseRefusal = DomainError<'SHIP_NOT_FOUND'> | RequestWorktreeClearRefusal;
16
+ export type RequestWorktreeClear = (caller: Caller, input: {
17
+ trierarchShipId: ShipId;
18
+ shipId: ShipId;
19
+ repository: string;
20
+ }) => Promise<Result<undefined, RequestWorktreeClearUseCaseRefusal>>;
21
+ /**
22
+ * Use case: the caller asks a trierarch to clear the worktree it kept for a
23
+ * ship in a repository (decision 0032). Its scope (fleet:manage) is checked
24
+ * before this runs. In one unit of work, locking the trierarch ship first so
25
+ * two requests never both pass its limit: the request and its event.
26
+ */
27
+ export declare function createRequestWorktreeClear(deps: {
28
+ uow: UnitOfWork<RequestWorktreeClearTx>;
29
+ clock: Clock;
30
+ ids: IdGenerator;
31
+ }): RequestWorktreeClear;
@@ -0,0 +1,35 @@
1
+ import { refuse } from '../shared/errors.js';
2
+ import { recordEvent, shipActor } from '../shared/events.js';
3
+ import { ok } from '../shared/result.js';
4
+ import { requestWorktreeClear } from './clear-request.js';
5
+ /**
6
+ * Use case: the caller asks a trierarch to clear the worktree it kept for a
7
+ * ship in a repository (decision 0032). Its scope (fleet:manage) is checked
8
+ * before this runs. In one unit of work, locking the trierarch ship first so
9
+ * two requests never both pass its limit: the request and its event.
10
+ */
11
+ export function createRequestWorktreeClear(deps) {
12
+ return (caller, input) => deps.uow.run(async (tx) => {
13
+ const { fleetId } = caller;
14
+ const trierarch = await tx.ships.findForUpdate(fleetId, input.trierarchShipId);
15
+ if (!trierarch) {
16
+ return refuse('SHIP_NOT_FOUND', `Ship ${input.trierarchShipId} does not exist`);
17
+ }
18
+ if (!(await tx.ships.find(fleetId, input.shipId))) {
19
+ return refuse('SHIP_NOT_FOUND', `Ship ${input.shipId} does not exist`);
20
+ }
21
+ const key = { trierarchShipId: trierarch.id, shipId: input.shipId, repository: input.repository };
22
+ const requested = requestWorktreeClear({ trierarch, current: await tx.clearRequests.find(fleetId, key), pending: (await tx.clearRequests.listFor(fleetId, trierarch.id)).length }, { shipId: input.shipId, repository: input.repository, requestedBy: caller.shipId, at: deps.clock.now(), actor: shipActor(caller.shipId) });
23
+ if (!requested.isOk) {
24
+ return requested;
25
+ }
26
+ if (requested.value.request) {
27
+ await tx.clearRequests.save(requested.value.request);
28
+ }
29
+ for (const event of requested.value.events) {
30
+ await recordEvent({ events: tx.events, ids: deps.ids }, event);
31
+ }
32
+ return ok(undefined);
33
+ });
34
+ }
35
+ //# sourceMappingURL=request-worktree-clear.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-worktree-clear.js","sourceRoot":"","sources":["../../../src/domain/registry/request-worktree-clear.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,oBAAoB,EAAoC,MAAM,oBAAoB,CAAC;AAgB5F;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAAiF;IAC1H,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAkE,EAAE;QACxF,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;QAC/E,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,KAAK,CAAC,eAAe,iBAAiB,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YAClD,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,KAAK,CAAC,MAAM,iBAAiB,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,GAAG,GAAG,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;QAClG,MAAM,SAAS,GAAG,oBAAoB,CACpC,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,EAC1I,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAC1I,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YACpB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC5B,MAAM,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvD,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -6,11 +6,13 @@ import { type DomainError } from '../shared/errors.js';
6
6
  import { type Result } from '../shared/result.js';
7
7
  import type { UnitOfWork } from '../shared/unit-of-work.js';
8
8
  import { type LeaseTx } from './leases.js';
9
- import type { CrewRequestRepository, ShipRepository } from './ports.js';
9
+ import type { ClearRequestRepository, CrewRequestRepository, LabelRepository, ShipRepository } from './ports.js';
10
10
  import { type RetireRefusal } from './ship.js';
11
11
  export interface RetireShipTx extends LeaseTx, CredentialTx {
12
12
  ships: ShipRepository;
13
13
  crewRequests: CrewRequestRepository;
14
+ clearRequests: ClearRequestRepository;
15
+ labels: LabelRepository;
14
16
  }
15
17
  export type RetireShipRefusal = DomainError<'SHIP_NOT_FOUND'> | RetireRefusal;
16
18
  export type RetireShip = (caller: Caller, input: {
@@ -27,8 +29,12 @@ export type RetireShip = (caller: Caller, input: {
27
29
  * is retired: never claimed or addressed again, its name free. Deliveries to
28
30
  * its type stay for the other ships of the type, and an undeliverable one
29
31
  * stays for the operator. Its crew request, if any, goes with
30
- * CrewRequestRemoved: no one crews a retired ship. The caller's scope (fleet:manage) is checked before
31
- * this runs.
32
+ * CrewRequestRemoved: no one crews a retired ship. The labels it carries go,
33
+ * and the labels it owns retire with it, each locked first and every
34
+ * assignment of it gone first (decision 0031). A retired trierarch clears
35
+ * nothing: its pending clear requests go, one WorktreeClearRemoved each
36
+ * (decision 0032). The caller's scope
37
+ * (fleet:manage) is checked before this runs.
32
38
  *
33
39
  * It locks the ship first, as a release does (FOR NO KEY UPDATE). A send to
34
40
  * the ship holds it FOR SHARE while it resolves the selector, so the two
@@ -2,7 +2,9 @@ import { revokeShipSecret } from '../identity/public.js';
2
2
  import { refuse } from '../shared/errors.js';
3
3
  import { recordEvent, shipActor } from '../shared/events.js';
4
4
  import { ok } from '../shared/result.js';
5
+ import { removeClearRequestsOf } from './clear-request.js';
5
6
  import { removeCrewRequest } from './crew-request.js';
7
+ import { retireLabelsWith } from './label.js';
6
8
  import { endLease } from './leases.js';
7
9
  import { checkCanRetire } from './ship.js';
8
10
  /**
@@ -14,8 +16,12 @@ import { checkCanRetire } from './ship.js';
14
16
  * is retired: never claimed or addressed again, its name free. Deliveries to
15
17
  * its type stay for the other ships of the type, and an undeliverable one
16
18
  * stays for the operator. Its crew request, if any, goes with
17
- * CrewRequestRemoved: no one crews a retired ship. The caller's scope (fleet:manage) is checked before
18
- * this runs.
19
+ * CrewRequestRemoved: no one crews a retired ship. The labels it carries go,
20
+ * and the labels it owns retire with it, each locked first and every
21
+ * assignment of it gone first (decision 0031). A retired trierarch clears
22
+ * nothing: its pending clear requests go, one WorktreeClearRemoved each
23
+ * (decision 0032). The caller's scope
24
+ * (fleet:manage) is checked before this runs.
19
25
  *
20
26
  * It locks the ship first, as a release does (FOR NO KEY UPDATE). A send to
21
27
  * the ship holds it FOR SHARE while it resolves the selector, so the two
@@ -62,6 +68,25 @@ export function createRetireShip(deps) {
62
68
  await recordEvent(recorded, event);
63
69
  }
64
70
  }
71
+ const clearRequests = await tx.clearRequests.listFor(fleetId, shipId);
72
+ for (const request of clearRequests) {
73
+ await tx.clearRequests.remove(fleetId, request);
74
+ }
75
+ for (const event of removeClearRequestsOf({ trierarch: ship, requests: clearRequests }, { at, actor })) {
76
+ await recordEvent(recorded, event);
77
+ }
78
+ const owned = await Promise.all((await tx.labels.listOwnedByForUpdate(fleetId, shipId)).map(async (label) => ({ label, carriers: await tx.labels.carriersOf(fleetId, label.id) })));
79
+ const carried = await Promise.all((await tx.labels.carriedBy(fleetId, shipId)).map(async (assignment) => ({ label: await tx.labels.find(fleetId, assignment.labelId), assignment })));
80
+ const labels = retireLabelsWith({ owned, carried: carried.flatMap(({ label, assignment }) => (label ? [{ label, assignment }] : [])) }, { at, actor });
81
+ for (const assignment of labels.unassigned) {
82
+ await tx.labels.unassign(assignment);
83
+ }
84
+ for (const label of labels.retired) {
85
+ await tx.labels.remove(fleetId, label.id);
86
+ }
87
+ for (const event of labels.events) {
88
+ await recordEvent(recorded, event);
89
+ }
65
90
  return ok({ abandonedDeliveries: abandoned.length });
66
91
  });
67
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"retire-ship.js","sourceRoot":"","sources":["../../../src/domain/registry/retire-ship.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAqB,MAAM,uBAAuB,CAAC;AAG5E,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAgB,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,cAAc,EAAsB,MAAM,WAAW,CAAC;AAc/D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAIhC;IACC,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAuE,EAAE;QAC7F,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,MAAM,iBAAiB,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YACpB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;QAEtD,MAAM,gBAAgB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9E,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACjE,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QACtG,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAChF,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QAE/C,MAAM,WAAW,CAAC,QAAQ,EAAE;YAC1B,OAAO;YACP,IAAI,EAAE,aAAa;YACnB,UAAU,EAAE,EAAE;YACd,KAAK;YACL,MAAM;YACN,OAAO,EAAE,EAAE,mBAAmB,EAAE,SAAS,CAAC,MAAM,EAAE;SACnD,CAAC,CAAC;QACH,KAAK,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,SAAS,EAAE,CAAC;YAClD,MAAM,WAAW,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;QAC5H,CAAC;QACD,mEAAmE;QACnE,MAAM,OAAO,GAAG,iBAAiB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACjH,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC9C,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;gBACzC,MAAM,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QACD,OAAO,EAAE,CAAC,EAAE,mBAAmB,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"retire-ship.js","sourceRoot":"","sources":["../../../src/domain/registry/retire-ship.ts"],"names":[],"mappings":"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"}
@@ -65,7 +65,7 @@ export declare function commissionAgentShip(input: {
65
65
  name: string;
66
66
  type: string;
67
67
  note?: string;
68
- /** fleet:read, fleet:manage and/or fleet:crew, added to the agent scopes (ADR 0002). */
68
+ /** fleet:read, fleet:manage, crew:assign and/or crew:run, added to the agent scopes (ADR 0002, decision 0029). */
69
69
  fleetScopes?: readonly FleetScope[];
70
70
  at: Date;
71
71
  actor: Actor;
@@ -0,0 +1,30 @@
1
+ import type { IdGenerator, LabelValueId, ShipId } from '@aeolus-fleet/common';
2
+ import type { Caller } from '../shared/caller.js';
3
+ import type { Clock } from '../shared/clock.js';
4
+ import { type DomainError } from '../shared/errors.js';
5
+ import { type EventLog } from '../shared/events.js';
6
+ import { type Result } from '../shared/result.js';
7
+ import type { UnitOfWork } from '../shared/unit-of-work.js';
8
+ import { type UnassignLabelRefusal } from './label.js';
9
+ import type { LabelRepository, ShipRepository } from './ports.js';
10
+ export interface UnassignLabelTx {
11
+ ships: Pick<ShipRepository, 'find' | 'findForUpdate'>;
12
+ labels: Pick<LabelRepository, 'findByValueForShare' | 'carriedBy' | 'unassign'>;
13
+ events: EventLog;
14
+ }
15
+ export type UnassignLabelFailure = DomainError<'SHIP_NOT_FOUND' | 'LABEL_VALUE_NOT_FOUND'> | UnassignLabelRefusal;
16
+ export type UnassignLabel = (caller: Caller, input: {
17
+ shipId: ShipId;
18
+ valueId: LabelValueId;
19
+ }) => Promise<Result<undefined, UnassignLabelFailure>>;
20
+ /**
21
+ * Use case: a label's owner takes one of its values off a ship, by the value's id (decision 0031). Its scope
22
+ * (labels:assign) is checked before this runs. In one unit of work, locking
23
+ * the ship, then holding the label, as an assignment does: the assignment
24
+ * goes, with LabelUnassigned.
25
+ */
26
+ export declare function createUnassignLabel(deps: {
27
+ uow: UnitOfWork<UnassignLabelTx>;
28
+ clock: Clock;
29
+ ids: IdGenerator;
30
+ }): UnassignLabel;
@@ -0,0 +1,37 @@
1
+ import { refuse } from '../shared/errors.js';
2
+ import { recordEvent, shipActor } from '../shared/events.js';
3
+ import { ok } from '../shared/result.js';
4
+ import { unassignLabel } from './label.js';
5
+ /**
6
+ * Use case: a label's owner takes one of its values off a ship, by the value's id (decision 0031). Its scope
7
+ * (labels:assign) is checked before this runs. In one unit of work, locking
8
+ * the ship, then holding the label, as an assignment does: the assignment
9
+ * goes, with LabelUnassigned.
10
+ */
11
+ export function createUnassignLabel(deps) {
12
+ return (caller, input) => deps.uow.run(async (tx) => {
13
+ const { fleetId } = caller;
14
+ const ship = await tx.ships.findForUpdate(fleetId, input.shipId);
15
+ if (!ship) {
16
+ return refuse('SHIP_NOT_FOUND', `Ship ${input.shipId} does not exist`);
17
+ }
18
+ const label = await tx.labels.findByValueForShare(fleetId, input.valueId);
19
+ // Read after the lock: a change of values that came first may have removed the value.
20
+ if (!label?.values.some((value) => value.id === input.valueId)) {
21
+ return refuse('LABEL_VALUE_NOT_FOUND', `The fleet has no label value ${input.valueId}`);
22
+ }
23
+ const owner = await tx.ships.find(fleetId, label.ownerShipId);
24
+ const unassigned = unassignLabel({ label, ownerName: owner?.name ?? label.ownerShipId, ship, carried: await tx.labels.carriedBy(fleetId, ship.id) }, { callerShipId: caller.shipId, valueId: input.valueId, at: deps.clock.now(), actor: shipActor(caller.shipId) });
25
+ if (!unassigned.isOk) {
26
+ return unassigned;
27
+ }
28
+ if (unassigned.value.unassigned) {
29
+ await tx.labels.unassign(unassigned.value.unassigned);
30
+ }
31
+ for (const event of unassigned.value.events) {
32
+ await recordEvent({ events: tx.events, ids: deps.ids }, event);
33
+ }
34
+ return ok(undefined);
35
+ });
36
+ }
37
+ //# sourceMappingURL=unassign-label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unassign-label.js","sourceRoot":"","sources":["../../../src/domain/registry/unassign-label.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAA6B,MAAM,YAAY,CAAC;AAatE;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAA0E;IAC5G,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAoD,EAAE;QAC1E,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,KAAK,CAAC,MAAM,iBAAiB,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1E,sFAAsF;QACtF,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/D,OAAO,MAAM,CAAC,uBAAuB,EAAE,gCAAgC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;QAC9D,MAAM,UAAU,GAAG,aAAa,CAC9B,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,EAClH,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAC/G,CAAC;QACF,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;YACrB,OAAO,UAAU,CAAC;QACpB,CAAC;QACD,IAAI,UAAU,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YAChC,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACxD,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC5C,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { type Err } from './result.js';
2
2
  /** Every reason the domain refuses a request. */
3
- export type DomainErrorKind = 'ASSIGNEE_NOT_ACTIVE' | 'CREW_REQUEST_ALREADY_ASSIGNED' | 'CREW_REQUEST_NOT_ASSIGNED_TO_CALLER' | 'CREW_REQUEST_NOT_FOUND' | 'CREW_REQUEST_NOT_RELEASING' | 'CREW_REQUEST_RELEASING' | 'CREW_REQUEST_SETTINGS_TOO_LARGE' | 'DELIVERY_HELD_BY_ANOTHER_SHIP' | 'DELIVERY_NOT_FOUND' | 'DELIVERY_NOT_A_PING' | 'DELIVERY_NOT_IN_FLIGHT' | 'DELIVERY_NOT_OPEN' | 'DELIVERY_NOT_UNDELIVERABLE' | 'FLEET_ALREADY_EXISTS' | 'FLEET_LIMIT_REACHED' | 'FLEET_NOT_FOUND' | 'FLEET_HAS_NO_VIEWER' | 'NOTICE_NOT_FOUND' | 'NOTICE_NOT_DISMISSIBLE' | 'GUIDE_NOT_FOUND' | 'GUIDE_STEP_NOT_FOUND' | 'IDEMPOTENCY_KEY_REUSED' | 'IN_REPLY_TO_NOT_FOUND' | 'MESSAGE_LIMIT_REACHED' | 'MODEL_REQUIRED' | 'INVALID_HARNESS' | 'MODEL_FROM_ARGO' | 'INVALID_CONTENT_TYPE' | 'INVALID_EMAIL' | 'INVALID_FLEET_NAME' | 'INVALID_FOLLOW_MAX' | 'INVALID_FOLLOW_WAIT' | 'INVALID_IDEMPOTENCY_KEY' | 'INVALID_INBOX_WAIT' | 'INVALID_LIMIT' | 'INVALID_LOCATION' | 'INVALID_PASSWORD' | 'INVALID_RECEIVE_MAX' | 'INVALID_CREW_REQUEST_REASON' | 'INVALID_REPORT_DETAILS' | 'INVALID_REPORT_NOTE' | 'INVALID_REPORT_STATE' | 'INVALID_SHIP_NAME' | 'INVALID_SHIP_NOTE' | 'INVALID_SHIP_TYPE' | 'LEASE_ENDED' | 'MESSAGE_NOT_FOUND' | 'NOT_THE_OPERATOR_SHIP' | 'OPERATOR_EMAIL_TAKEN' | 'OPERATOR_HAS_NO_PASSWORD' | 'OPERATOR_SHIP_GETS_NO_STARTING_PROMPT' | 'OPERATOR_SHIP_HAS_NO_SECRET' | 'OPERATOR_SHIP_IS_NOT_PINGED' | 'OPERATOR_SHIP_IS_PERMANENT' | 'PAYLOAD_TOO_LARGE' | 'PING_NOT_RESENT' | 'REPORT_DETAILS_TOO_LARGE' | 'RESERVED_CONTENT_TYPE' | 'SHIP_ALREADY_RETIRED' | 'SHIP_NAME_RESERVED' | 'SHIP_NAME_TAKEN' | 'SHIP_NOT_AWAITING_CREW' | 'SHIP_NOT_CREWED' | 'SHIP_LIMIT_REACHED' | 'SHIP_NOT_FOUND' | 'SIGN_IN_TICKET_INVALID' | 'UNKNOWN_CREW_TOKEN' | 'UNRESOLVABLE_SELECTOR' | 'WRONG_EMAIL_OR_PASSWORD' | 'WRONG_SHIP_ID_OR_SECRET';
3
+ export type DomainErrorKind = 'ASSIGNEE_NOT_ACTIVE' | 'CLEAR_REQUEST_LIMIT_REACHED' | 'CLEAR_REQUEST_NOT_FOUND' | 'CREW_REQUEST_ALREADY_ASSIGNED' | 'CREW_REQUEST_NOT_ASSIGNED_TO_CALLER' | 'CREW_REQUEST_NOT_FOUND' | 'CREW_REQUEST_NOT_RELEASING' | 'CREW_REQUEST_RELEASING' | 'CREW_REQUEST_SETTINGS_TOO_LARGE' | 'DELIVERY_HELD_BY_ANOTHER_SHIP' | 'DELIVERY_NOT_FOUND' | 'DELIVERY_NOT_A_PING' | 'DELIVERY_NOT_IN_FLIGHT' | 'DELIVERY_NOT_OPEN' | 'DELIVERY_NOT_UNDELIVERABLE' | 'FLEET_ALREADY_EXISTS' | 'FLEET_LIMIT_REACHED' | 'FLEET_NOT_FOUND' | 'FLEET_HAS_NO_VIEWER' | 'NOTICE_NOT_FOUND' | 'NOTICE_NOT_DISMISSIBLE' | 'GUIDE_NOT_FOUND' | 'GUIDE_STEP_NOT_FOUND' | 'IDEMPOTENCY_KEY_REUSED' | 'IN_REPLY_TO_NOT_FOUND' | 'MESSAGE_LIMIT_REACHED' | 'MODEL_REQUIRED' | 'INVALID_HARNESS' | 'MODEL_FROM_ARGO' | 'INVALID_CONTENT_TYPE' | 'INVALID_EMAIL' | 'INVALID_FLEET_NAME' | 'INVALID_FOLLOW_MAX' | 'INVALID_FOLLOW_WAIT' | 'INVALID_IDEMPOTENCY_KEY' | 'INVALID_INBOX_WAIT' | 'INVALID_LABEL_KEY' | 'INVALID_LABEL_VALUE' | 'INVALID_LABEL_VALUES' | 'INVALID_LIMIT' | 'INVALID_LOCATION' | 'INVALID_PASSWORD' | 'INVALID_RECEIVE_MAX' | 'INVALID_CREW_REQUEST_REASON' | 'INVALID_REPORT_DETAILS' | 'INVALID_REPORT_NOTE' | 'INVALID_REPORT_STATE' | 'INVALID_SHIP_NAME' | 'INVALID_SHIP_NOTE' | 'INVALID_SHIP_TYPE' | 'LABEL_CARRIED' | 'LABEL_KEY_TAKEN' | 'LABEL_NOT_FOUND' | 'LABEL_ON_OWN_SHIP' | 'LABEL_VALUE_CARRIED' | 'LABEL_VALUE_NOT_FOUND' | 'LEASE_ENDED' | 'MESSAGE_NOT_FOUND' | 'NOT_A_TRIERARCH' | 'NOT_THE_LABEL_OWNER' | 'NOT_THE_OPERATOR_SHIP' | 'OPERATOR_EMAIL_TAKEN' | 'OPERATOR_HAS_NO_PASSWORD' | 'OPERATOR_SHIP_GETS_NO_STARTING_PROMPT' | 'OPERATOR_SHIP_HAS_NO_SECRET' | 'OPERATOR_SHIP_IS_NOT_PINGED' | 'OPERATOR_SHIP_IS_PERMANENT' | 'PAYLOAD_TOO_LARGE' | 'PING_NOT_RESENT' | 'REPORT_DETAILS_TOO_LARGE' | 'RESERVED_CONTENT_TYPE' | 'SHIP_ALREADY_RETIRED' | 'SHIP_NAME_RESERVED' | 'SHIP_NAME_TAKEN' | 'SHIP_NOT_AWAITING_CREW' | 'SHIP_NOT_CREWED' | 'SHIP_LABEL_LIMIT_REACHED' | 'SHIP_LIMIT_REACHED' | 'SHIP_NOT_FOUND' | 'SIGN_IN_TICKET_INVALID' | 'UNKNOWN_CREW_TOKEN' | 'UNRESOLVABLE_SELECTOR' | 'WRONG_EMAIL_OR_PASSWORD' | 'WRONG_SHIP_ID_OR_SECRET';
4
4
  /**
5
5
  * Why the domain refused a request. Adapters map the kind to their own error
6
6
  * shape (a tRPC code, an exit code); the message is safe to show a caller.
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/domain/shared/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAY,MAAM,aAAa,CAAC;AAoF5C,qDAAqD;AACrD,MAAM,UAAU,MAAM,CAA4B,IAAO,EAAE,OAAe;IACxE,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/domain/shared/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAY,MAAM,aAAa,CAAC;AAkG5C,qDAAqD;AACrD,MAAM,UAAU,MAAM,CAA4B,IAAO,EAAE,OAAe;IACxE,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAChC,CAAC"}
package/dist/wiring.d.ts CHANGED
@@ -47,7 +47,17 @@ import { type AssignCrew } from './domain/registry/assign-crew.js';
47
47
  import { type ReportCrewStatus } from './domain/registry/report-crew-status.js';
48
48
  import { type ConfirmCrewRelease } from './domain/registry/confirm-crew-release.js';
49
49
  import { type ReadAssignedCrewRequests } from './domain/registry/read-assigned-crew-requests.js';
50
+ import { type ConfirmWorktreeCleared } from './domain/registry/confirm-worktree-cleared.js';
51
+ import { type ReadClearRequests } from './domain/registry/read-clear-requests.js';
52
+ import { type RequestWorktreeClear } from './domain/registry/request-worktree-clear.js';
50
53
  import { type ExplainCrewRequest } from './domain/registry/explain-crew-request.js';
54
+ import { type DefineLabel } from './domain/registry/define-label.js';
55
+ import { type ChangeLabelValues } from './domain/registry/change-label-values.js';
56
+ import { type AssignLabel } from './domain/registry/assign-label.js';
57
+ import { type UnassignLabel } from './domain/registry/unassign-label.js';
58
+ import { type ListLabels } from './domain/registry/list-labels.js';
59
+ import { type DeleteLabel } from './domain/registry/delete-label.js';
60
+ import { type FindLabelValue } from './domain/registry/find-label-value.js';
51
61
  import { type ReadReportLog } from './domain/registry/report-log.js';
52
62
  import { type Whoami } from './domain/registry/whoami.js';
53
63
  import type { Clock } from './domain/shared/clock.js';
@@ -90,7 +100,17 @@ export interface UseCases {
90
100
  reportCrewStatus: ReportCrewStatus;
91
101
  confirmCrewRelease: ConfirmCrewRelease;
92
102
  readAssignedCrewRequests: ReadAssignedCrewRequests;
103
+ requestWorktreeClear: RequestWorktreeClear;
104
+ readClearRequests: ReadClearRequests;
105
+ confirmWorktreeCleared: ConfirmWorktreeCleared;
93
106
  explainCrewRequest: ExplainCrewRequest;
107
+ defineLabel: DefineLabel;
108
+ changeLabelValues: ChangeLabelValues;
109
+ assignLabel: AssignLabel;
110
+ unassignLabel: UnassignLabel;
111
+ listLabels: ListLabels;
112
+ deleteLabel: DeleteLabel;
113
+ findLabelValue: FindLabelValue;
94
114
  reportLog: ReadReportLog;
95
115
  deregister: Deregister;
96
116
  sendMessage: SendMessage;
package/dist/wiring.js CHANGED
@@ -4,7 +4,7 @@ import { cryptoRandomTokens, sha256Hasher } from './adapters/crypto/secrets.js';
4
4
  import { createPrismaFleetEventFeed } from './adapters/prisma/event-log.js';
5
5
  import { createPrismaFleetCounter } from './adapters/prisma/fleet-counter.js';
6
6
  import { createPrismaShipHistory } from './adapters/prisma/history.js';
7
- import { createPrismaFleetListing, createPrismaFleetRepository, createPrismaCrewRequestRepository, createPrismaLeaseRepository, createPrismaShipRepository, } from './adapters/prisma/registry.js';
7
+ import { createPrismaFleetListing, createPrismaFleetRepository, createPrismaClearRequestRepository, createPrismaCrewRequestRepository, createPrismaLeaseRepository, createPrismaShipRepository, } from './adapters/prisma/registry.js';
8
8
  import { createPrismaGuideProgress, createPrismaNoticeDismissals, createPrismaOperatorAccountLookup } from './adapters/prisma/identity.js';
9
9
  import { createReceiverWakeups } from './adapters/prisma/receiver-wakeups.js';
10
10
  import { createPrismaFleetLimitReads, createPrismaGuideRepository, createPrismaInstallationFleets, createPrismaInstallationSettings, createPrismaNoticeRepository, } from './adapters/prisma/installation.js';
@@ -55,7 +55,17 @@ import { createAssignCrew } from './domain/registry/assign-crew.js';
55
55
  import { createReportCrewStatus } from './domain/registry/report-crew-status.js';
56
56
  import { createConfirmCrewRelease } from './domain/registry/confirm-crew-release.js';
57
57
  import { createReadAssignedCrewRequests } from './domain/registry/read-assigned-crew-requests.js';
58
+ import { createConfirmWorktreeCleared } from './domain/registry/confirm-worktree-cleared.js';
59
+ import { createReadClearRequests } from './domain/registry/read-clear-requests.js';
60
+ import { createRequestWorktreeClear } from './domain/registry/request-worktree-clear.js';
58
61
  import { createExplainCrewRequest } from './domain/registry/explain-crew-request.js';
62
+ import { createDefineLabel } from './domain/registry/define-label.js';
63
+ import { createChangeLabelValues } from './domain/registry/change-label-values.js';
64
+ import { createAssignLabel } from './domain/registry/assign-label.js';
65
+ import { createUnassignLabel } from './domain/registry/unassign-label.js';
66
+ import { createListLabels } from './domain/registry/list-labels.js';
67
+ import { createDeleteLabel } from './domain/registry/delete-label.js';
68
+ import { createFindLabelValue } from './domain/registry/find-label-value.js';
59
69
  import { createReadReportLog } from './domain/registry/report-log.js';
60
70
  import { createWhoami } from './domain/registry/whoami.js';
61
71
  import { createPing } from './domain/shared/ping.js';
@@ -137,6 +147,16 @@ export function createUseCases(options) {
137
147
  confirmCrewRelease: createConfirmCrewRelease({ uow, clock, ids }),
138
148
  readAssignedCrewRequests: createReadAssignedCrewRequests({ crewRequests: createPrismaCrewRequestRepository(prisma) }),
139
149
  explainCrewRequest: createExplainCrewRequest({ uow, clock, ids }),
150
+ requestWorktreeClear: createRequestWorktreeClear({ uow, clock, ids }),
151
+ readClearRequests: createReadClearRequests({ clearRequests: createPrismaClearRequestRepository(prisma) }),
152
+ confirmWorktreeCleared: createConfirmWorktreeCleared({ uow, clock, ids }),
153
+ defineLabel: createDefineLabel({ uow, clock, ids }),
154
+ changeLabelValues: createChangeLabelValues({ uow, clock, ids }),
155
+ assignLabel: createAssignLabel({ uow, clock, ids }),
156
+ unassignLabel: createUnassignLabel({ uow, clock, ids }),
157
+ listLabels: createListLabels({ listing: createPrismaFleetListing(prisma) }),
158
+ deleteLabel: createDeleteLabel({ uow, clock, ids }),
159
+ findLabelValue: createFindLabelValue({ listing: createPrismaFleetListing(prisma) }),
140
160
  reportLog: createReadReportLog({ leases: createPrismaLeaseRepository(prisma) }),
141
161
  deregister: createDeregister({ uow, clock, ids }),
142
162
  sendMessage: createSendMessage({ uow, clock, ids, hasher: sha256Hasher }),