@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
@@ -0,0 +1,51 @@
1
+ import { CLEAR_REQUESTS_PER_TRIERARCH_MAX } from '@aeolus-fleet/common';
2
+ import { refuse } from '../shared/errors.js';
3
+ import { ok } from '../shared/result.js';
4
+ /** The type of the ship a trierarch crews (docs/trierarch.md). */
5
+ export const TRIERARCH_SHIP_TYPE = 'trierarch';
6
+ function event(trierarch, change) {
7
+ const { at, actor, ...what } = change;
8
+ return { fleetId: trierarch.fleetId, occurredAt: at, actor, shipId: trierarch.id, ...what };
9
+ }
10
+ /**
11
+ * A ship asks a trierarch to clear the worktree it kept for a ship in a
12
+ * repository: the request, and WorktreeClearRequested on the trierarch's
13
+ * ship. Only a trierarch that is not retired; at most
14
+ * CLEAR_REQUESTS_PER_TRIERARCH_MAX pending at once. A request it holds
15
+ * already changes nothing: no request and no event.
16
+ */
17
+ export function requestWorktreeClear({ trierarch, current, pending }, input) {
18
+ if (trierarch.type !== TRIERARCH_SHIP_TYPE) {
19
+ return refuse('NOT_A_TRIERARCH', `${trierarch.name} is no trierarch: only a trierarch clears a worktree it kept`);
20
+ }
21
+ if (trierarch.retiredAt !== null) {
22
+ return refuse('SHIP_ALREADY_RETIRED', `${trierarch.name} is retired: a retired trierarch clears nothing`);
23
+ }
24
+ if (current) {
25
+ return ok({ request: null, events: [] });
26
+ }
27
+ if (pending >= CLEAR_REQUESTS_PER_TRIERARCH_MAX) {
28
+ return refuse('CLEAR_REQUEST_LIMIT_REACHED', `${trierarch.name} holds ${String(CLEAR_REQUESTS_PER_TRIERARCH_MAX)} clear requests already, the most a trierarch may hold (decision 0032): ask again once it confirms some`);
29
+ }
30
+ const { shipId, repository, requestedBy, at, actor } = input;
31
+ return ok({
32
+ request: { fleetId: trierarch.fleetId, trierarchShipId: trierarch.id, shipId, repository, requestedBy, requestedAt: at },
33
+ events: [event(trierarch, { type: 'WorktreeClearRequested', details: { worktreeShipId: shipId, repository }, at, actor })],
34
+ });
35
+ }
36
+ /**
37
+ * The trierarch confirms a clear request it holds, saying how it came out:
38
+ * the request goes, with WorktreeCleared and the outcome.
39
+ */
40
+ export function confirmWorktreeCleared({ trierarch, worktreeShipName, current }, input) {
41
+ const { repository, outcome, at, actor } = input;
42
+ if (!current) {
43
+ return refuse('CLEAR_REQUEST_NOT_FOUND', `${trierarch.name} holds no clear request for the ${repository} worktree of ${worktreeShipName}`);
44
+ }
45
+ return ok({ events: [event(trierarch, { type: 'WorktreeCleared', details: { worktreeShipId: current.shipId, repository, outcome }, at, actor })] });
46
+ }
47
+ /** A retired trierarch clears nothing: its pending requests go, one WorktreeClearRemoved each. */
48
+ export function removeClearRequestsOf({ trierarch, requests }, change) {
49
+ return requests.map(({ shipId, repository }) => event(trierarch, { type: 'WorktreeClearRemoved', details: { worktreeShipId: shipId, repository }, ...change }));
50
+ }
51
+ //# sourceMappingURL=clear-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clear-request.js","sourceRoot":"","sources":["../../../src/domain/registry/clear-request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { ClearOutcome, 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 ConfirmWorktreeClearedRefusal } from './clear-request.js';
9
+ import type { ClearRequestRepository, ShipRepository } from './ports.js';
10
+ export interface ConfirmWorktreeClearedTx {
11
+ ships: Pick<ShipRepository, 'find' | 'findForUpdate'>;
12
+ clearRequests: ClearRequestRepository;
13
+ events: EventLog;
14
+ }
15
+ export type ConfirmWorktreeClearedUseCaseRefusal = DomainError<'SHIP_NOT_FOUND'> | ConfirmWorktreeClearedRefusal;
16
+ export type ConfirmWorktreeCleared = (caller: Caller, input: {
17
+ shipId: ShipId;
18
+ repository: string;
19
+ outcome: ClearOutcome;
20
+ }) => Promise<Result<undefined, ConfirmWorktreeClearedUseCaseRefusal>>;
21
+ /**
22
+ * Use case: a trierarch confirms a clear request to its own ship, saying it
23
+ * removed the worktree or kept none (decision 0032). Its scope (crew:run) is
24
+ * checked before this runs. In one unit of work, locking its ship first: the
25
+ * request goes, with WorktreeCleared.
26
+ */
27
+ export declare function createConfirmWorktreeCleared(deps: {
28
+ uow: UnitOfWork<ConfirmWorktreeClearedTx>;
29
+ clock: Clock;
30
+ ids: IdGenerator;
31
+ }): ConfirmWorktreeCleared;
@@ -0,0 +1,30 @@
1
+ import { refuse } from '../shared/errors.js';
2
+ import { recordEvent, shipActor } from '../shared/events.js';
3
+ import { ok } from '../shared/result.js';
4
+ import { confirmWorktreeCleared } from './clear-request.js';
5
+ /**
6
+ * Use case: a trierarch confirms a clear request to its own ship, saying it
7
+ * removed the worktree or kept none (decision 0032). Its scope (crew:run) is
8
+ * checked before this runs. In one unit of work, locking its ship first: the
9
+ * request goes, with WorktreeCleared.
10
+ */
11
+ export function createConfirmWorktreeCleared(deps) {
12
+ return (caller, input) => deps.uow.run(async (tx) => {
13
+ const { fleetId } = caller;
14
+ const trierarch = await tx.ships.findForUpdate(fleetId, caller.shipId);
15
+ if (!trierarch) {
16
+ return refuse('SHIP_NOT_FOUND', `Ship ${caller.shipId} does not exist`);
17
+ }
18
+ const key = { trierarchShipId: trierarch.id, shipId: input.shipId, repository: input.repository };
19
+ const confirmed = confirmWorktreeCleared({ trierarch, worktreeShipName: (await tx.ships.find(fleetId, input.shipId))?.name ?? input.shipId, current: await tx.clearRequests.find(fleetId, key) }, { repository: input.repository, outcome: input.outcome, at: deps.clock.now(), actor: shipActor(caller.shipId) });
20
+ if (!confirmed.isOk) {
21
+ return confirmed;
22
+ }
23
+ await tx.clearRequests.remove(fleetId, key);
24
+ for (const event of confirmed.value.events) {
25
+ await recordEvent({ events: tx.events, ids: deps.ids }, event);
26
+ }
27
+ return ok(undefined);
28
+ });
29
+ }
30
+ //# sourceMappingURL=confirm-worktree-cleared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm-worktree-cleared.js","sourceRoot":"","sources":["../../../src/domain/registry/confirm-worktree-cleared.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,sBAAsB,EAAsC,MAAM,oBAAoB,CAAC;AAgBhG;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAAmF;IAC9H,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAoE,EAAE;QAC1F,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACvE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,MAAM,CAAC,MAAM,iBAAiB,CAAC,CAAC;QAC1E,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,sBAAsB,CACtC,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,EACvJ,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,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,CAChH,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YACpB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC5C,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"}
@@ -28,6 +28,10 @@ export interface CrewRequest {
28
28
  status: CrewStatus | null;
29
29
  /** Why no trierarch can take it, written by the assigner while unassigned; null when none. */
30
30
  reason: string | null;
31
+ /** How many times its trierarch restarted the session within its restart window, written with the status: 0 on its first start (#332). */
32
+ attempt: number;
33
+ /** When the session its trierarch runs now started, written with the status; null while none runs. */
34
+ sessionStartedAt: Date | null;
31
35
  }
32
36
  type NotFound = DomainError<'CREW_REQUEST_NOT_FOUND'>;
33
37
  type Releasing = DomainError<'CREW_REQUEST_RELEASING'>;
@@ -105,9 +109,9 @@ export declare function explainCrewRequest({ ship, current }: {
105
109
  events: NewEvent[];
106
110
  }, ExplainCrewRequestRefusal>;
107
111
  /**
108
- * The assigned trierarch writes how its crew of the ship stands, with
109
- * CrewStatusChanged when it changes. Once the request is releasing, only
110
- * releasing.
112
+ * The assigned trierarch writes how its crew of the ship stands, with the
113
+ * restart attempt and when the session started (#332), and CrewStatusChanged
114
+ * when any of them changes. Once the request is releasing, only releasing.
111
115
  */
112
116
  export declare function reportCrewStatus({ ship, current, trierarchShipId }: {
113
117
  ship: Ship;
@@ -115,6 +119,8 @@ export declare function reportCrewStatus({ ship, current, trierarchShipId }: {
115
119
  trierarchShipId: ShipId;
116
120
  }, input: {
117
121
  status: CrewStatus;
122
+ attempt: number;
123
+ sessionStartedAt: Date | null;
118
124
  at: Date;
119
125
  actor: Actor;
120
126
  }): Result<{
@@ -38,6 +38,8 @@ export function requestCrew({ ship, current }, input) {
38
38
  assignedTo: current?.assignedTo ?? null,
39
39
  status: current?.status ?? null,
40
40
  reason: current?.reason ?? null,
41
+ attempt: current?.attempt ?? 0,
42
+ sessionStartedAt: current?.sessionStartedAt ?? null,
41
43
  };
42
44
  return ok({ request, events: [event(ship, { at: input.at, actor: input.actor, type: 'CrewRequested', details: { settingsVersion: request.settingsVersion } })] });
43
45
  }
@@ -119,9 +121,9 @@ function checkAssignedTo({ ship, current, trierarchShipId }) {
119
121
  : refuse('CREW_REQUEST_NOT_ASSIGNED_TO_CALLER', `${ship.name}'s crew request is not assigned to your ship`);
120
122
  }
121
123
  /**
122
- * The assigned trierarch writes how its crew of the ship stands, with
123
- * CrewStatusChanged when it changes. Once the request is releasing, only
124
- * releasing.
124
+ * The assigned trierarch writes how its crew of the ship stands, with the
125
+ * restart attempt and when the session started (#332), and CrewStatusChanged
126
+ * when any of them changes. Once the request is releasing, only releasing.
125
127
  */
126
128
  export function reportCrewStatus({ ship, current, trierarchShipId }, input) {
127
129
  if (!current) {
@@ -134,12 +136,13 @@ export function reportCrewStatus({ ship, current, trierarchShipId }, input) {
134
136
  if (current.status === 'releasing' && input.status !== 'releasing') {
135
137
  return refuse('CREW_REQUEST_RELEASING', `${ship.name}'s crew request is releasing: stop its session, end its lease and confirm`);
136
138
  }
137
- if (current.status === input.status) {
139
+ const isSameStart = (current.sessionStartedAt?.getTime() ?? null) === (input.sessionStartedAt?.getTime() ?? null);
140
+ if (current.status === input.status && current.attempt === input.attempt && isSameStart) {
138
141
  return ok({ request: current, events: [] });
139
142
  }
140
143
  return ok({
141
- request: { ...current, status: input.status },
142
- events: [event(ship, { at: input.at, actor: input.actor, type: 'CrewStatusChanged', details: { status: input.status } })],
144
+ request: { ...current, status: input.status, attempt: input.attempt, sessionStartedAt: input.sessionStartedAt },
145
+ events: [event(ship, { at: input.at, actor: input.actor, type: 'CrewStatusChanged', details: { status: input.status, attempt: input.attempt } })],
143
146
  });
144
147
  }
145
148
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"crew-request.js","sourceRoot":"","sources":["../../../src/domain/registry/crew-request.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crew-request.js","sourceRoot":"","sources":["../../../src/domain/registry/crew-request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { IdGenerator, LabelId } from '@aeolus-fleet/common';
2
+ import type { Caller } from '../shared/caller.js';
3
+ import type { Clock } from '../shared/clock.js';
4
+ import { type EventLog } from '../shared/events.js';
5
+ import { type Result } from '../shared/result.js';
6
+ import type { UnitOfWork } from '../shared/unit-of-work.js';
7
+ import { type DefineLabelRefusal, type LabelValue } from './label.js';
8
+ import type { LabelRepository, ShipRepository } from './ports.js';
9
+ export interface DefineLabelTx {
10
+ ships: Pick<ShipRepository, 'find'>;
11
+ labels: Pick<LabelRepository, 'lockKey' | 'findByKey' | 'save'>;
12
+ events: EventLog;
13
+ }
14
+ /** The new label's id, and its values with their ids. */
15
+ export interface DefinedLabel {
16
+ labelId: LabelId;
17
+ values: readonly LabelValue[];
18
+ }
19
+ export type DefineLabel = (caller: Caller, input: {
20
+ key: string;
21
+ values: readonly string[];
22
+ }) => Promise<Result<DefinedLabel, DefineLabelRefusal>>;
23
+ /**
24
+ * Use case: the caller's ship defines a label it then owns (decision 0031).
25
+ * Its scope (labels:define) is checked before this runs. In one unit of work,
26
+ * holding the key's lock so two definitions of one key never both find it
27
+ * free: the label, a new id for it and each of its values, and LabelDefined.
28
+ */
29
+ export declare function createDefineLabel(deps: {
30
+ uow: UnitOfWork<DefineLabelTx>;
31
+ clock: Clock;
32
+ ids: IdGenerator;
33
+ }): DefineLabel;
@@ -0,0 +1,33 @@
1
+ import { recordEvent, shipActor } from '../shared/events.js';
2
+ import { ok } from '../shared/result.js';
3
+ import { defineLabel } from './label.js';
4
+ /**
5
+ * Use case: the caller's ship defines a label it then owns (decision 0031).
6
+ * Its scope (labels:define) is checked before this runs. In one unit of work,
7
+ * holding the key's lock so two definitions of one key never both find it
8
+ * free: the label, a new id for it and each of its values, and LabelDefined.
9
+ */
10
+ export function createDefineLabel(deps) {
11
+ return (caller, input) => deps.uow.run(async (tx) => {
12
+ const { fleetId } = caller;
13
+ await tx.labels.lockKey(fleetId, input.key);
14
+ const label = await tx.labels.findByKey(fleetId, input.key);
15
+ const owner = label && (await tx.ships.find(fleetId, label.ownerShipId));
16
+ const defined = defineLabel({ owner: { fleetId, id: caller.shipId }, existing: label && { label, ownerName: owner?.name ?? label.ownerShipId } }, {
17
+ id: deps.ids('label'),
18
+ key: input.key,
19
+ values: input.values.map((value) => ({ value, newId: deps.ids('labelValue') })),
20
+ at: deps.clock.now(),
21
+ actor: shipActor(caller.shipId),
22
+ });
23
+ if (!defined.isOk) {
24
+ return defined;
25
+ }
26
+ await tx.labels.save(defined.value.label);
27
+ for (const event of defined.value.events) {
28
+ await recordEvent({ events: tx.events, ids: deps.ids }, event);
29
+ }
30
+ return ok({ labelId: defined.value.label.id, values: defined.value.label.values });
31
+ });
32
+ }
33
+ //# sourceMappingURL=define-label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-label.js","sourceRoot":"","sources":["../../../src/domain/registry/define-label.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAA4C,MAAM,YAAY,CAAC;AAiBnF;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAwE;IACxG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAqD,EAAE;QAC3E,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;QACzE,MAAM,OAAO,GAAG,WAAW,CACzB,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,EACpH;YACE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;YACrB,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC/E,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YACpB,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;SAChC,CACF,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1C,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACzC,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,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { IdGenerator, LabelId } 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 DeleteLabelRefusal } from './label.js';
9
+ import type { LabelRepository, ShipRepository } from './ports.js';
10
+ export interface DeleteLabelTx {
11
+ ships: Pick<ShipRepository, 'find'>;
12
+ labels: Pick<LabelRepository, 'findForUpdate' | 'carriersOf' | 'remove'>;
13
+ events: EventLog;
14
+ }
15
+ export type DeleteLabelFailure = DomainError<'LABEL_NOT_FOUND'> | DeleteLabelRefusal;
16
+ export type DeleteLabel = (caller: Caller, input: {
17
+ labelId: LabelId;
18
+ }) => Promise<Result<undefined, DeleteLabelFailure>>;
19
+ /**
20
+ * Use case: a label's owner deletes it, freeing its key (decision 0031). Its
21
+ * scope (labels:define) is checked before this runs. In one unit of work,
22
+ * locking the label first, as a change of values does, so an assignment
23
+ * either comes before and is seen here, or waits and finds the label gone:
24
+ * the label goes with its values, with LabelDeleted.
25
+ */
26
+ export declare function createDeleteLabel(deps: {
27
+ uow: UnitOfWork<DeleteLabelTx>;
28
+ clock: Clock;
29
+ ids: IdGenerator;
30
+ }): DeleteLabel;
@@ -0,0 +1,32 @@
1
+ import { refuse } from '../shared/errors.js';
2
+ import { recordEvent, shipActor } from '../shared/events.js';
3
+ import { ok } from '../shared/result.js';
4
+ import { deleteLabel } from './label.js';
5
+ /**
6
+ * Use case: a label's owner deletes it, freeing its key (decision 0031). Its
7
+ * scope (labels:define) is checked before this runs. In one unit of work,
8
+ * locking the label first, as a change of values does, so an assignment
9
+ * either comes before and is seen here, or waits and finds the label gone:
10
+ * the label goes with its values, with LabelDeleted.
11
+ */
12
+ export function createDeleteLabel(deps) {
13
+ return (caller, input) => deps.uow.run(async (tx) => {
14
+ const { fleetId } = caller;
15
+ const label = await tx.labels.findForUpdate(fleetId, input.labelId);
16
+ if (!label) {
17
+ return refuse('LABEL_NOT_FOUND', `The fleet has no label ${input.labelId}`);
18
+ }
19
+ const nameOf = async (shipId) => (await tx.ships.find(fleetId, shipId))?.name ?? shipId;
20
+ const carrierNames = await Promise.all((await tx.labels.carriersOf(fleetId, label.id)).map((carried) => nameOf(carried.shipId)));
21
+ const deleted = deleteLabel({ label, ownerName: await nameOf(label.ownerShipId), carrierNames }, { callerShipId: caller.shipId, at: deps.clock.now(), actor: shipActor(caller.shipId) });
22
+ if (!deleted.isOk) {
23
+ return deleted;
24
+ }
25
+ await tx.labels.remove(fleetId, label.id);
26
+ for (const event of deleted.value.events) {
27
+ await recordEvent({ events: tx.events, ids: deps.ids }, event);
28
+ }
29
+ return ok(undefined);
30
+ });
31
+ }
32
+ //# sourceMappingURL=delete-label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete-label.js","sourceRoot":"","sources":["../../../src/domain/registry/delete-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,WAAW,EAA2B,MAAM,YAAY,CAAC;AAalE;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAwE;IACxG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAkD,EAAE;QACxE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACpE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,MAAM,CAAC,iBAAiB,EAAE,0BAA0B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,EAAE,MAAwB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,EAAE,IAAI,IAAI,MAAM,CAAC;QAC1G,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACjI,MAAM,OAAO,GAAG,WAAW,CACzB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,YAAY,EAAE,EACnE,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CACvF,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1C,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACzC,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,22 @@
1
+ import type { LabelId, LabelValueId } from '@aeolus-fleet/common';
2
+ import type { Caller } from '../shared/caller.js';
3
+ import { type DomainError } from '../shared/errors.js';
4
+ import { type Result } from '../shared/result.js';
5
+ import type { FleetListing } from './ports.js';
6
+ export type FindLabelValue = (caller: Caller, input: {
7
+ key: string;
8
+ value: string;
9
+ }) => Promise<Result<{
10
+ labelId: LabelId;
11
+ valueId: LabelValueId;
12
+ }, DomainError<'LABEL_VALUE_NOT_FOUND'>>>;
13
+ /**
14
+ * Use case: the ids of a label and one of its values, by the texts people
15
+ * write, so a caller that knows `os=macos` can assign and select by id
16
+ * (decision 0031). Keys and values are lowercase, so both texts are
17
+ * lowercased, then matched exactly. The caller's scope (fleet:read) is
18
+ * checked before this runs.
19
+ */
20
+ export declare function createFindLabelValue(deps: {
21
+ listing: Pick<FleetListing, 'labels'>;
22
+ }): FindLabelValue;
@@ -0,0 +1,19 @@
1
+ import { refuse } from '../shared/errors.js';
2
+ import { ok } from '../shared/result.js';
3
+ /**
4
+ * Use case: the ids of a label and one of its values, by the texts people
5
+ * write, so a caller that knows `os=macos` can assign and select by id
6
+ * (decision 0031). Keys and values are lowercase, so both texts are
7
+ * lowercased, then matched exactly. The caller's scope (fleet:read) is
8
+ * checked before this runs.
9
+ */
10
+ export function createFindLabelValue(deps) {
11
+ return async (caller, input) => {
12
+ const key = input.key.toLowerCase();
13
+ const value = input.value.toLowerCase();
14
+ const label = (await deps.listing.labels(caller.fleetId)).find((listed) => listed.key === key);
15
+ const found = label?.values.find((held) => held.value === value);
16
+ return label && found ? ok({ labelId: label.id, valueId: found.id }) : refuse('LABEL_VALUE_NOT_FOUND', `The fleet has no label value ${input.key}=${input.value}`);
17
+ };
18
+ }
19
+ //# sourceMappingURL=find-label-value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-label-value.js","sourceRoot":"","sources":["../../../src/domain/registry/find-label-value.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAQtD;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAA+C;IAClF,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;QAC7B,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;QAC/F,MAAM,KAAK,GAAG,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QACjE,OAAO,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,uBAAuB,EAAE,gCAAgC,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACrK,CAAC,CAAC;AACJ,CAAC"}
@@ -25,7 +25,7 @@ export type GetShip = (caller: Caller, input: {
25
25
  }) => Promise<Result<ShipDetail, DomainError<'SHIP_NOT_FOUND' | 'CREW_REQUEST_NOT_ASSIGNED_TO_CALLER'>>>;
26
26
  /**
27
27
  * Use case: one ship of the caller's fleet, retired ships included: they keep
28
- * their page. The caller's scope (fleet:read, fleet:crew or crew:run) is
28
+ * their page. The caller's scope (fleet:read or crew:run) is
29
29
  * checked before this runs; crew:run reads only the ships whose crew requests
30
30
  * are assigned to the caller's ship.
31
31
  */
@@ -3,10 +3,10 @@ import { ok } from '../shared/result.js';
3
3
  import { listedShipOf } from './list-fleet.js';
4
4
  import { checkReaches } from './crew-request.js';
5
5
  /** The scopes that read every ship; crew:run reads only the ships assigned to the caller's ship. */
6
- const READ_SCOPES = ['fleet:read', 'fleet:crew'];
6
+ const READ_SCOPES = ['fleet:read'];
7
7
  /**
8
8
  * Use case: one ship of the caller's fleet, retired ships included: they keep
9
- * their page. The caller's scope (fleet:read, fleet:crew or crew:run) is
9
+ * their page. The caller's scope (fleet:read or crew:run) is
10
10
  * checked before this runs; crew:run reads only the ships whose crew requests
11
11
  * are assigned to the caller's ship.
12
12
  */
@@ -1 +1 @@
1
- {"version":3,"file":"get-ship.js","sourceRoot":"","sources":["../../../src/domain/registry/get-ship.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAmB,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAoB,MAAM,mBAAmB,CAAC;AAwBnE,oGAAoG;AACpG,MAAM,WAAW,GAAG,CAAC,YAAY,EAAE,YAAY,CAAU,CAAC;AAE1D;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAA+B;IAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAClC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,MAAM,CAAC,gBAAgB,EAAE,WAAW,MAAM,gBAAgB,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;QACjH,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACzE,OAAO,EAAE,CAAC;YACR,GAAG,MAAM;YACT,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,IAAI,IAAI;YACvC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,IAAI,EAAE,GAAG,MAAM,CAAC,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE;YACvH,kBAAkB,EAAE,MAAM,CAAC,QAAQ;YACnC,cAAc,EAAE,MAAM,CAAC,IAAI;YAC3B,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS;YACpC,WAAW,EAAE,KAAK,CAAC,SAAS,EAAE,SAAS,IAAI,IAAI;SAChD,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"get-ship.js","sourceRoot":"","sources":["../../../src/domain/registry/get-ship.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAmB,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAoB,MAAM,mBAAmB,CAAC;AAwBnE,oGAAoG;AACpG,MAAM,WAAW,GAAG,CAAC,YAAY,CAAU,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAA+B;IAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAClC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,MAAM,CAAC,gBAAgB,EAAE,WAAW,MAAM,gBAAgB,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;QACjH,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACzE,OAAO,EAAE,CAAC;YACR,GAAG,MAAM;YACT,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,IAAI,IAAI;YACvC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,IAAI,EAAE,GAAG,MAAM,CAAC,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE;YACvH,kBAAkB,EAAE,MAAM,CAAC,QAAQ;YACnC,cAAc,EAAE,MAAM,CAAC,IAAI;YAC3B,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS;YACpC,WAAW,EAAE,KAAK,CAAC,SAAS,EAAE,SAAS,IAAI,IAAI;SAChD,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -8,8 +8,8 @@ import { issueStartingPrompt } from './starting-prompt.js';
8
8
  /**
9
9
  * Use case: a new starting prompt for a ship of the caller's fleet that awaits
10
10
  * crew. Its new secret invalidates any earlier one, so at most one is valid; a
11
- * prompt lost before use costs nothing. The caller's scope (fleet:manage,
12
- * fleet:crew or crew:run) is checked before this runs; crew:run reaches only
11
+ * prompt lost before use costs nothing. The caller's scope (fleet:manage or
12
+ * crew:run) is checked before this runs; crew:run reaches only
13
13
  * the ships whose crew requests are assigned to the caller's ship.
14
14
  *
15
15
  * Locks in the fleet's order: the ship first, so concurrent prompts for one
@@ -19,7 +19,7 @@ import { issueStartingPrompt } from './starting-prompt.js';
19
19
  * back.
20
20
  */
21
21
  /** The scopes that reach every ship for a starting prompt; crew:run reaches only assigned ones. */
22
- const PROMPT_SCOPES = ['fleet:manage', 'fleet:crew'];
22
+ const PROMPT_SCOPES = ['fleet:manage'];
23
23
  export function createGetStartingPrompt(deps) {
24
24
  return (caller, { shipId }) => deps.uow.run(async (tx) => {
25
25
  const { fleetId } = caller;
@@ -1 +1 @@
1
- {"version":3,"file":"get-starting-prompt.js","sourceRoot":"","sources":["../../../src/domain/registry/get-starting-prompt.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAG3E,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,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAoD,MAAM,sBAAsB,CAAC;AAiB7G;;;;;;;;;;;;GAYG;AACH,mGAAmG;AACnG,MAAM,aAAa,GAAG,CAAC,cAAc,EAAE,YAAY,CAAU,CAAC;AAE9D,MAAM,UAAU,uBAAuB,CAAC,IAKvC;IACC,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAmE,EAAE;QACzF,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,aAAa,EAAE,CAAC,CAAC;QACjI,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;QAC5B,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,MAAM,OAAO,GAAG,2BAA2B,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC,CAAC;QACrF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EACnD,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAC/B,CAAC;QACF,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"get-starting-prompt.js","sourceRoot":"","sources":["../../../src/domain/registry/get-starting-prompt.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAG3E,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,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAoD,MAAM,sBAAsB,CAAC;AAiB7G;;;;;;;;;;;;GAYG;AACH,mGAAmG;AACnG,MAAM,aAAa,GAAG,CAAC,cAAc,CAAU,CAAC;AAEhD,MAAM,UAAU,uBAAuB,CAAC,IAKvC;IACC,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAmE,EAAE;QACzF,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,aAAa,EAAE,CAAC,CAAC;QACjI,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;QAC5B,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,MAAM,OAAO,GAAG,2BAA2B,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC,CAAC;QACrF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EACnD,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAC/B,CAAC;QACF,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;AACP,CAAC"}