@aeolus-fleet/core 0.26.0 → 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
@@ -2,6 +2,7 @@ import { refuse } from '../shared/errors.js';
2
2
  import { recordEvent, shipActor } from '../shared/events.js';
3
3
  import { ok } from '../shared/result.js';
4
4
  import { requestWorktreeClear } from './clear-request.js';
5
+ import { checkManage, keepingReachRefusal } from './check-reach.js';
5
6
  /**
6
7
  * Use case: the caller asks a trierarch to clear the worktree it kept for a
7
8
  * ship in a repository (decision 0032). Its scope (fleet:manage) is checked
@@ -9,7 +10,7 @@ import { requestWorktreeClear } from './clear-request.js';
9
10
  * two requests never both pass its limit: the request and its event.
10
11
  */
11
12
  export function createRequestWorktreeClear(deps) {
12
- return (caller, input) => deps.uow.run(async (tx) => {
13
+ return (caller, input) => keepingReachRefusal(deps.uow, async (tx) => {
13
14
  const { fleetId } = caller;
14
15
  const trierarch = await tx.ships.findForUpdate(fleetId, input.trierarchShipId);
15
16
  if (!trierarch) {
@@ -18,6 +19,10 @@ export function createRequestWorktreeClear(deps) {
18
19
  if (!(await tx.ships.find(fleetId, input.shipId))) {
19
20
  return refuse('SHIP_NOT_FOUND', `Ship ${input.shipId} does not exist`);
20
21
  }
22
+ const managed = await checkManage({ tx, ids: deps.ids }, { fleetId: fleetId, managerShipId: caller.shipId, shipId: input.shipId, at: deps.clock.now() });
23
+ if (!managed.isOk) {
24
+ return managed;
25
+ }
21
26
  const key = { trierarchShipId: trierarch.id, shipId: input.shipId, repository: input.repository };
22
27
  const requested = requestWorktreeClear({ trierarch, current: await tx.clearRequests.find(fleetId, key), pending: (await tx.clearRequests.listFor(fleetId, trierarch.id)).length }, { shipId: input.shipId, repository: input.repository, requestedBy: caller.shipId, at: deps.clock.now(), actor: shipActor(caller.shipId) });
23
28
  if (!requested.isOk) {
@@ -1 +1 @@
1
- {"version":3,"file":"request-worktree-clear.js","sourceRoot":"","sources":["../../../src/domain/registry/request-worktree-clear.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,oBAAoB,EAAoC,MAAM,oBAAoB,CAAC;AAgB5F;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAAiF;IAC1H,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAkE,EAAE;QACxF,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;QAC/E,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,KAAK,CAAC,eAAe,iBAAiB,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YAClD,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,KAAK,CAAC,MAAM,iBAAiB,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,GAAG,GAAG,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;QAClG,MAAM,SAAS,GAAG,oBAAoB,CACpC,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,EAC1I,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAC1I,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YACpB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC5B,MAAM,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvD,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"request-worktree-clear.js","sourceRoot":"","sources":["../../../src/domain/registry/request-worktree-clear.ts"],"names":[],"mappings":"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"}
@@ -5,18 +5,20 @@ 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 CheckManageTx, type NotReachable } from './check-reach.js';
8
9
  import { type LeaseTx } from './leases.js';
9
- import type { ClearRequestRepository, CrewRequestRepository, DeclaredNetworkRulesRepository, LabelRepository, NetworkSettingsRepository, ShipRepository } from './ports.js';
10
+ import type { ClearRequestRepository, CrewRequestRepository, DeclaredNetworkRulesRepository, LabelRepository, NetworkSettingsRepository, ScopeNamespaceRepository, ShipRepository } from './ports.js';
10
11
  import { type RetireRefusal } from './ship.js';
11
- export interface RetireShipTx extends LeaseTx, CredentialTx {
12
+ export interface RetireShipTx extends LeaseTx, CredentialTx, Omit<CheckManageTx, 'ships' | 'leases' | 'labels' | 'networkSettings'> {
12
13
  ships: ShipRepository;
13
14
  crewRequests: CrewRequestRepository;
14
15
  clearRequests: ClearRequestRepository;
15
16
  labels: LabelRepository;
16
- networkSettings: Pick<NetworkSettingsRepository, 'findForUpdate' | 'save'>;
17
+ networkSettings: Pick<NetworkSettingsRepository, 'find' | 'findForShare' | 'findForUpdate' | 'save'>;
17
18
  declaredNetworkRules: Pick<DeclaredNetworkRulesRepository, 'find' | 'save'>;
19
+ scopeNamespaces: Pick<ScopeNamespaceRepository, 'findByDeclarer' | 'lockNamespace' | 'remove'>;
18
20
  }
19
- export type RetireShipRefusal = DomainError<'SHIP_NOT_FOUND'> | RetireRefusal;
21
+ export type RetireShipRefusal = DomainError<'SHIP_NOT_FOUND'> | NotReachable | RetireRefusal;
20
22
  export type RetireShip = (caller: Caller, input: {
21
23
  shipId: ShipId;
22
24
  }) => Promise<Result<{
@@ -36,9 +38,16 @@ export type RetireShip = (caller: Caller, input: {
36
38
  * assignment of it gone first (decision 0031). A retired trierarch clears
37
39
  * nothing: its pending clear requests go, one WorktreeClearRemoved each
38
40
  * (decision 0032). The network rules it declared go with its labels
39
- * (decision 0037). A retired networking plugin unregisters, its rules going
40
- * with it: all-to-all (decision 0035). The caller's scope (fleet:manage) is
41
- * checked before this runs.
41
+ * (decision 0037). Each active ship it owned falls to argo, one
42
+ * OwnerChanged each, locked after the ship as a set owner locks the owner
43
+ * first (decision 0045). A retired networking plugin unregisters, its rules going
44
+ * with it: all-to-all (decision 0035). A plugin namespace it declared goes,
45
+ * and its scopes leave every ship, one ScopesChanged each (decision 0046).
46
+ * The caller's scope (fleet:manage) is
47
+ * checked before this runs, and manage reach on the ship here (decision
48
+ * 0034), a refusal storing only its record. That check reads the network
49
+ * settings without a lock: retire takes them exclusively later, after the
50
+ * ships it owns, and a shared hold taken first would deadlock two retires.
42
51
  *
43
52
  * It locks the ship first, as a release does (FOR NO KEY UPDATE). A send to
44
53
  * the ship holds it FOR SHARE while it resolves the selector, so the two
@@ -2,13 +2,15 @@ import { revokeShipSecret } from '../identity/public.js';
2
2
  import { refuse } from '../shared/errors.js';
3
3
  import { recordEvent, shipActor } from '../shared/events.js';
4
4
  import { ok } from '../shared/result.js';
5
+ import { checkManage, keepingReachRefusal } from './check-reach.js';
5
6
  import { removeClearRequestsOf } from './clear-request.js';
6
7
  import { removeCrewRequest } from './crew-request.js';
7
8
  import { retireLabelsWith } from './label.js';
8
9
  import { endLease } from './leases.js';
9
10
  import { withdrawWithRetiredShip } from './declared-network-rules.js';
10
11
  import { unregisterNetworkPlugin } from './network-settings.js';
11
- import { checkCanRetire } from './ship.js';
12
+ import { changeOwner, checkCanRetire } from './ship.js';
13
+ import { releaseWithDeclarer } from './scope-namespace.js';
12
14
  /**
13
15
  * Use case: the caller retires a ship of its fleet for good (Retire): any ship
14
16
  * but argo, crewed or not. In one unit of work: its secret stops working; a
@@ -23,9 +25,16 @@ import { checkCanRetire } from './ship.js';
23
25
  * assignment of it gone first (decision 0031). A retired trierarch clears
24
26
  * nothing: its pending clear requests go, one WorktreeClearRemoved each
25
27
  * (decision 0032). The network rules it declared go with its labels
26
- * (decision 0037). A retired networking plugin unregisters, its rules going
27
- * with it: all-to-all (decision 0035). The caller's scope (fleet:manage) is
28
- * checked before this runs.
28
+ * (decision 0037). Each active ship it owned falls to argo, one
29
+ * OwnerChanged each, locked after the ship as a set owner locks the owner
30
+ * first (decision 0045). A retired networking plugin unregisters, its rules going
31
+ * with it: all-to-all (decision 0035). A plugin namespace it declared goes,
32
+ * and its scopes leave every ship, one ScopesChanged each (decision 0046).
33
+ * The caller's scope (fleet:manage) is
34
+ * checked before this runs, and manage reach on the ship here (decision
35
+ * 0034), a refusal storing only its record. That check reads the network
36
+ * settings without a lock: retire takes them exclusively later, after the
37
+ * ships it owns, and a shared hold taken first would deadlock two retires.
29
38
  *
30
39
  * It locks the ship first, as a release does (FOR NO KEY UPDATE). A send to
31
40
  * the ship holds it FOR SHARE while it resolves the selector, so the two
@@ -34,12 +43,16 @@ import { checkCanRetire } from './ship.js';
34
43
  * network settings exclusively, after the ship as every send takes them.
35
44
  */
36
45
  export function createRetireShip(deps) {
37
- return (caller, { shipId }) => deps.uow.run(async (tx) => {
46
+ return (caller, { shipId }) => keepingReachRefusal(deps.uow, async (tx) => {
38
47
  const { fleetId } = caller;
39
48
  const ship = await tx.ships.findForUpdate(fleetId, shipId);
40
49
  if (!ship) {
41
50
  return refuse('SHIP_NOT_FOUND', `Ship ${shipId} does not exist`);
42
51
  }
52
+ const managed = await checkManage({ tx, ids: deps.ids }, { fleetId, managerShipId: caller.shipId, shipId, at: deps.clock.now(), settings: await tx.networkSettings.find(fleetId) });
53
+ if (!managed.isOk) {
54
+ return managed;
55
+ }
43
56
  const retirable = checkCanRetire(ship);
44
57
  if (!retirable.isOk) {
45
58
  return retirable;
@@ -65,6 +78,17 @@ export function createRetireShip(deps) {
65
78
  for (const { deliveryId, messageId } of abandoned) {
66
79
  await recordEvent(recorded, { fleetId, type: 'DeliveryAbandoned', occurredAt: at, actor, shipId, messageId, deliveryId });
67
80
  }
81
+ const argo = await tx.ships.findOperatorShip(fleetId);
82
+ for (const ownedShip of await tx.ships.listActiveOwnedByForUpdate(fleetId, shipId)) {
83
+ // Never refused: an owned ship is active and never argo's own, and argo is always active.
84
+ const changed = changeOwner(ownedShip, { owner: argo, why: 'ownerRetired', at, actor });
85
+ if (changed.isOk && changed.value.ship.owner !== null && changed.value.ship.owner !== ownedShip.owner) {
86
+ await tx.ships.setOwner({ fleetId, shipId: ownedShip.id, ownerShipId: changed.value.ship.owner });
87
+ for (const event of changed.value.events) {
88
+ await recordEvent(recorded, event);
89
+ }
90
+ }
91
+ }
68
92
  // A ship without a crew request has none to remove: nothing to do.
69
93
  const removed = removeCrewRequest({ ship, current: await tx.crewRequests.find(fleetId, shipId) }, { at, actor });
70
94
  if (removed.isOk) {
@@ -107,6 +131,23 @@ export function createRetireShip(deps) {
107
131
  await recordEvent(recorded, event);
108
132
  }
109
133
  }
134
+ const declared = await tx.scopeNamespaces.findByDeclarer(fleetId, shipId);
135
+ if (declared !== undefined) {
136
+ // The holders first, as every grant locks its ship before the
137
+ // namespace; then the namespace, so no grant of its scopes commits
138
+ // in between; then the holders again: a grant that did commit before
139
+ // the namespace lock holds no lock any more.
140
+ await tx.ships.listActiveHoldingInForUpdate(fleetId, declared.namespace);
141
+ await tx.scopeNamespaces.lockNamespace(fleetId, declared.namespace);
142
+ const released = releaseWithDeclarer(declared, { holders: await tx.ships.listActiveHoldingInForUpdate(fleetId, declared.namespace), at, actor });
143
+ for (const changed of released.ships) {
144
+ await tx.ships.setScopes({ fleetId, shipId: changed.id, scopes: changed.scopes });
145
+ }
146
+ await tx.scopeNamespaces.remove(fleetId, declared.namespace);
147
+ for (const event of released.events) {
148
+ await recordEvent(recorded, event);
149
+ }
150
+ }
110
151
  return ok({ abandonedDeliveries: abandoned.length });
111
152
  });
112
153
  }
@@ -1 +1 @@
1
- {"version":3,"file":"retire-ship.js","sourceRoot":"","sources":["../../../src/domain/registry/retire-ship.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"retire-ship.js","sourceRoot":"","sources":["../../../src/domain/registry/retire-ship.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { type ScopeName, type ShipId, type ShipKind } from '@aeolus-fleet/common';
2
+ import { type DomainError } from '../shared/errors.js';
3
+ import type { Actor, NewEvent } from '../shared/events.js';
4
+ import { type Result } from '../shared/result.js';
5
+ import type { ScopeNamespace } from './scope-namespace.js';
6
+ import type { Ship } from './ship.js';
7
+ export type GrantScopesRefusal = DomainError<'INVALID_SCOPE' | 'BASE_SCOPE' | 'SCOPE_NOT_DECLARED' | 'SCOPE_NOT_HELD' | 'PLUGIN_SCOPE_NOT_YOURS' | 'SHIP_SCOPES_FIXED' | 'OWN_SHIP_SCOPES' | 'SHIP_ALREADY_RETIRED'>;
8
+ /**
9
+ * A granter grants and revokes scopes on a live ship (decision 0046), each
10
+ * within what it may grant: a core scope it holds (argo holds every one), or
11
+ * a declared scope of a plugin namespace when it is argo or that namespace's
12
+ * declarer. Revoking follows the same rule. Refused: a malformed or unknown
13
+ * scope, one both granted and revoked, revoking sending or receiving, argo's
14
+ * and the viewer's scopes, the granter's own ship and a retired ship. Writes
15
+ * ScopesChanged when anything changes.
16
+ */
17
+ export declare function grantScopes(input: {
18
+ ship: Ship;
19
+ granter: {
20
+ shipId: ShipId;
21
+ kind: ShipKind;
22
+ scopes: readonly ScopeName[];
23
+ };
24
+ grant: readonly string[];
25
+ revoke: readonly string[];
26
+ at: Date;
27
+ actor: Actor;
28
+ }, fleet: {
29
+ /** The plugin namespaces the granted and revoked scopes name, with their declarers' names, by namespace. */
30
+ namespaces: ReadonlyMap<string, {
31
+ namespace: ScopeNamespace;
32
+ declarerName: string;
33
+ }>;
34
+ }): Result<{
35
+ ship: Ship;
36
+ events: NewEvent[];
37
+ }, GrantScopesRefusal>;
38
+ /**
39
+ * Whether the granter may grant or revoke the scope, at commission or on a
40
+ * live ship: a core scope it holds, or a declared plugin scope when it is
41
+ * argo or the declarer.
42
+ */
43
+ export declare function mayGrant(scope: string, at: {
44
+ granter: {
45
+ shipId: ShipId;
46
+ kind: ShipKind;
47
+ scopes: readonly ScopeName[];
48
+ };
49
+ namespaces: ReadonlyMap<string, {
50
+ namespace: ScopeNamespace;
51
+ declarerName: string;
52
+ }>;
53
+ }): Result<null, DomainError<'INVALID_SCOPE' | 'SCOPE_NOT_DECLARED' | 'SCOPE_NOT_HELD' | 'PLUGIN_SCOPE_NOT_YOURS'>>;
@@ -0,0 +1,74 @@
1
+ import { scopeNameSchema, scopeSchema } from '@aeolus-fleet/common';
2
+ import { refuse } from '../shared/errors.js';
3
+ import { ok } from '../shared/result.js';
4
+ /** The scopes every agent, person and app ship holds: never revoked (decision 0046). */
5
+ const BASE_SCOPES = ['messages:send', 'messages:receive'];
6
+ /**
7
+ * A granter grants and revokes scopes on a live ship (decision 0046), each
8
+ * within what it may grant: a core scope it holds (argo holds every one), or
9
+ * a declared scope of a plugin namespace when it is argo or that namespace's
10
+ * declarer. Revoking follows the same rule. Refused: a malformed or unknown
11
+ * scope, one both granted and revoked, revoking sending or receiving, argo's
12
+ * and the viewer's scopes, the granter's own ship and a retired ship. Writes
13
+ * ScopesChanged when anything changes.
14
+ */
15
+ export function grantScopes(input, fleet) {
16
+ const { ship, granter, at, actor } = input;
17
+ if (ship.kind === 'operator' || ship.kind === 'viewer') {
18
+ return refuse('SHIP_SCOPES_FIXED', `${ship.name}'s scopes are its own: argo holds every scope and the viewer reads`);
19
+ }
20
+ if (ship.id === granter.shipId) {
21
+ return refuse('OWN_SHIP_SCOPES', 'A ship never changes its own scopes');
22
+ }
23
+ if (ship.retiredAt !== null) {
24
+ return refuse('SHIP_ALREADY_RETIRED', `${ship.name} is retired: its scopes stay as they were`);
25
+ }
26
+ for (const scope of [...input.grant, ...input.revoke]) {
27
+ const allowed = mayGrant(scope, { granter, namespaces: fleet.namespaces });
28
+ if (!allowed.isOk) {
29
+ return allowed;
30
+ }
31
+ }
32
+ const both = input.grant.find((scope) => input.revoke.includes(scope));
33
+ if (both !== undefined) {
34
+ return refuse('INVALID_SCOPE', `${both} is both granted and revoked`);
35
+ }
36
+ const base = input.revoke.find((scope) => BASE_SCOPES.includes(scope));
37
+ if (base !== undefined) {
38
+ return refuse('BASE_SCOPE', `Every ship holds ${base}: it is never revoked`);
39
+ }
40
+ const added = [...new Set(input.grant)].filter((scope) => !ship.scopes.includes(scope));
41
+ const removed = ship.scopes.filter((scope) => input.revoke.includes(scope));
42
+ if (added.length === 0 && removed.length === 0) {
43
+ return ok({ ship, events: [] });
44
+ }
45
+ const changed = { ...ship, scopes: [...ship.scopes.filter((scope) => !removed.includes(scope)), ...added] };
46
+ return ok({
47
+ ship: changed,
48
+ events: [{ fleetId: ship.fleetId, type: 'ScopesChanged', occurredAt: at, actor, shipId: ship.id, details: { added: added.join(' '), removed: removed.join(' ') } }],
49
+ });
50
+ }
51
+ /**
52
+ * Whether the granter may grant or revoke the scope, at commission or on a
53
+ * live ship: a core scope it holds, or a declared plugin scope when it is
54
+ * argo or the declarer.
55
+ */
56
+ export function mayGrant(scope, at) {
57
+ const { granter, namespaces } = at;
58
+ if (!scopeNameSchema.safeParse(scope).success) {
59
+ return refuse('INVALID_SCOPE', `${scope} is no scope: a core scope, or a plugin's <namespace>:<action>`);
60
+ }
61
+ if (scopeSchema.safeParse(scope).success) {
62
+ return granter.kind === 'operator' || granter.scopes.includes(scope) ? ok(null) : refuse('SCOPE_NOT_HELD', `Your ship does not hold ${scope}, so it cannot grant it`);
63
+ }
64
+ const namespace = scope.slice(0, scope.indexOf(':'));
65
+ const declared = namespaces.get(namespace);
66
+ if (declared?.namespace.scopes.some((each) => each.scope === scope) !== true) {
67
+ return refuse('SCOPE_NOT_DECLARED', `No plugin declared ${scope}`);
68
+ }
69
+ if (granter.kind !== 'operator' && declared.namespace.declaredBy !== granter.shipId) {
70
+ return refuse('PLUGIN_SCOPE_NOT_YOURS', `Only argo and ${declared.declarerName}, which declared ${namespace}, grant ${scope}`);
71
+ }
72
+ return ok(null);
73
+ }
74
+ //# sourceMappingURL=scope-grant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-grant.js","sourceRoot":"","sources":["../../../src/domain/registry/scope-grant.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,WAAW,EAA8C,MAAM,sBAAsB,CAAC;AAEhH,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAE/D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAItD,wFAAwF;AACxF,MAAM,WAAW,GAAyB,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAC;AAMhF;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CACzB,KAOC,EACD,KAGC;IAED,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAC3C,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvD,OAAO,MAAM,CAAC,mBAAmB,EAAE,GAAG,IAAI,CAAC,IAAI,oEAAoE,CAAC,CAAC;IACvH,CAAC;IACD,IAAI,IAAI,CAAC,EAAE,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC,iBAAiB,EAAE,qCAAqC,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC,sBAAsB,EAAE,GAAG,IAAI,CAAC,IAAI,2CAA2C,CAAC,CAAC;IACjG,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QAC3E,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACvE,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,MAAM,CAAC,eAAe,EAAE,GAAG,IAAI,8BAA8B,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACvE,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,MAAM,CAAC,YAAY,EAAE,oBAAoB,IAAI,uBAAuB,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACxF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/C,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,OAAO,GAAS,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;IAClH,OAAO,EAAE,CAAC;QACR,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;KACpK,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAa,EACb,EAAuK;IAEvK,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;IACnC,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;QAC9C,OAAO,MAAM,CAAC,eAAe,EAAE,GAAG,KAAK,gEAAgE,CAAC,CAAC;IAC3G,CAAC;IACD,IAAI,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;QACzC,OAAO,OAAO,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,EAAE,2BAA2B,KAAK,yBAAyB,CAAC,CAAC;IACxK,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC3C,IAAI,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7E,OAAO,MAAM,CAAC,oBAAoB,EAAE,sBAAsB,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,IAAI,QAAQ,CAAC,SAAS,CAAC,UAAU,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QACpF,OAAO,MAAM,CAAC,wBAAwB,EAAE,iBAAiB,QAAQ,CAAC,YAAY,oBAAoB,SAAS,WAAW,KAAK,EAAE,CAAC,CAAC;IACjI,CAAC;IACD,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { type FleetId, type ScopeName, type ShipId } from '@aeolus-fleet/common';
2
+ import { type DomainError } from '../shared/errors.js';
3
+ import type { Actor, NewEvent } from '../shared/events.js';
4
+ import { type Result } from '../shared/result.js';
5
+ import type { Ship } from './ship.js';
6
+ /** One scope a plugin declared, with its one-line description. */
7
+ export interface DeclaredScope {
8
+ scope: ScopeName;
9
+ description: string;
10
+ }
11
+ /**
12
+ * A plugin's namespace (decision 0046): taken up for good by the ship that
13
+ * declared it, one per ship and unique in the fleet, with its whole list of
14
+ * scopes. Core stores and answers them and never checks them; the plugin
15
+ * enforces them. It goes when its declarer retires.
16
+ */
17
+ export interface ScopeNamespace {
18
+ fleetId: FleetId;
19
+ namespace: string;
20
+ declaredBy: ShipId;
21
+ /** In the order the declarer gave them, each once. */
22
+ scopes: readonly DeclaredScope[];
23
+ }
24
+ export type DeclareScopesRefusal = DomainError<'INVALID_SCOPE' | 'INVALID_SCOPE_DESCRIPTION' | 'CORE_NAMESPACE' | 'NAMESPACE_TAKEN' | 'SECOND_NAMESPACE' | 'TOO_MANY_SCOPES' | 'SCOPE_HELD'>;
25
+ /**
26
+ * A ship declares its namespace with its whole list of scopes, the first
27
+ * time or again (decision 0046). Refused: a malformed namespace or scope, a
28
+ * scope of another namespace or twice, a description not on one line, a core
29
+ * namespace, a namespace another ship took, a second namespace, more than 20
30
+ * scopes, and removing a scope an active ship holds. Writes ScopesDeclared.
31
+ */
32
+ export declare function declareScopes(input: {
33
+ fleetId: FleetId;
34
+ declarer: ShipId;
35
+ namespace: string;
36
+ scopes: readonly {
37
+ scope: string;
38
+ description: string;
39
+ }[];
40
+ at: Date;
41
+ actor: Actor;
42
+ }, fleet: {
43
+ /** The namespace as the fleet holds it, with its declarer's name, if anyone took it. */
44
+ taken: {
45
+ namespace: ScopeNamespace;
46
+ declarerName: string;
47
+ } | undefined;
48
+ /** The namespace the declaring ship took, if any. */
49
+ ofDeclarer: ScopeNamespace | undefined;
50
+ /** The scopes of this namespace an active ship holds. */
51
+ held: readonly ScopeName[];
52
+ }): Result<{
53
+ namespace: ScopeNamespace;
54
+ events: NewEvent[];
55
+ }, DeclareScopesRefusal>;
56
+ /**
57
+ * The namespace goes with its retiring declarer (decision 0046): each active
58
+ * ship that holds any of its scopes loses them, keeping its other scopes, one
59
+ * ScopesChanged each.
60
+ */
61
+ export declare function releaseWithDeclarer(namespace: ScopeNamespace, at: {
62
+ holders: readonly Ship[];
63
+ at: Date;
64
+ actor: Actor;
65
+ }): {
66
+ ships: Ship[];
67
+ events: NewEvent[];
68
+ };
@@ -0,0 +1,82 @@
1
+ import { isCoreNamespace, NAMESPACE_SCOPES_MAX, SCOPE_DESCRIPTION_MAX_LENGTH, SCOPE_NAME_PATTERN, SCOPE_NAMESPACE_PATTERN, } from '@aeolus-fleet/common';
2
+ import { refuse } from '../shared/errors.js';
3
+ import { ok } from '../shared/result.js';
4
+ /**
5
+ * A ship declares its namespace with its whole list of scopes, the first
6
+ * time or again (decision 0046). Refused: a malformed namespace or scope, a
7
+ * scope of another namespace or twice, a description not on one line, a core
8
+ * namespace, a namespace another ship took, a second namespace, more than 20
9
+ * scopes, and removing a scope an active ship holds. Writes ScopesDeclared.
10
+ */
11
+ export function declareScopes(input, fleet) {
12
+ const { fleetId, declarer, namespace, at, actor } = input;
13
+ if (!SCOPE_NAMESPACE_PATTERN.test(namespace)) {
14
+ return refuse('INVALID_SCOPE', `${namespace} is no namespace: lowercase letters, digits and hyphens, starting with a letter, at most 32 characters`);
15
+ }
16
+ if (isCoreNamespace(namespace)) {
17
+ return refuse('CORE_NAMESPACE', `${namespace} is a core namespace: core alone declares its scopes`);
18
+ }
19
+ if (input.scopes.length > NAMESPACE_SCOPES_MAX) {
20
+ return refuse('TOO_MANY_SCOPES', `A namespace has at most ${String(NAMESPACE_SCOPES_MAX)} scopes`);
21
+ }
22
+ const scopes = declaredScopes(namespace, input.scopes);
23
+ if (!scopes.isOk) {
24
+ return scopes;
25
+ }
26
+ if (fleet.taken !== undefined && fleet.taken.namespace.declaredBy !== declarer) {
27
+ return refuse('NAMESPACE_TAKEN', `The namespace ${namespace} is taken, by ${fleet.taken.declarerName}`);
28
+ }
29
+ if (fleet.ofDeclarer !== undefined && fleet.ofDeclarer.namespace !== namespace) {
30
+ return refuse('SECOND_NAMESPACE', `This ship declared the namespace ${fleet.ofDeclarer.namespace}: a ship takes up one namespace`);
31
+ }
32
+ const kept = new Set(scopes.value.map(({ scope }) => scope));
33
+ const removedHeld = fleet.held.filter((scope) => !kept.has(scope));
34
+ if (removedHeld.length > 0) {
35
+ return refuse('SCOPE_HELD', `Ships hold ${removedHeld.join(', ')}: revoke it from them first`);
36
+ }
37
+ const declared = { fleetId, namespace, declaredBy: declarer, scopes: scopes.value };
38
+ return ok({
39
+ namespace: declared,
40
+ events: [{ fleetId, type: 'ScopesDeclared', occurredAt: at, actor, shipId: declarer, details: { namespace, scopes: declared.scopes.length } }],
41
+ });
42
+ }
43
+ /** The scopes as declared, each of the namespace, once, with a description on one line. */
44
+ function declaredScopes(namespace, scopes) {
45
+ const seen = new Set();
46
+ const declared = [];
47
+ for (const { scope, description } of scopes) {
48
+ if (!SCOPE_NAME_PATTERN.test(scope) || !scope.startsWith(`${namespace}:`)) {
49
+ return refuse('INVALID_SCOPE', `${scope} is no scope of ${namespace}: ${namespace}:<action>`);
50
+ }
51
+ if (seen.has(scope)) {
52
+ return refuse('INVALID_SCOPE', `${scope} is declared twice`);
53
+ }
54
+ if (description.trim() === '' || description.includes('\n') || description.length > SCOPE_DESCRIPTION_MAX_LENGTH) {
55
+ return refuse('INVALID_SCOPE_DESCRIPTION', `The description of ${scope} is one line of 1 to ${String(SCOPE_DESCRIPTION_MAX_LENGTH)} characters`);
56
+ }
57
+ seen.add(scope);
58
+ declared.push({ scope, description });
59
+ }
60
+ return ok(declared);
61
+ }
62
+ /**
63
+ * The namespace goes with its retiring declarer (decision 0046): each active
64
+ * ship that holds any of its scopes loses them, keeping its other scopes, one
65
+ * ScopesChanged each.
66
+ */
67
+ export function releaseWithDeclarer(namespace, at) {
68
+ const isOfNamespace = (scope) => scope.startsWith(`${namespace.namespace}:`);
69
+ const changed = at.holders.filter((ship) => ship.id !== namespace.declaredBy && ship.scopes.some(isOfNamespace));
70
+ return {
71
+ ships: changed.map((ship) => ({ ...ship, scopes: ship.scopes.filter((scope) => !isOfNamespace(scope)) })),
72
+ events: changed.map((ship) => ({
73
+ fleetId: ship.fleetId,
74
+ type: 'ScopesChanged',
75
+ occurredAt: at.at,
76
+ actor: at.actor,
77
+ shipId: ship.id,
78
+ details: { added: '', removed: ship.scopes.filter(isOfNamespace).join(' ') },
79
+ })),
80
+ };
81
+ }
82
+ //# sourceMappingURL=scope-namespace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-namespace.js","sourceRoot":"","sources":["../../../src/domain/registry/scope-namespace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { IdGenerator, SetBuiltInRuleInput } 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 SetBuiltInRuleRefusal } from './network-settings.js';
8
+ import type { NetworkSettingsRepository } from './ports.js';
9
+ export interface SetBuiltInRuleTx {
10
+ networkSettings: Pick<NetworkSettingsRepository, 'findForUpdate' | 'save'>;
11
+ events: EventLog;
12
+ }
13
+ export type SetBuiltInRule = (caller: Caller, input: SetBuiltInRuleInput) => Promise<Result<{
14
+ version: number;
15
+ }, SetBuiltInRuleRefusal>>;
16
+ /**
17
+ * Use case: a built-in rule turned on or off (decision 0034): the viewer
18
+ * reading by argo, open for one verb by the fleet's networking plugin. Its
19
+ * scope (fleet:network, which argo holds) is checked before this runs. In one
20
+ * unit of work, holding the settings exclusively so no send is checked
21
+ * halfway: the settings at their next version, and BuiltInRuleChanged. A rule
22
+ * already as asked answers the version it has.
23
+ */
24
+ export declare function createSetBuiltInRule(deps: {
25
+ uow: UnitOfWork<SetBuiltInRuleTx>;
26
+ clock: Clock;
27
+ ids: IdGenerator;
28
+ }): SetBuiltInRule;
@@ -0,0 +1,33 @@
1
+ import { recordEvent, shipActor } from '../shared/events.js';
2
+ import { ok } from '../shared/result.js';
3
+ import { setBuiltInRule } from './network-settings.js';
4
+ /**
5
+ * Use case: a built-in rule turned on or off (decision 0034): the viewer
6
+ * reading by argo, open for one verb by the fleet's networking plugin. Its
7
+ * scope (fleet:network, which argo holds) is checked before this runs. In one
8
+ * unit of work, holding the settings exclusively so no send is checked
9
+ * halfway: the settings at their next version, and BuiltInRuleChanged. A rule
10
+ * already as asked answers the version it has.
11
+ */
12
+ export function createSetBuiltInRule(deps) {
13
+ return (caller, input) => deps.uow.run(async (tx) => {
14
+ const current = await tx.networkSettings.findForUpdate(caller.fleetId);
15
+ const set = setBuiltInRule(current, {
16
+ input,
17
+ caller: { shipId: caller.shipId, isOperator: caller.kind === 'operator' },
18
+ at: deps.clock.now(),
19
+ actor: shipActor(caller.shipId),
20
+ });
21
+ if (!set.isOk) {
22
+ return set;
23
+ }
24
+ if (set.value.events.length > 0) {
25
+ await tx.networkSettings.save(set.value.settings);
26
+ }
27
+ for (const event of set.value.events) {
28
+ await recordEvent({ events: tx.events, ids: deps.ids }, event);
29
+ }
30
+ return ok({ version: set.value.settings.version });
31
+ });
32
+ }
33
+ //# sourceMappingURL=set-built-in-rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-built-in-rule.js","sourceRoot":"","sources":["../../../src/domain/registry/set-built-in-rule.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAA8B,MAAM,uBAAuB,CAAC;AAUnF;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAA2E;IAC9G,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAA+D,EAAE;QACrF,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,eAAe,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvE,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,EAAE;YAClC,KAAK;YACL,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE;YACzE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YACpB,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,GAAG,CAAC;QACb,CAAC;QACD,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpD,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACrC,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,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -12,13 +12,13 @@ export interface SetNetworkRulesTx {
12
12
  events: EventLog;
13
13
  }
14
14
  export type SetNetworkRules = (caller: Caller, input: {
15
- rules: readonly NetworkRule[] | null;
15
+ rules: readonly NetworkRule[];
16
16
  }) => Promise<Result<{
17
17
  version: number;
18
18
  }, SetNetworkRulesRefusal>>;
19
19
  /**
20
- * Use case: the caller sets the fleet's network rules, the whole list, or
21
- * none for all-to-all (decision 0034), argo's with the rules the fleet's
20
+ * Use case: the caller sets the fleet's network rules, the whole list beside
21
+ * the built-in ones (decision 0034), argo's with the rules the fleet's
22
22
  * ships declared added (decision 0037), which the limit counts. Its scope (fleet:network, which argo
23
23
  * holds) is checked before this runs. In one unit of work, holding the
24
24
  * settings exclusively so no send is checked halfway: the settings at their
@@ -2,8 +2,8 @@ import { recordEvent, shipActor } from '../shared/events.js';
2
2
  import { ok } from '../shared/result.js';
3
3
  import { setNetworkRules } from './network-settings.js';
4
4
  /**
5
- * Use case: the caller sets the fleet's network rules, the whole list, or
6
- * none for all-to-all (decision 0034), argo's with the rules the fleet's
5
+ * Use case: the caller sets the fleet's network rules, the whole list beside
6
+ * the built-in ones (decision 0034), argo's with the rules the fleet's
7
7
  * ships declared added (decision 0037), which the limit counts. Its scope (fleet:network, which argo
8
8
  * holds) is checked before this runs. In one unit of work, holding the
9
9
  * settings exclusively so no send is checked halfway: the settings at their