@aeolus-fleet/core 0.26.1 → 0.27.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 (286) hide show
  1. package/README.md +1 -1
  2. package/dist/adapters/http/request-credentials.d.ts +2 -9
  3. package/dist/adapters/http/request-credentials.js +8 -1
  4. package/dist/adapters/http/request-credentials.js.map +1 -1
  5. package/dist/adapters/http/server.js +2 -1
  6. package/dist/adapters/http/server.js.map +1 -1
  7. package/dist/adapters/mcp/mcp-endpoint.js +11 -1
  8. package/dist/adapters/mcp/mcp-endpoint.js.map +1 -1
  9. package/dist/adapters/prisma/generated/browser.d.ts +8 -0
  10. package/dist/adapters/prisma/generated/client.d.ts +8 -0
  11. package/dist/adapters/prisma/generated/enums.d.ts +2 -0
  12. package/dist/adapters/prisma/generated/enums.js +3 -1
  13. package/dist/adapters/prisma/generated/enums.js.map +1 -1
  14. package/dist/adapters/prisma/generated/internal/class.d.ts +11 -0
  15. package/dist/adapters/prisma/generated/internal/class.js +4 -4
  16. package/dist/adapters/prisma/generated/internal/class.js.map +1 -1
  17. package/dist/adapters/prisma/generated/internal/prismaNamespace.d.ts +94 -1
  18. package/dist/adapters/prisma/generated/internal/prismaNamespace.js +18 -1
  19. package/dist/adapters/prisma/generated/internal/prismaNamespace.js.map +1 -1
  20. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.d.ts +18 -0
  21. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js +18 -1
  22. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  23. package/dist/adapters/prisma/generated/models/Delivery.d.ts +71 -1
  24. package/dist/adapters/prisma/generated/models/Fleet.d.ts +275 -0
  25. package/dist/adapters/prisma/generated/models/Lease.d.ts +113 -1
  26. package/dist/adapters/prisma/generated/models/NetworkSettings.d.ts +151 -19
  27. package/dist/adapters/prisma/generated/models/ReachRefusal.d.ts +71 -1
  28. package/dist/adapters/prisma/generated/models/ScopeNamespace.d.ts +1220 -0
  29. package/dist/adapters/prisma/generated/models/ScopeNamespace.js +2 -0
  30. package/dist/adapters/prisma/generated/models/ScopeNamespace.js.map +1 -0
  31. package/dist/adapters/prisma/generated/models/Ship.d.ts +983 -55
  32. package/dist/adapters/prisma/generated/models.d.ts +1 -0
  33. package/dist/adapters/prisma/health.js +27 -7
  34. package/dist/adapters/prisma/health.js.map +1 -1
  35. package/dist/adapters/prisma/history.js +14 -70
  36. package/dist/adapters/prisma/history.js.map +1 -1
  37. package/dist/adapters/prisma/messaging.js +27 -34
  38. package/dist/adapters/prisma/messaging.js.map +1 -1
  39. package/dist/adapters/prisma/network.js +39 -12
  40. package/dist/adapters/prisma/network.js.map +1 -1
  41. package/dist/adapters/prisma/registry.js +65 -11
  42. package/dist/adapters/prisma/registry.js.map +1 -1
  43. package/dist/adapters/prisma/rows.d.ts +3 -0
  44. package/dist/adapters/prisma/rows.js +20 -7
  45. package/dist/adapters/prisma/rows.js.map +1 -1
  46. package/dist/adapters/prisma/scope-namespaces.d.ts +4 -0
  47. package/dist/adapters/prisma/scope-namespaces.js +39 -0
  48. package/dist/adapters/prisma/scope-namespaces.js.map +1 -0
  49. package/dist/adapters/prisma/unit-of-work.d.ts +2 -1
  50. package/dist/adapters/prisma/unit-of-work.js +2 -0
  51. package/dist/adapters/prisma/unit-of-work.js.map +1 -1
  52. package/dist/adapters/rest/rest-api.js +2 -2
  53. package/dist/adapters/rest/rest-api.js.map +1 -1
  54. package/dist/adapters/trpc/console.d.ts +1 -1
  55. package/dist/adapters/trpc/console.js +6 -4
  56. package/dist/adapters/trpc/console.js.map +1 -1
  57. package/dist/adapters/trpc/context.d.ts +20 -4
  58. package/dist/adapters/trpc/fleet.d.ts +179 -82
  59. package/dist/adapters/trpc/fleet.js +117 -53
  60. package/dist/adapters/trpc/fleet.js.map +1 -1
  61. package/dist/adapters/trpc/router.d.ts +231 -80
  62. package/dist/adapters/trpc/ship-contract.js +4 -0
  63. package/dist/adapters/trpc/ship-contract.js.map +1 -1
  64. package/dist/adapters/trpc/ship-protocol.js +7 -5
  65. package/dist/adapters/trpc/ship-protocol.js.map +1 -1
  66. package/dist/adapters/trpc/ship.d.ts +71 -3
  67. package/dist/adapters/trpc/ship.js +42 -5
  68. package/dist/adapters/trpc/ship.js.map +1 -1
  69. package/dist/adapters/trpc/trpc.d.ts +6 -5
  70. package/dist/adapters/trpc/trpc.js +76 -21
  71. package/dist/adapters/trpc/trpc.js.map +1 -1
  72. package/dist/domain/messaging/check-inbox.d.ts +5 -5
  73. package/dist/domain/messaging/check-inbox.js +9 -7
  74. package/dist/domain/messaging/check-inbox.js.map +1 -1
  75. package/dist/domain/messaging/dismiss-delivery.d.ts +9 -4
  76. package/dist/domain/messaging/dismiss-delivery.js +26 -19
  77. package/dist/domain/messaging/dismiss-delivery.js.map +1 -1
  78. package/dist/domain/messaging/message.d.ts +11 -5
  79. package/dist/domain/messaging/message.js +11 -4
  80. package/dist/domain/messaging/message.js.map +1 -1
  81. package/dist/domain/messaging/ping-ship.d.ts +3 -3
  82. package/dist/domain/messaging/ping-ship.js +6 -2
  83. package/dist/domain/messaging/ping-ship.js.map +1 -1
  84. package/dist/domain/messaging/ports.d.ts +9 -3
  85. package/dist/domain/messaging/receive-deliveries.d.ts +2 -0
  86. package/dist/domain/messaging/receive-deliveries.js +1 -0
  87. package/dist/domain/messaging/receive-deliveries.js.map +1 -1
  88. package/dist/domain/messaging/resend-delivery.d.ts +5 -2
  89. package/dist/domain/messaging/resend-delivery.js +8 -4
  90. package/dist/domain/messaging/resend-delivery.js.map +1 -1
  91. package/dist/domain/messaging/send-message.d.ts +9 -2
  92. package/dist/domain/messaging/send-message.js +12 -2
  93. package/dist/domain/messaging/send-message.js.map +1 -1
  94. package/dist/domain/messaging/send-request.d.ts +3 -1
  95. package/dist/domain/messaging/send-request.js +4 -2
  96. package/dist/domain/messaging/send-request.js.map +1 -1
  97. package/dist/domain/registry/assign-label.d.ts +2 -1
  98. package/dist/domain/registry/assign-label.js +3 -2
  99. package/dist/domain/registry/assign-label.js.map +1 -1
  100. package/dist/domain/registry/check-reach.d.ts +63 -4
  101. package/dist/domain/registry/check-reach.js +107 -11
  102. package/dist/domain/registry/check-reach.js.map +1 -1
  103. package/dist/domain/registry/commission-ship.d.ts +17 -8
  104. package/dist/domain/registry/commission-ship.js +24 -10
  105. package/dist/domain/registry/commission-ship.js.map +1 -1
  106. package/dist/domain/registry/crew-request.d.ts +1 -1
  107. package/dist/domain/registry/declare-scopes.d.ts +38 -0
  108. package/dist/domain/registry/declare-scopes.js +34 -0
  109. package/dist/domain/registry/declare-scopes.js.map +1 -0
  110. package/dist/domain/registry/declared-network-rules.d.ts +2 -1
  111. package/dist/domain/registry/declared-network-rules.js +11 -5
  112. package/dist/domain/registry/declared-network-rules.js.map +1 -1
  113. package/dist/domain/registry/discover.d.ts +28 -0
  114. package/dist/domain/registry/discover.js +54 -0
  115. package/dist/domain/registry/discover.js.map +1 -0
  116. package/dist/domain/registry/explain-reach.d.ts +12 -12
  117. package/dist/domain/registry/explain-reach.js +35 -12
  118. package/dist/domain/registry/explain-reach.js.map +1 -1
  119. package/dist/domain/registry/get-ship.d.ts +11 -3
  120. package/dist/domain/registry/get-ship.js +8 -2
  121. package/dist/domain/registry/get-ship.js.map +1 -1
  122. package/dist/domain/registry/get-starting-prompt.d.ts +18 -2
  123. package/dist/domain/registry/get-starting-prompt.js +7 -7
  124. package/dist/domain/registry/get-starting-prompt.js.map +1 -1
  125. package/dist/domain/registry/grant-scopes.d.ts +34 -0
  126. package/dist/domain/registry/grant-scopes.js +35 -0
  127. package/dist/domain/registry/grant-scopes.js.map +1 -0
  128. package/dist/domain/registry/label.d.ts +12 -7
  129. package/dist/domain/registry/label.js +21 -4
  130. package/dist/domain/registry/label.js.map +1 -1
  131. package/dist/domain/registry/list-fleet.d.ts +19 -6
  132. package/dist/domain/registry/list-fleet.js +18 -3
  133. package/dist/domain/registry/list-fleet.js.map +1 -1
  134. package/dist/domain/registry/list-scopes.d.ts +24 -0
  135. package/dist/domain/registry/list-scopes.js +22 -0
  136. package/dist/domain/registry/list-scopes.js.map +1 -0
  137. package/dist/domain/registry/managed-or-assigned.d.ts +25 -0
  138. package/dist/domain/registry/managed-or-assigned.js +23 -0
  139. package/dist/domain/registry/managed-or-assigned.js.map +1 -0
  140. package/dist/domain/registry/named-namespaces.d.ts +19 -0
  141. package/dist/domain/registry/named-namespaces.js +19 -0
  142. package/dist/domain/registry/named-namespaces.js.map +1 -0
  143. package/dist/domain/registry/network-settings.d.ts +84 -24
  144. package/dist/domain/registry/network-settings.js +134 -45
  145. package/dist/domain/registry/network-settings.js.map +1 -1
  146. package/dist/domain/registry/ports.d.ts +63 -1
  147. package/dist/domain/registry/public.d.ts +3 -2
  148. package/dist/domain/registry/public.js +3 -2
  149. package/dist/domain/registry/public.js.map +1 -1
  150. package/dist/domain/registry/reach-refusal.d.ts +12 -4
  151. package/dist/domain/registry/read-assigned-crew-requests.d.ts +12 -3
  152. package/dist/domain/registry/read-assigned-crew-requests.js +8 -8
  153. package/dist/domain/registry/read-assigned-crew-requests.js.map +1 -1
  154. package/dist/domain/registry/read-built-in-rules.d.ts +20 -0
  155. package/dist/domain/registry/read-built-in-rules.js +23 -0
  156. package/dist/domain/registry/read-built-in-rules.js.map +1 -0
  157. package/dist/domain/registry/read-clear-requests.d.ts +5 -3
  158. package/dist/domain/registry/read-clear-requests.js +7 -5
  159. package/dist/domain/registry/read-clear-requests.js.map +1 -1
  160. package/dist/domain/registry/read-on-behalf.d.ts +20 -0
  161. package/dist/domain/registry/read-on-behalf.js +31 -0
  162. package/dist/domain/registry/read-on-behalf.js.map +1 -0
  163. package/dist/domain/registry/read-reach.d.ts +62 -0
  164. package/dist/domain/registry/read-reach.js +78 -0
  165. package/dist/domain/registry/read-reach.js.map +1 -0
  166. package/dist/domain/registry/recrew-ship.d.ts +3 -2
  167. package/dist/domain/registry/recrew-ship.js +6 -1
  168. package/dist/domain/registry/recrew-ship.js.map +1 -1
  169. package/dist/domain/registry/release-ship.d.ts +6 -3
  170. package/dist/domain/registry/release-ship.js +7 -7
  171. package/dist/domain/registry/release-ship.js.map +1 -1
  172. package/dist/domain/registry/remove-crew-request.d.ts +4 -3
  173. package/dist/domain/registry/remove-crew-request.js +6 -1
  174. package/dist/domain/registry/remove-crew-request.js.map +1 -1
  175. package/dist/domain/registry/rename-ship.d.ts +7 -5
  176. package/dist/domain/registry/rename-ship.js +9 -3
  177. package/dist/domain/registry/rename-ship.js.map +1 -1
  178. package/dist/domain/registry/request-crew.d.ts +5 -4
  179. package/dist/domain/registry/request-crew.js +6 -1
  180. package/dist/domain/registry/request-crew.js.map +1 -1
  181. package/dist/domain/registry/request-worktree-clear.d.ts +3 -2
  182. package/dist/domain/registry/request-worktree-clear.js +6 -1
  183. package/dist/domain/registry/request-worktree-clear.js.map +1 -1
  184. package/dist/domain/registry/retire-ship.d.ts +16 -7
  185. package/dist/domain/registry/retire-ship.js +46 -5
  186. package/dist/domain/registry/retire-ship.js.map +1 -1
  187. package/dist/domain/registry/scope-grant.d.ts +53 -0
  188. package/dist/domain/registry/scope-grant.js +74 -0
  189. package/dist/domain/registry/scope-grant.js.map +1 -0
  190. package/dist/domain/registry/scope-namespace.d.ts +68 -0
  191. package/dist/domain/registry/scope-namespace.js +82 -0
  192. package/dist/domain/registry/scope-namespace.js.map +1 -0
  193. package/dist/domain/registry/set-built-in-rule.d.ts +28 -0
  194. package/dist/domain/registry/set-built-in-rule.js +33 -0
  195. package/dist/domain/registry/set-built-in-rule.js.map +1 -0
  196. package/dist/domain/registry/set-network-rules.d.ts +3 -3
  197. package/dist/domain/registry/set-network-rules.js +2 -2
  198. package/dist/domain/registry/set-owner.d.ts +30 -0
  199. package/dist/domain/registry/set-owner.js +37 -0
  200. package/dist/domain/registry/set-owner.js.map +1 -0
  201. package/dist/domain/registry/set-statement.d.ts +27 -0
  202. package/dist/domain/registry/set-statement.js +28 -0
  203. package/dist/domain/registry/set-statement.js.map +1 -0
  204. package/dist/domain/registry/ship.d.ts +70 -10
  205. package/dist/domain/registry/ship.js +95 -10
  206. package/dist/domain/registry/ship.js.map +1 -1
  207. package/dist/domain/registry/statement.d.ts +32 -0
  208. package/dist/domain/registry/statement.js +39 -0
  209. package/dist/domain/registry/statement.js.map +1 -0
  210. package/dist/domain/registry/unassign-label.js +1 -1
  211. package/dist/domain/registry/unassign-label.js.map +1 -1
  212. package/dist/domain/registry/whoami.d.ts +5 -1
  213. package/dist/domain/registry/whoami.js +7 -4
  214. package/dist/domain/registry/whoami.js.map +1 -1
  215. package/dist/domain/shared/caller.d.ts +5 -2
  216. package/dist/domain/shared/caller.js.map +1 -1
  217. package/dist/domain/shared/errors.d.ts +1 -1
  218. package/dist/domain/shared/errors.js.map +1 -1
  219. package/dist/domain/shared/events-read.d.ts +16 -0
  220. package/dist/domain/shared/events-read.js +15 -0
  221. package/dist/domain/shared/events-read.js.map +1 -0
  222. package/dist/domain/shared/follow-fleet.d.ts +8 -2
  223. package/dist/domain/shared/follow-fleet.js +14 -4
  224. package/dist/domain/shared/follow-fleet.js.map +1 -1
  225. package/dist/domain/shared/health.d.ts +9 -2
  226. package/dist/domain/shared/health.js +9 -3
  227. package/dist/domain/shared/health.js.map +1 -1
  228. package/dist/domain/shared/history.d.ts +9 -42
  229. package/dist/domain/shared/history.js +9 -0
  230. package/dist/domain/shared/history.js.map +1 -1
  231. package/dist/domain/shared/read-fleet-events.d.ts +8 -2
  232. package/dist/domain/shared/read-fleet-events.js +10 -4
  233. package/dist/domain/shared/read-fleet-events.js.map +1 -1
  234. package/dist/domain/shared/read-health.d.ts +4 -1
  235. package/dist/domain/shared/read-health.js +7 -2
  236. package/dist/domain/shared/read-health.js.map +1 -1
  237. package/dist/domain/shared/read-inbox.d.ts +6 -3
  238. package/dist/domain/shared/read-inbox.js +14 -4
  239. package/dist/domain/shared/read-inbox.js.map +1 -1
  240. package/dist/domain/shared/read-message.d.ts +6 -2
  241. package/dist/domain/shared/read-message.js +6 -2
  242. package/dist/domain/shared/read-message.js.map +1 -1
  243. package/dist/domain/shared/read-needs-attention.d.ts +4 -1
  244. package/dist/domain/shared/read-needs-attention.js +8 -3
  245. package/dist/domain/shared/read-needs-attention.js.map +1 -1
  246. package/dist/domain/shared/read-ship-messages.d.ts +6 -2
  247. package/dist/domain/shared/read-ship-messages.js +7 -2
  248. package/dist/domain/shared/read-ship-messages.js.map +1 -1
  249. package/dist/domain/shared/read-ship-timeline.d.ts +5 -2
  250. package/dist/domain/shared/read-ship-timeline.js +11 -6
  251. package/dist/domain/shared/read-ship-timeline.js.map +1 -1
  252. package/dist/domain/shared/read-ship-way.d.ts +11 -4
  253. package/dist/domain/shared/read-ship-way.js +9 -2
  254. package/dist/domain/shared/read-ship-way.js.map +1 -1
  255. package/dist/domain/shared/stuck.d.ts +10 -1
  256. package/dist/domain/shared/stuck.js +1 -1
  257. package/dist/domain/shared/stuck.js.map +1 -1
  258. package/dist/wiring.d.ts +18 -4
  259. package/dist/wiring.js +37 -18
  260. package/dist/wiring.js.map +1 -1
  261. package/package.json +2 -2
  262. package/src/adapters/prisma/migrations/20261018100000_force_scope/migration.sql +8 -0
  263. package/src/adapters/prisma/migrations/20261018110000_forced_delivery/migration.sql +4 -0
  264. package/src/adapters/prisma/migrations/20261018120000_person_and_app_ships/migration.sql +3 -0
  265. package/src/adapters/prisma/migrations/20261018130000_owners/migration.sql +14 -0
  266. package/src/adapters/prisma/migrations/20261018140000_owners_on_reach_refusals/migration.sql +14 -0
  267. package/src/adapters/prisma/migrations/20261018150000_network_verbs/migration.sql +9 -0
  268. package/src/adapters/prisma/migrations/20261018160000_built_in_rules/migration.sql +13 -0
  269. package/src/adapters/prisma/migrations/20261018170000_network_rules_a_list/migration.sql +5 -0
  270. package/src/adapters/prisma/migrations/20261018180000_verb_on_reach_refusals/migration.sql +4 -0
  271. package/src/adapters/prisma/migrations/20261018200000_lease_statements/migration.sql +3 -0
  272. package/src/adapters/prisma/migrations/20261018210000_declare_and_grant_scopes/migration.sql +8 -0
  273. package/src/adapters/prisma/migrations/20261018220000_plugin_scopes/migration.sql +14 -0
  274. package/src/adapters/prisma/migrations/20261018230000_scope_namespaces/migration.sql +20 -0
  275. package/src/adapters/prisma/migrations/20261018240000_trierarch_plugin_crew_run/migration.sql +44 -0
  276. package/src/adapters/prisma/migrations/20261018250000_scope_catalogue/migration.sql +66 -0
  277. package/src/adapters/prisma/migrations/20261019090000_reach_refusal_asked_by/migration.sql +2 -0
  278. package/src/adapters/prisma/migrations/20261019100000_on_behalf_scope/migration.sql +59 -0
  279. package/src/adapters/prisma/migrations/20261019110000_events_fleet_id_occurred_at/migration.sql +2 -0
  280. package/src/adapters/prisma/schema.prisma +47 -2
  281. package/dist/domain/shared/read-no-ship-can-take.d.ts +0 -13
  282. package/dist/domain/shared/read-no-ship-can-take.js +0 -12
  283. package/dist/domain/shared/read-no-ship-can-take.js.map +0 -1
  284. package/dist/domain/shared/read-overdue.d.ts +0 -13
  285. package/dist/domain/shared/read-overdue.js +0 -12
  286. package/dist/domain/shared/read-overdue.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"declared-network-rules.js","sourceRoot":"","sources":["../../../src/domain/registry/declared-network-rules.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"declared-network-rules.js","sourceRoot":"","sources":["../../../src/domain/registry/declared-network-rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { Discovered } from '@aeolus-fleet/common';
2
+ import type { Caller } from '../shared/caller.js';
3
+ import type { Clock } from '../shared/clock.js';
4
+ import { type Result } from '../shared/result.js';
5
+ import type { UnitOfWork } from '../shared/unit-of-work.js';
6
+ import { type CheckReachTx } from './check-reach.js';
7
+ import type { LeaseRepository, ShipRepository } from './ports.js';
8
+ export interface DiscoverTx {
9
+ networkSettings: CheckReachTx['networkSettings'];
10
+ ships: Pick<ShipRepository, 'find' | 'listActive'>;
11
+ labels: CheckReachTx['labels'];
12
+ leases: Pick<LeaseRepository, 'findLastSeen' | 'listOpenStatements'>;
13
+ }
14
+ export type Discover = (caller: Caller) => Promise<Result<Discovered, never>>;
15
+ /**
16
+ * Use case: a ship asks which ships and types it may send to now (decision
17
+ * 0047), its scope (messages:send) checked before this runs. Each active
18
+ * ship but the caller and the viewer is checked as a send to it would be at
19
+ * this moment (decision 0034): the rules in force, what the networking plugin
20
+ * declared while it does not respond, the built-in rules; there is no message,
21
+ * so no answer to a sender. Each reached ship comes with its name, type, kind,
22
+ * status and statement, and each type with how many of its ships it reaches.
23
+ * Ships, never rules; it records nothing, a refusal included.
24
+ */
25
+ export declare function createDiscover(deps: {
26
+ uow: UnitOfWork<DiscoverTx>;
27
+ clock: Clock;
28
+ }): Discover;
@@ -0,0 +1,54 @@
1
+ import { ok } from '../shared/result.js';
2
+ import { reaching, rulesInForceAt, shipAsItIs } from './check-reach.js';
3
+ import { allowsReach } from './network-settings.js';
4
+ import { discoveredStatementOf } from './statement.js';
5
+ /**
6
+ * Use case: a ship asks which ships and types it may send to now (decision
7
+ * 0047), its scope (messages:send) checked before this runs. Each active
8
+ * ship but the caller and the viewer is checked as a send to it would be at
9
+ * this moment (decision 0034): the rules in force, what the networking plugin
10
+ * declared while it does not respond, the built-in rules; there is no message,
11
+ * so no answer to a sender. Each reached ship comes with its name, type, kind,
12
+ * status and statement, and each type with how many of its ships it reaches.
13
+ * Ships, never rules; it records nothing, a refusal included.
14
+ */
15
+ export function createDiscover(deps) {
16
+ return (caller) => deps.uow.run(async (tx) => {
17
+ const { fleetId } = caller;
18
+ const settings = await tx.networkSettings.findForShare(fleetId);
19
+ const inForce = await rulesInForceAt(tx, { settings, now: deps.clock.now() });
20
+ const active = await tx.ships.listActive(fleetId);
21
+ const callerShip = active.find((ship) => ship.id === caller.shipId);
22
+ const sender = callerShip === undefined ? undefined : reaching(await shipAsItIs(tx, callerShip));
23
+ const crews = new Map((await tx.leases.listOpenStatements(fleetId)).map(({ shipId, stated }) => [shipId, stated]));
24
+ const ships = [];
25
+ for (const ship of active) {
26
+ if (ship.id === caller.shipId || ship.kind === 'viewer' || sender === undefined) {
27
+ continue;
28
+ }
29
+ const recipient = reaching(await shipAsItIs(tx, ship));
30
+ if (!allowsReach(inForce, { verb: 'send', sender, recipient, isAnswerToSender: false })) {
31
+ continue;
32
+ }
33
+ const isCrewed = ship.kind === 'operator' || crews.has(ship.id);
34
+ ships.push({
35
+ id: ship.id,
36
+ name: ship.name,
37
+ type: ship.type,
38
+ kind: ship.kind,
39
+ status: isCrewed ? 'crewed' : 'awaitingCrew',
40
+ statement: discoveredStatementOf(ship, crews.get(ship.id) ?? null),
41
+ });
42
+ }
43
+ return ok({ ships, types: typesOf(ships) });
44
+ });
45
+ }
46
+ /** Each type of the reached ships with how many of them, in the order the ships come. */
47
+ function typesOf(ships) {
48
+ const counts = new Map();
49
+ for (const ship of ships) {
50
+ counts.set(ship.type, (counts.get(ship.type) ?? 0) + 1);
51
+ }
52
+ return [...counts].map(([type, reachable]) => ({ type, reachable }));
53
+ }
54
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../../src/domain/registry/discover.ts"],"names":[],"mappings":"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"}
@@ -1,32 +1,32 @@
1
- import type { ShipId } from '@aeolus-fleet/common';
1
+ import { type ExplainedReach, type ShipId } from '@aeolus-fleet/common';
2
2
  import type { Caller } from '../shared/caller.js';
3
3
  import type { Clock } from '../shared/clock.js';
4
4
  import { type DomainError } from '../shared/errors.js';
5
5
  import { type Result } from '../shared/result.js';
6
6
  import type { UnitOfWork } from '../shared/unit-of-work.js';
7
7
  import { type CheckReachTx } from './check-reach.js';
8
- import type { ShipRepository } from './ports.js';
8
+ import type { DeclaredNetworkRulesRepository, ShipRepository } from './ports.js';
9
9
  export interface ExplainReachTx {
10
10
  networkSettings: CheckReachTx['networkSettings'];
11
11
  ships: Pick<ShipRepository, 'find' | 'listActive'>;
12
12
  labels: CheckReachTx['labels'];
13
13
  leases: CheckReachTx['leases'];
14
+ declaredNetworkRules: Pick<DeclaredNetworkRulesRepository, 'list'>;
14
15
  }
15
16
  export type ExplainReachFailure = DomainError<'NOT_THE_OPERATOR_SHIP' | 'SHIP_NOT_FOUND'>;
16
17
  export type ExplainReach = (caller: Caller, input: {
17
18
  fromShipId: ShipId;
18
19
  toShipId?: ShipId;
19
- }) => Promise<Result<{
20
- reachableShipIds: ShipId[];
21
- }, ExplainReachFailure>>;
20
+ }) => Promise<Result<ExplainedReach, ExplainReachFailure>>;
22
21
  /**
23
- * Use case: argo asks which ships a ship reaches now, or whether it reaches
24
- * one ship (design points 11 and 12 on #260). It answers as a send would be
25
- * checked at this moment: the rules in force, what the networking plugin
26
- * declared while it does not respond, argo both ways. There is no message, so
27
- * no answer to a sender. It answers the ships, never the rules or the reasons,
28
- * and records nothing: an explain is not a send. Only argo; the viewer ship
29
- * receives nothing, so it is never reached.
22
+ * Use case: argo asks which ships a ship reaches now, per verb, or whether it
23
+ * reaches one ship (decision 0034). It answers as a send would be checked at
24
+ * this moment: the rules in force, what the networking plugin declared while
25
+ * it does not respond, the built-in rules. Each ship comes with the rule that
26
+ * allows it: a built-in rule, a rule the plugin supplied, or a rule a ship
27
+ * declared, named by its declarer, when the plugin supplied it as declared.
28
+ * There is no message, so no answer to a sender. It records nothing: an
29
+ * explain is not a send. Only argo.
30
30
  */
31
31
  export declare function createExplainReach(deps: {
32
32
  uow: UnitOfWork<ExplainReachTx>;
@@ -1,15 +1,17 @@
1
+ import { NETWORK_VERBS } from '@aeolus-fleet/common';
1
2
  import { refuse } from '../shared/errors.js';
2
3
  import { ok } from '../shared/result.js';
3
4
  import { reaching, rulesInForceAt, shipAsItIs } from './check-reach.js';
4
- import { allowsReach } from './network-settings.js';
5
+ import { reachRuleOf } from './network-settings.js';
5
6
  /**
6
- * Use case: argo asks which ships a ship reaches now, or whether it reaches
7
- * one ship (design points 11 and 12 on #260). It answers as a send would be
8
- * checked at this moment: the rules in force, what the networking plugin
9
- * declared while it does not respond, argo both ways. There is no message, so
10
- * no answer to a sender. It answers the ships, never the rules or the reasons,
11
- * and records nothing: an explain is not a send. Only argo; the viewer ship
12
- * receives nothing, so it is never reached.
7
+ * Use case: argo asks which ships a ship reaches now, per verb, or whether it
8
+ * reaches one ship (decision 0034). It answers as a send would be checked at
9
+ * this moment: the rules in force, what the networking plugin declared while
10
+ * it does not respond, the built-in rules. Each ship comes with the rule that
11
+ * allows it: a built-in rule, a rule the plugin supplied, or a rule a ship
12
+ * declared, named by its declarer, when the plugin supplied it as declared.
13
+ * There is no message, so no answer to a sender. It records nothing: an
14
+ * explain is not a send. Only argo.
13
15
  */
14
16
  export function createExplainReach(deps) {
15
17
  return (caller, input) => deps.uow.run(async (tx) => {
@@ -28,15 +30,36 @@ export function createExplainReach(deps) {
28
30
  }
29
31
  const settings = await tx.networkSettings.findForShare(fleetId);
30
32
  const inForce = await rulesInForceAt(tx, { settings, now: deps.clock.now() });
33
+ const declared = await tx.declaredNetworkRules.list(fleetId);
31
34
  const sender = reaching(await shipAsItIs(tx, from));
32
- const reachableShipIds = [];
35
+ const explained = { send: [], read: [], manage: [] };
33
36
  for (const ship of others) {
34
37
  const recipient = reaching(await shipAsItIs(tx, ship));
35
- if (allowsReach(inForce, { sender, recipient, isAnswerToSender: false })) {
36
- reachableShipIds.push(ship.id);
38
+ for (const verb of NETWORK_VERBS) {
39
+ const rule = reachRuleOf(inForce, { verb, sender, recipient, isAnswerToSender: false });
40
+ if (rule !== undefined) {
41
+ explained[verb].push({ shipId: ship.id, rule: namedRule(rule, { rules: inForce.rules, declared }) });
42
+ }
37
43
  }
38
44
  }
39
- return ok({ reachableShipIds });
45
+ return ok(explained);
40
46
  });
41
47
  }
48
+ /** A rule of the settings named as argo reads it: a declared one by its declarer and its place in that ship's list, any other as the plugin's. */
49
+ function namedRule(rule, held) {
50
+ if ('builtIn' in rule) {
51
+ return rule;
52
+ }
53
+ const text = ruleText(held.rules[rule.index]);
54
+ for (const { shipId, rules } of held.declared) {
55
+ const index = rules.findIndex((each) => ruleText(each) === text);
56
+ if (index !== -1) {
57
+ return { declared: shipId, index };
58
+ }
59
+ }
60
+ return { plugin: rule.index };
61
+ }
62
+ function ruleText(rule) {
63
+ return JSON.stringify(rule === undefined ? null : [rule.verb, rule.from, rule.to]);
64
+ }
42
65
  //# sourceMappingURL=explain-reach.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"explain-reach.js","sourceRoot":"","sources":["../../../src/domain/registry/explain-reach.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAqB,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAiBpD;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAuD;IACxF,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAwE,EAAE;QAC9F,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC/B,OAAO,MAAM,CAAC,uBAAuB,EAAE,0BAA0B,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAC5D,IAAI,IAAI,EAAE,SAAS,KAAK,IAAI,EAAE,CAAC;YAC7B,OAAO,MAAM,CAAC,gBAAgB,EAAE,2DAA2D,CAAC,CAAC;QAC/F,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5H,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;YACtF,OAAO,MAAM,CAAC,gBAAgB,EAAE,+DAA+D,CAAC,CAAC;QACnG,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,eAAe,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC9E,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;QACpD,MAAM,gBAAgB,GAAa,EAAE,CAAC;QACtC,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;YAC1B,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;YACvD,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;gBACzE,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QACD,OAAO,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"explain-reach.js","sourceRoot":"","sources":["../../../src/domain/registry/explain-reach.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,8 @@ import type { ShipId } from '@aeolus-fleet/common';
2
2
  import type { Caller } from '../shared/caller.js';
3
3
  import { type DomainError } from '../shared/errors.js';
4
4
  import { type Result } from '../shared/result.js';
5
- import { type ListedShip } from './list-fleet.js';
5
+ import { type ListedShip, type ShipOutsideReadReach } from './list-fleet.js';
6
+ import { type ReadReachOf } from './read-reach.js';
6
7
  import { type CrewRequest } from './crew-request.js';
7
8
  import type { FleetListing } from './ports.js';
8
9
  import { type ShownReport } from './ship-report.js';
@@ -19,16 +20,23 @@ export interface ShipDetail extends Omit<ListedShip, 'report' | 'crewRequest'> {
19
20
  inFlightDeliveries: number;
20
21
  /** Its direct deliveries pending or in flight: what a retire abandons. */
21
22
  openDeliveries: number;
23
+ /** Its owner by id and name; null for argo and the viewer (decision 0045). */
24
+ owner: {
25
+ id: ShipId;
26
+ name: string;
27
+ } | null;
22
28
  }
23
29
  export type GetShip = (caller: Caller, input: {
24
30
  shipId: ShipId;
25
- }) => Promise<Result<ShipDetail, DomainError<'SHIP_NOT_FOUND' | 'CREW_REQUEST_NOT_ASSIGNED_TO_CALLER'>>>;
31
+ }) => Promise<Result<ShipDetail | ShipOutsideReadReach, DomainError<'SHIP_NOT_FOUND' | 'CREW_REQUEST_NOT_ASSIGNED_TO_CALLER'>>>;
26
32
  /**
27
33
  * Use case: one ship of the caller's fleet, retired ships included: they keep
28
34
  * their page. The caller's scope (fleet:read or crew:run) is
29
35
  * checked before this runs; crew:run reads only the ships whose crew requests
30
- * are assigned to the caller's ship.
36
+ * are assigned to the caller's ship, whole. Any other ship outside the
37
+ * caller's read reach shows its name, type and status only (decision 0034).
31
38
  */
32
39
  export declare function createGetShip(deps: {
33
40
  listing: FleetListing;
41
+ readReach: ReadReachOf;
34
42
  }): GetShip;
@@ -1,6 +1,7 @@
1
1
  import { refuse } from '../shared/errors.js';
2
2
  import { ok } from '../shared/result.js';
3
- import { listedShipOf } from './list-fleet.js';
3
+ import { listedShipOf, outsideReadReach } from './list-fleet.js';
4
+ import { readsShip } from './read-reach.js';
4
5
  import { checkReaches } from './crew-request.js';
5
6
  import { shownReportOf } from './ship-report.js';
6
7
  /** The scopes that read every ship; crew:run reads only the ships assigned to the caller's ship. */
@@ -9,7 +10,8 @@ const READ_SCOPES = ['fleet:read'];
9
10
  * Use case: one ship of the caller's fleet, retired ships included: they keep
10
11
  * their page. The caller's scope (fleet:read or crew:run) is
11
12
  * checked before this runs; crew:run reads only the ships whose crew requests
12
- * are assigned to the caller's ship.
13
+ * are assigned to the caller's ship, whole. Any other ship outside the
14
+ * caller's read reach shows its name, type and status only (decision 0034).
13
15
  */
14
16
  export function createGetShip(deps) {
15
17
  return async (caller, { shipId }) => {
@@ -22,6 +24,9 @@ export function createGetShip(deps) {
22
24
  return reaches;
23
25
  }
24
26
  const listed = listedShipOf(facts);
27
+ if (facts.crewRequest?.assignedTo !== caller.shipId && !readsShip(await deps.readReach(caller), shipId)) {
28
+ return ok(outsideReadReach(listed));
29
+ }
25
30
  const counts = await deps.listing.deliveryCounts(caller.fleetId, shipId);
26
31
  return ok({
27
32
  ...listed,
@@ -31,6 +36,7 @@ export function createGetShip(deps) {
31
36
  openDeliveries: counts.open,
32
37
  commissionedAt: facts.ship.createdAt,
33
38
  crewedSince: facts.openLease?.startedAt ?? null,
39
+ owner: facts.owner,
34
40
  });
35
41
  };
36
42
  }
@@ -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;AAEnE,OAAO,EAAE,aAAa,EAAoB,MAAM,kBAAkB,CAAC;AAsBnE,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,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI;YAC9E,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,EAAE,gBAAgB,EAA8C,MAAM,iBAAiB,CAAC;AAC7G,OAAO,EAAE,SAAS,EAAoB,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAoB,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAoB,MAAM,kBAAkB,CAAC;AAwBnE,oGAAoG;AACpG,MAAM,WAAW,GAAG,CAAC,YAAY,CAAU,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAuD;IACnF,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,IAAI,KAAK,CAAC,WAAW,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC;YACxG,OAAO,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;QACtC,CAAC;QACD,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,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI;YAC9E,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;YAC/C,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -5,17 +5,33 @@ import type { Clock } from '../shared/clock.js';
5
5
  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
+ import { type NotReachable } from './check-reach.js';
9
+ import { type ManagedOrAssignedTx } from './managed-or-assigned.js';
8
10
  import type { CrewRequestRepository, LeaseRepository, ShipRepository } from './ports.js';
9
11
  import { type IssuedStartingPrompt, type StartingPromptTx } from './starting-prompt.js';
10
- export interface GetStartingPromptTx extends StartingPromptTx {
12
+ export interface GetStartingPromptTx extends StartingPromptTx, Omit<ManagedOrAssignedTx, 'ships' | 'leases' | 'crewRequests'> {
11
13
  ships: ShipRepository;
12
14
  leases: LeaseRepository;
13
15
  crewRequests: Pick<CrewRequestRepository, 'find'>;
14
16
  }
15
- export type GetStartingPromptRefusal = DomainError<'SHIP_NOT_FOUND' | 'OPERATOR_SHIP_GETS_NO_STARTING_PROMPT' | 'SHIP_NOT_AWAITING_CREW' | 'CREW_REQUEST_NOT_ASSIGNED_TO_CALLER'>;
17
+ export type GetStartingPromptRefusal = DomainError<'SHIP_NOT_FOUND' | 'OPERATOR_SHIP_GETS_NO_STARTING_PROMPT' | 'SHIP_NOT_AWAITING_CREW' | 'CREW_REQUEST_NOT_ASSIGNED_TO_CALLER'> | NotReachable;
16
18
  export type GetStartingPrompt = (caller: Caller, input: {
17
19
  shipId: ShipId;
18
20
  }) => Promise<Result<IssuedStartingPrompt, GetStartingPromptRefusal>>;
21
+ /**
22
+ * Use case: a new starting prompt for a ship of the caller's fleet that awaits
23
+ * crew. Its new secret invalidates any earlier one, so at most one is valid; a
24
+ * prompt lost before use costs nothing. The caller's scope (fleet:manage or
25
+ * crew:run) is checked before this runs; crew:run reaches only
26
+ * the ships whose crew requests are assigned to the caller's ship, and
27
+ * fleet:manage the ships in its manage reach (decision 0034).
28
+ *
29
+ * Locks in the fleet's order: the ship first, so concurrent prompts for one
30
+ * ship take turns and the last one issued is the valid one; then its secret;
31
+ * then its lease. The lease is read last, so a session that claimed the ship
32
+ * with the old secret meanwhile is seen, and the refusal rolls the revocation
33
+ * back.
34
+ */
19
35
  export declare function createGetStartingPrompt(deps: {
20
36
  uow: UnitOfWork<GetStartingPromptTx>;
21
37
  clock: Clock;
@@ -2,7 +2,8 @@ import { revokeShipSecret } from '../identity/public.js';
2
2
  import { refuse } from '../shared/errors.js';
3
3
  import { shipActor } from '../shared/events.js';
4
4
  import { ok } from '../shared/result.js';
5
- import { checkReaches } from './crew-request.js';
5
+ import { keepingReachRefusal } from './check-reach.js';
6
+ import { checkManagedOrAssigned } from './managed-or-assigned.js';
6
7
  import { checkCanIssueStartingPrompt } from './ship.js';
7
8
  import { issueStartingPrompt } from './starting-prompt.js';
8
9
  /**
@@ -10,7 +11,8 @@ import { issueStartingPrompt } from './starting-prompt.js';
10
11
  * crew. Its new secret invalidates any earlier one, so at most one is valid; a
11
12
  * prompt lost before use costs nothing. The caller's scope (fleet:manage or
12
13
  * crew:run) is checked before this runs; crew:run reaches only
13
- * the ships whose crew requests are assigned to the caller's ship.
14
+ * the ships whose crew requests are assigned to the caller's ship, and
15
+ * fleet:manage the ships in its manage reach (decision 0034).
14
16
  *
15
17
  * Locks in the fleet's order: the ship first, so concurrent prompts for one
16
18
  * ship take turns and the last one issued is the valid one; then its secret;
@@ -18,21 +20,19 @@ import { issueStartingPrompt } from './starting-prompt.js';
18
20
  * with the old secret meanwhile is seen, and the refusal rolls the revocation
19
21
  * back.
20
22
  */
21
- /** The scopes that reach every ship for a starting prompt; crew:run reaches only assigned ones. */
22
- const PROMPT_SCOPES = ['fleet:manage'];
23
23
  export function createGetStartingPrompt(deps) {
24
- return (caller, { shipId }) => deps.uow.run(async (tx) => {
24
+ return (caller, { shipId }) => keepingReachRefusal(deps.uow, async (tx) => {
25
25
  const { fleetId } = caller;
26
26
  const ship = await tx.ships.findForUpdate(fleetId, shipId);
27
27
  if (!ship) {
28
28
  return refuse('SHIP_NOT_FOUND', `Ship ${shipId} does not exist`);
29
29
  }
30
- const reaches = checkReaches(caller, { ship, current: await tx.crewRequests.find(fleetId, shipId), broadScopes: PROMPT_SCOPES });
30
+ const at = deps.clock.now();
31
+ const reaches = await checkManagedOrAssigned({ tx, ids: deps.ids }, { caller, ship, at });
31
32
  if (!reaches.isOk) {
32
33
  return reaches;
33
34
  }
34
35
  const actor = shipActor(caller.shipId);
35
- const at = deps.clock.now();
36
36
  await revokeShipSecret({ tx, ids: deps.ids }, { fleetId, shipId, actor, at });
37
37
  const lease = await tx.leases.findOpenForUpdate(fleetId, shipId);
38
38
  const allowed = checkCanIssueStartingPrompt(ship, { isCrewed: lease !== undefined });
@@ -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,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"}
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,mBAAmB,EAAqB,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAA4B,MAAM,0BAA0B,CAAC;AAE5F,OAAO,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAoD,MAAM,sBAAsB,CAAC;AAiB7G;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAKvC;IACC,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAC5B,mBAAmB,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,EAAmE,EAAE;QAC1G,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,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAC1F,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,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"}
@@ -0,0 +1,34 @@
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 { ScopeNamespaceRepository, ShipRepository } from './ports.js';
9
+ import { type GrantScopesRefusal } from './scope-grant.js';
10
+ export interface GrantScopesTx {
11
+ ships: Pick<ShipRepository, 'find' | 'findForUpdate' | 'setScopes'>;
12
+ scopeNamespaces: Pick<ScopeNamespaceRepository, 'lockNamespace' | 'find'>;
13
+ events: EventLog;
14
+ }
15
+ export type GrantScopes = (caller: Caller, input: {
16
+ shipId: ShipId;
17
+ grant: readonly string[];
18
+ revoke: readonly string[];
19
+ }) => Promise<Result<{
20
+ scopes: readonly string[];
21
+ }, GrantScopesRefusal | DomainError<'SHIP_NOT_FOUND'>>>;
22
+ /**
23
+ * Use case: the caller grants and revokes scopes on a live ship of its fleet
24
+ * (decision 0046), within what its ship may grant, read from the server.
25
+ * Its scope (scopes:grant) is checked before this runs. In one unit of work,
26
+ * holding the ship, then each plugin namespace the scopes name, so a
27
+ * declaration that removes a scope waits: the ship's scopes and
28
+ * ScopesChanged. The ship's crew holds them from its next call.
29
+ */
30
+ export declare function createGrantScopes(deps: {
31
+ uow: UnitOfWork<GrantScopesTx>;
32
+ clock: Clock;
33
+ ids: IdGenerator;
34
+ }): GrantScopes;
@@ -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 { grantScopes } from './scope-grant.js';
5
+ import { lockNamedNamespaces } from './named-namespaces.js';
6
+ /**
7
+ * Use case: the caller grants and revokes scopes on a live ship of its fleet
8
+ * (decision 0046), within what its ship may grant, read from the server.
9
+ * Its scope (scopes:grant) is checked before this runs. In one unit of work,
10
+ * holding the ship, then each plugin namespace the scopes name, so a
11
+ * declaration that removes a scope waits: the ship's scopes and
12
+ * ScopesChanged. The ship's crew holds them from its next call.
13
+ */
14
+ export function createGrantScopes(deps) {
15
+ return (caller, input) => deps.uow.run(async (tx) => {
16
+ const { fleetId } = caller;
17
+ const ship = await tx.ships.findForUpdate(fleetId, input.shipId);
18
+ if (!ship) {
19
+ return refuse('SHIP_NOT_FOUND', `Ship ${input.shipId} does not exist`);
20
+ }
21
+ const namespaces = await lockNamedNamespaces(tx, { fleetId, scopes: [...input.grant, ...input.revoke] });
22
+ const granted = grantScopes({ ship, granter: caller, grant: input.grant, revoke: input.revoke, at: deps.clock.now(), actor: shipActor(caller.shipId) }, { namespaces });
23
+ if (!granted.isOk) {
24
+ return granted;
25
+ }
26
+ if (granted.value.events.length > 0) {
27
+ await tx.ships.setScopes({ fleetId, shipId: ship.id, scopes: granted.value.ship.scopes });
28
+ }
29
+ for (const event of granted.value.events) {
30
+ await recordEvent({ events: tx.events, ids: deps.ids }, event);
31
+ }
32
+ return ok({ scopes: granted.value.ship.scopes });
33
+ });
34
+ }
35
+ //# sourceMappingURL=grant-scopes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grant-scopes.js","sourceRoot":"","sources":["../../../src/domain/registry/grant-scopes.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;AAGtD,OAAO,EAAE,WAAW,EAA2B,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAa5D;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAwE;IACxG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAsG,EAAE;QAC5H,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,UAAU,GAAG,MAAM,mBAAmB,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACzG,MAAM,OAAO,GAAG,WAAW,CACzB,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,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,EAC1H,EAAE,UAAU,EAAE,CACf,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,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,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -1,4 +1,4 @@
1
- import { type FleetId, type LabelId, type LabelValueId, type ShipId } from '@aeolus-fleet/common';
1
+ import { type FleetId, type LabelId, type LabelValueId, type ShipId, type ShipKind } from '@aeolus-fleet/common';
2
2
  import { type DomainError } from '../shared/errors.js';
3
3
  import type { Actor, NewEvent } from '../shared/events.js';
4
4
  import { type Result } from '../shared/result.js';
@@ -128,13 +128,15 @@ export declare function deleteLabel({ label, ownerName, carrierNames }: {
128
128
  }): Result<{
129
129
  events: NewEvent[];
130
130
  }, DeleteLabelRefusal>;
131
- export type AssignLabelRefusal = NotTheOwner | DomainError<'SHIP_ALREADY_RETIRED' | 'SHIP_LABEL_LIMIT_REACHED'>;
131
+ /** A ship the caller may not label: neither its own nor one it commissioned, and the caller is not argo. */
132
+ export type NotYourShipToLabel = DomainError<'NOT_YOUR_SHIP_TO_LABEL'>;
133
+ export type AssignLabelRefusal = NotTheOwner | NotYourShipToLabel | DomainError<'SHIP_ALREADY_RETIRED' | 'SHIP_LABEL_LIMIT_REACHED'>;
132
134
  /**
133
135
  * The owner gives a ship one of its label's values, by its id: the ship
134
136
  * holds a set of values, so it may carry several of one label. A value it
135
- * carries changes nothing. Any ship, the owner's own included, but never a
136
- * retired ship; argo and the viewer ship as any other (decision 0016). A ship
137
- * carries at most 20 values. LabelAssigned names the ship, with the label and the value.
137
+ * carries changes nothing. Its own ship and the ships it commissioned, argo
138
+ * any ship (decision 0046), but never a retired ship. A ship carries at most
139
+ * 20 values. LabelAssigned names the ship, with the label and the value.
138
140
  */
139
141
  export declare function assignLabel({ label, ownerName, ship, carried, }: {
140
142
  label: Label;
@@ -143,6 +145,7 @@ export declare function assignLabel({ label, ownerName, ship, carried, }: {
143
145
  carried: readonly ShipLabel[];
144
146
  }, input: {
145
147
  callerShipId: ShipId;
148
+ callerKind: ShipKind;
146
149
  valueId: LabelValueId;
147
150
  at: Date;
148
151
  actor: Actor;
@@ -150,18 +153,20 @@ export declare function assignLabel({ label, ownerName, ship, carried, }: {
150
153
  assignment: ShipLabel | undefined;
151
154
  events: NewEvent[];
152
155
  }, AssignLabelRefusal>;
153
- export type UnassignLabelRefusal = NotTheOwner;
156
+ export type UnassignLabelRefusal = NotTheOwner | NotYourShipToLabel;
154
157
  /**
155
158
  * The owner takes one value of its label off a ship. A ship that does not
156
159
  * carry it changes nothing. LabelUnassigned names the ship, with the label
157
160
  * and the value it carried.
158
161
  */
159
- export declare function unassignLabel({ label, ownerName, carried, }: {
162
+ export declare function unassignLabel({ label, ownerName, ship, carried, }: {
160
163
  label: Label;
161
164
  ownerName: string;
165
+ ship: Ship;
162
166
  carried: readonly ShipLabel[];
163
167
  }, input: {
164
168
  callerShipId: ShipId;
169
+ callerKind: ShipKind;
165
170
  valueId: LabelValueId;
166
171
  at: Date;
167
172
  actor: Actor;
@@ -173,18 +173,31 @@ function assignmentEvent({ label, assignment }, change) {
173
173
  },
174
174
  };
175
175
  }
176
+ /**
177
+ * Whether the caller may put values on the ship or take them off (decision
178
+ * 0046): its own ship and the ships it commissioned; argo any ship.
179
+ */
180
+ function checkMayLabel(ship, caller) {
181
+ return caller.kind === 'operator' || ship.id === caller.shipId || ship.commission?.by === caller.shipId
182
+ ? ok(undefined)
183
+ : refuse('NOT_YOUR_SHIP_TO_LABEL', `${ship.name} is neither your ship nor one it commissioned: only argo labels it`);
184
+ }
176
185
  /**
177
186
  * The owner gives a ship one of its label's values, by its id: the ship
178
187
  * holds a set of values, so it may carry several of one label. A value it
179
- * carries changes nothing. Any ship, the owner's own included, but never a
180
- * retired ship; argo and the viewer ship as any other (decision 0016). A ship
181
- * carries at most 20 values. LabelAssigned names the ship, with the label and the value.
188
+ * carries changes nothing. Its own ship and the ships it commissioned, argo
189
+ * any ship (decision 0046), but never a retired ship. A ship carries at most
190
+ * 20 values. LabelAssigned names the ship, with the label and the value.
182
191
  */
183
192
  export function assignLabel({ label, ownerName, ship, carried, }, input) {
184
193
  const owned = checkOwner({ label, ownerName }, { shipId: input.callerShipId, act: 'assigns' });
185
194
  if (!owned.isOk) {
186
195
  return owned;
187
196
  }
197
+ const mayLabel = checkMayLabel(ship, { shipId: input.callerShipId, kind: input.callerKind });
198
+ if (!mayLabel.isOk) {
199
+ return mayLabel;
200
+ }
188
201
  if (ship.retiredAt !== null) {
189
202
  return refuse('SHIP_ALREADY_RETIRED', `${ship.name} is retired`);
190
203
  }
@@ -210,11 +223,15 @@ export function assignLabel({ label, ownerName, ship, carried, }, input) {
210
223
  * carry it changes nothing. LabelUnassigned names the ship, with the label
211
224
  * and the value it carried.
212
225
  */
213
- export function unassignLabel({ label, ownerName, carried, }, input) {
226
+ export function unassignLabel({ label, ownerName, ship, carried, }, input) {
214
227
  const owned = checkOwner({ label, ownerName }, { shipId: input.callerShipId, act: 'unassigns' });
215
228
  if (!owned.isOk) {
216
229
  return owned;
217
230
  }
231
+ const mayLabel = checkMayLabel(ship, { shipId: input.callerShipId, kind: input.callerKind });
232
+ if (!mayLabel.isOk) {
233
+ return mayLabel;
234
+ }
218
235
  const current = carried.find((each) => each.valueId === input.valueId);
219
236
  if (!current) {
220
237
  return ok({ unassigned: undefined, events: [] });