@aeolus-fleet/core 0.20.3 → 0.20.4

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 (108) hide show
  1. package/README.md +1 -1
  2. package/dist/adapters/http/server.d.ts +0 -2
  3. package/dist/adapters/http/server.js +4 -12
  4. package/dist/adapters/http/server.js.map +1 -1
  5. package/dist/adapters/prisma/client.d.ts +0 -2
  6. package/dist/adapters/prisma/client.js +0 -9
  7. package/dist/adapters/prisma/client.js.map +1 -1
  8. package/dist/adapters/prisma/generated/browser.d.ts +18 -0
  9. package/dist/adapters/prisma/generated/client.d.ts +18 -0
  10. package/dist/adapters/prisma/generated/internal/class.d.ts +22 -0
  11. package/dist/adapters/prisma/generated/internal/class.js +4 -4
  12. package/dist/adapters/prisma/generated/internal/class.js.map +1 -1
  13. package/dist/adapters/prisma/generated/internal/prismaNamespace.d.ts +169 -1
  14. package/dist/adapters/prisma/generated/internal/prismaNamespace.js +16 -0
  15. package/dist/adapters/prisma/generated/internal/prismaNamespace.js.map +1 -1
  16. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.d.ts +18 -0
  17. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js +16 -0
  18. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  19. package/dist/adapters/prisma/generated/models/Delivery.d.ts +68 -1
  20. package/dist/adapters/prisma/generated/models/Fleet.d.ts +481 -0
  21. package/dist/adapters/prisma/generated/models/NetworkSettings.d.ts +1101 -0
  22. package/dist/adapters/prisma/generated/models/NetworkSettings.js +2 -0
  23. package/dist/adapters/prisma/generated/models/NetworkSettings.js.map +1 -0
  24. package/dist/adapters/prisma/generated/models/ReachRefusal.d.ts +1239 -0
  25. package/dist/adapters/prisma/generated/models/ReachRefusal.js +2 -0
  26. package/dist/adapters/prisma/generated/models/ReachRefusal.js.map +1 -0
  27. package/dist/adapters/prisma/generated/models.d.ts +2 -0
  28. package/dist/adapters/prisma/messaging.js +16 -2
  29. package/dist/adapters/prisma/messaging.js.map +1 -1
  30. package/dist/adapters/prisma/network.d.ts +4 -0
  31. package/dist/adapters/prisma/network.js +69 -0
  32. package/dist/adapters/prisma/network.js.map +1 -0
  33. package/dist/adapters/prisma/registry.js +3 -0
  34. package/dist/adapters/prisma/registry.js.map +1 -1
  35. package/dist/adapters/prisma/unit-of-work.d.ts +3 -1
  36. package/dist/adapters/prisma/unit-of-work.js +3 -0
  37. package/dist/adapters/prisma/unit-of-work.js.map +1 -1
  38. package/dist/adapters/trpc/console.d.ts +1 -1
  39. package/dist/adapters/trpc/context.d.ts +4 -0
  40. package/dist/adapters/trpc/fleet.d.ts +68 -6
  41. package/dist/adapters/trpc/fleet.js +25 -1
  42. package/dist/adapters/trpc/fleet.js.map +1 -1
  43. package/dist/adapters/trpc/router.d.ts +67 -7
  44. package/dist/adapters/trpc/ship-contract.js +1 -0
  45. package/dist/adapters/trpc/ship-contract.js.map +1 -1
  46. package/dist/adapters/trpc/ship-protocol.js +9 -8
  47. package/dist/adapters/trpc/ship-protocol.js.map +1 -1
  48. package/dist/adapters/trpc/trpc.js +2 -0
  49. package/dist/adapters/trpc/trpc.js.map +1 -1
  50. package/dist/app.js +1 -2
  51. package/dist/app.js.map +1 -1
  52. package/dist/domain/messaging/answer.d.ts +17 -0
  53. package/dist/domain/messaging/answer.js +16 -0
  54. package/dist/domain/messaging/answer.js.map +1 -0
  55. package/dist/domain/messaging/message.d.ts +10 -1
  56. package/dist/domain/messaging/message.js +4 -2
  57. package/dist/domain/messaging/message.js.map +1 -1
  58. package/dist/domain/messaging/ports.d.ts +2 -0
  59. package/dist/domain/messaging/resend-delivery.d.ts +11 -4
  60. package/dist/domain/messaging/resend-delivery.js +87 -62
  61. package/dist/domain/messaging/resend-delivery.js.map +1 -1
  62. package/dist/domain/messaging/send-message.d.ts +11 -4
  63. package/dist/domain/messaging/send-message.js +32 -6
  64. package/dist/domain/messaging/send-message.js.map +1 -1
  65. package/dist/domain/registry/check-reach.d.ts +44 -0
  66. package/dist/domain/registry/check-reach.js +75 -0
  67. package/dist/domain/registry/check-reach.js.map +1 -0
  68. package/dist/domain/registry/get-ship.d.ts +3 -3
  69. package/dist/domain/registry/get-ship.js +2 -1
  70. package/dist/domain/registry/get-ship.js.map +1 -1
  71. package/dist/domain/registry/network-settings.d.ts +58 -0
  72. package/dist/domain/registry/network-settings.js +81 -0
  73. package/dist/domain/registry/network-settings.js.map +1 -0
  74. package/dist/domain/registry/ports.d.ts +22 -0
  75. package/dist/domain/registry/public.d.ts +1 -0
  76. package/dist/domain/registry/public.js +1 -0
  77. package/dist/domain/registry/public.js.map +1 -1
  78. package/dist/domain/registry/reach-refusal.d.ts +30 -0
  79. package/dist/domain/registry/reach-refusal.js +2 -0
  80. package/dist/domain/registry/reach-refusal.js.map +1 -0
  81. package/dist/domain/registry/read-reach-refusals.d.ts +14 -0
  82. package/dist/domain/registry/read-reach-refusals.js +17 -0
  83. package/dist/domain/registry/read-reach-refusals.js.map +1 -0
  84. package/dist/domain/registry/set-network-rules.d.ts +29 -0
  85. package/dist/domain/registry/set-network-rules.js +25 -0
  86. package/dist/domain/registry/set-network-rules.js.map +1 -0
  87. package/dist/domain/registry/ship-report.d.ts +5 -0
  88. package/dist/domain/registry/ship-report.js +3 -0
  89. package/dist/domain/registry/ship-report.js.map +1 -1
  90. package/dist/domain/shared/errors.d.ts +1 -1
  91. package/dist/domain/shared/errors.js.map +1 -1
  92. package/dist/domain/shared/history.d.ts +17 -0
  93. package/dist/domain/shared/history.js +4 -1
  94. package/dist/domain/shared/history.js.map +1 -1
  95. package/dist/domain/shared/read-needs-attention.d.ts +4 -4
  96. package/dist/domain/shared/read-needs-attention.js +4 -3
  97. package/dist/domain/shared/read-needs-attention.js.map +1 -1
  98. package/dist/domain/shared/read-ship-timeline.d.ts +5 -4
  99. package/dist/domain/shared/read-ship-timeline.js +7 -3
  100. package/dist/domain/shared/read-ship-timeline.js.map +1 -1
  101. package/dist/wiring.d.ts +4 -0
  102. package/dist/wiring.js +5 -0
  103. package/dist/wiring.js.map +1 -1
  104. package/package.json +2 -2
  105. package/src/adapters/prisma/migrations/20261009200000_network_scope/migration.sql +8 -0
  106. package/src/adapters/prisma/migrations/20261009210000_network_rules/migration.sql +31 -0
  107. package/src/adapters/prisma/migrations/20261009220000_type_delivery_reachable_ships/migration.sql +5 -0
  108. package/src/adapters/prisma/schema.prisma +38 -0
@@ -1,8 +1,9 @@
1
1
  import { isPingContentType } from '@aeolus-fleet/common';
2
- import { resolveSelector } from '../registry/public.js';
2
+ import { checkReach, resolveSelector } from '../registry/public.js';
3
3
  import { refuse } from '../shared/errors.js';
4
4
  import { recordEvent } from '../shared/events.js';
5
- import { ok } from '../shared/result.js';
5
+ import { err, ok } from '../shared/result.js';
6
+ import { isAnswerToSender } from './answer.js';
6
7
  import { withinDailyMessageLimit } from './daily-message-limit.js';
7
8
  import { dismissForResend } from './delivery.js';
8
9
  import { acceptMessage, repeatOf } from './message.js';
@@ -29,69 +30,93 @@ function resendKey(deliveryId) {
29
30
  * the type left, the resend is refused and the original stays undeliverable,
30
31
  * for the operator to dismiss. A ping is never resent: it is dismissed, and
31
32
  * the ship pinged again through ping, so pings never stack. Locks, in this order: the original delivery,
32
- * then the resend's key, then the ship the message is addressed to.
33
+ * then the resend's key, then the ship the message is addressed to, then the
34
+ * fleet's network settings.
35
+ *
36
+ * A resend is a new message, checked by the network rules at its own send time
37
+ * as the original sender sending (decision 0034): one no rule allows commits
38
+ * only its refusal's record and is refused, and the original stays
39
+ * undeliverable, for the operator to dismiss.
33
40
  */
34
41
  export function createResendDelivery(deps) {
35
- return (caller, input) => deps.uow.run(async (tx) => {
36
- const { fleetId } = caller;
37
- const delivery = await tx.deliveries.findForUpdate(fleetId, input.deliveryId);
38
- const original = delivery && (await tx.messages.find(fleetId, delivery.messageId));
39
- if (!delivery || !original) {
40
- return refuse('DELIVERY_NOT_FOUND', `Delivery ${input.deliveryId} does not exist`);
41
- }
42
- if (isPingContentType(original.contentType)) {
43
- return refuse('PING_NOT_RESENT', 'A ping is not resent: dismiss it, and ping the ship again');
44
- }
45
- const selector = original.selector;
46
- const inReplyTo = original.inReplyToMessageId ?? undefined;
47
- const requestHash = deps.hasher.hash(sendRequestText({ selector, payload: original.payload, contentType: original.contentType, inReplyTo }));
48
- const senderKey = { fleetId, senderShipId: original.senderShipId, idempotencyKey: resendKey(delivery.id) };
49
- await tx.messages.lockIdempotencyKey(senderKey);
50
- const earlier = await tx.messages.findByIdempotencyKey(senderKey);
51
- if (earlier) {
52
- const repeat = repeatOf(earlier, requestHash);
53
- return repeat.isOk ? ok({ messageId: repeat.value }) : repeat;
54
- }
55
- const at = deps.clock.now();
56
- const dismissed = dismissForResend(delivery, { by: caller.shipId, at });
57
- if (!dismissed.isOk) {
58
- return dismissed;
59
- }
60
- const recipient = await resolveSelector(tx, { fleetId, selector });
61
- if (!recipient.isOk) {
62
- return recipient;
63
- }
64
- const withinLimit = await withinDailyMessageLimit(tx, { fleetId, time: at });
65
- if (!withinLimit.isOk) {
66
- return withinLimit;
67
- }
68
- const repliedTo = inReplyTo === undefined ? undefined : await tx.messages.find(fleetId, inReplyTo);
69
- const accepted = acceptMessage({ recipient: recipient.value, repliedTo }, {
70
- messageId: deps.ids('message'),
71
- deliveryId: deps.ids('delivery'),
72
- fleetId,
73
- senderShipId: original.senderShipId,
74
- payload: original.payload,
75
- contentType: original.contentType,
76
- model: original.model ?? undefined,
77
- idempotencyKey: senderKey.idempotencyKey,
78
- requestHash,
79
- inReplyTo,
80
- resendOf: { messageId: original.id, by: caller.shipId },
81
- at,
42
+ return async (caller, input) => {
43
+ const outcome = await deps.uow.run(async (tx) => {
44
+ const { fleetId } = caller;
45
+ const delivery = await tx.deliveries.findForUpdate(fleetId, input.deliveryId);
46
+ const original = delivery && (await tx.messages.find(fleetId, delivery.messageId));
47
+ if (!delivery || !original) {
48
+ return refuse('DELIVERY_NOT_FOUND', `Delivery ${input.deliveryId} does not exist`);
49
+ }
50
+ if (isPingContentType(original.contentType)) {
51
+ return refuse('PING_NOT_RESENT', 'A ping is not resent: dismiss it, and ping the ship again');
52
+ }
53
+ const selector = original.selector;
54
+ const inReplyTo = original.inReplyToMessageId ?? undefined;
55
+ const requestHash = deps.hasher.hash(sendRequestText({ selector, payload: original.payload, contentType: original.contentType, inReplyTo }));
56
+ const senderKey = { fleetId, senderShipId: original.senderShipId, idempotencyKey: resendKey(delivery.id) };
57
+ await tx.messages.lockIdempotencyKey(senderKey);
58
+ const earlier = await tx.messages.findByIdempotencyKey(senderKey);
59
+ if (earlier) {
60
+ const repeat = repeatOf(earlier, requestHash);
61
+ return repeat.isOk ? ok({ messageId: repeat.value }) : repeat;
62
+ }
63
+ const at = deps.clock.now();
64
+ const dismissed = dismissForResend(delivery, { by: caller.shipId, at });
65
+ if (!dismissed.isOk) {
66
+ return dismissed;
67
+ }
68
+ const recipient = await resolveSelector(tx, { fleetId, selector });
69
+ if (!recipient.isOk) {
70
+ return recipient;
71
+ }
72
+ const repliedTo = inReplyTo === undefined ? undefined : await tx.messages.find(fleetId, inReplyTo);
73
+ const repliedDelivery = repliedTo && (await tx.deliveries.findOfMessage(fleetId, repliedTo.id));
74
+ const reach = await checkReach({ tx, ids: deps.ids }, {
75
+ fleetId,
76
+ senderShipId: original.senderShipId,
77
+ recipient: recipient.value,
78
+ isAnswerToSender: isAnswerToSender({ senderShipId: original.senderShipId, recipient: recipient.value }, repliedTo && repliedDelivery && { message: repliedTo, delivery: repliedDelivery }),
79
+ at,
80
+ });
81
+ if (!reach.isOk) {
82
+ // Nothing of the resend is stored yet: commit only the refusal's record.
83
+ return ok({ prevented: reach.error });
84
+ }
85
+ const withinLimit = await withinDailyMessageLimit(tx, { fleetId, time: at });
86
+ if (!withinLimit.isOk) {
87
+ return withinLimit;
88
+ }
89
+ const accepted = acceptMessage({ recipient: recipient.value, repliedTo, ...reach.value }, {
90
+ messageId: deps.ids('message'),
91
+ deliveryId: deps.ids('delivery'),
92
+ fleetId,
93
+ senderShipId: original.senderShipId,
94
+ payload: original.payload,
95
+ contentType: original.contentType,
96
+ model: original.model ?? undefined,
97
+ idempotencyKey: senderKey.idempotencyKey,
98
+ requestHash,
99
+ inReplyTo,
100
+ resendOf: { messageId: original.id, by: caller.shipId },
101
+ at,
102
+ });
103
+ if (!accepted.isOk) {
104
+ return accepted;
105
+ }
106
+ const { message, delivery: resent, events } = accepted.value;
107
+ await tx.messages.create(message);
108
+ await tx.deliveries.create(resent);
109
+ await tx.deliveries.update(dismissed.value.delivery);
110
+ for (const event of [...events, ...dismissed.value.events]) {
111
+ await recordEvent({ events: tx.events, ids: deps.ids }, event);
112
+ }
113
+ await tx.notifier.deliveryPending({ fleetId, deliveryId: resent.id, recipient: resent.recipient });
114
+ return ok({ messageId: message.id });
82
115
  });
83
- if (!accepted.isOk) {
84
- return accepted;
85
- }
86
- const { message, delivery: resent, events } = accepted.value;
87
- await tx.messages.create(message);
88
- await tx.deliveries.create(resent);
89
- await tx.deliveries.update(dismissed.value.delivery);
90
- for (const event of [...events, ...dismissed.value.events]) {
91
- await recordEvent({ events: tx.events, ids: deps.ids }, event);
116
+ if (!outcome.isOk) {
117
+ return outcome;
92
118
  }
93
- await tx.notifier.deliveryPending({ fleetId, deliveryId: resent.id, recipient: resent.recipient });
94
- return ok({ messageId: message.id });
95
- });
119
+ return 'prevented' in outcome.value ? err(outcome.value.prevented) : ok(outcome.value);
120
+ };
96
121
  }
97
122
  //# sourceMappingURL=resend-delivery.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resend-delivery.js","sourceRoot":"","sources":["../../../src/domain/messaging/resend-delivery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resend-delivery.js","sourceRoot":"","sources":["../../../src/domain/messaging/resend-delivery.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { type IdGenerator, type MessageId } from '@aeolus-fleet/common';
2
- import { type ResolveSelectorTx, type UnresolvableSelector } from '../registry/public.js';
2
+ import { type CheckReachTx, type NotReachable, type ResolveSelectorTx, type UnresolvableSelector } from '../registry/public.js';
3
3
  import type { Caller } from '../shared/caller.js';
4
4
  import type { Clock } from '../shared/clock.js';
5
5
  import { type DomainError } from '../shared/errors.js';
@@ -11,7 +11,8 @@ import type { UnitOfWork } from '../shared/unit-of-work.js';
11
11
  import { type DailyMessageLimitTx } from './daily-message-limit.js';
12
12
  import { type AcceptRefusal, type RepeatRefusal } from './message.js';
13
13
  import type { DeliveryRepository, MessageRepository, RequestHasher } from './ports.js';
14
- export interface SendMessageTx extends ResolveSelectorTx, DailyMessageLimitTx {
14
+ export interface SendMessageTx extends Omit<ResolveSelectorTx, 'ships'>, Omit<CheckReachTx, 'ships'>, DailyMessageLimitTx {
15
+ ships: ResolveSelectorTx['ships'] & CheckReachTx['ships'];
15
16
  messages: MessageRepository;
16
17
  deliveries: DeliveryRepository;
17
18
  events: EventLog;
@@ -32,7 +33,7 @@ export interface MessageSent {
32
33
  /** The message's id: the original one when the sender used the idempotency key before. */
33
34
  messageId: MessageId;
34
35
  }
35
- export type SendMessageRefusal = DomainError<'PAYLOAD_TOO_LARGE' | 'INVALID_CONTENT_TYPE' | 'INVALID_IDEMPOTENCY_KEY' | 'RESERVED_CONTENT_TYPE'> | RepeatRefusal | UnresolvableSelector | AcceptRefusal | DomainError<'MESSAGE_LIMIT_REACHED'>;
36
+ export type SendMessageRefusal = DomainError<'PAYLOAD_TOO_LARGE' | 'INVALID_CONTENT_TYPE' | 'INVALID_IDEMPOTENCY_KEY' | 'RESERVED_CONTENT_TYPE'> | RepeatRefusal | UnresolvableSelector | AcceptRefusal | NotReachable | DomainError<'MESSAGE_LIMIT_REACHED'>;
36
37
  export type SendMessage = (caller: Caller, input: MessageToSend) => Promise<Result<MessageSent, SendMessageRefusal>>;
37
38
  /**
38
39
  * Use case: the calling ship sends a message (`send`). The sender is always
@@ -53,7 +54,13 @@ export type SendMessage = (caller: Caller, input: MessageToSend) => Promise<Resu
53
54
  * a retry still gets its OK after the recipient was retired. Locks, in this
54
55
  * order: the sender's key, so two sends with one key take turns and the second
55
56
  * finds the first one's message; then the ship the message is addressed to,
56
- * held against a retire.
57
+ * held against a retire; then the fleet's network settings, held shared
58
+ * against a change of rules.
59
+ *
60
+ * With network rules set, a send no rule allows is refused (decision 0034):
61
+ * its unit of work commits only the refusal's record, and the sender gets a
62
+ * refusal without reasons. argo, and an answer to the sender of a message the
63
+ * ship received, always go through.
57
64
  */
58
65
  export declare function createSendMessage(deps: {
59
66
  uow: UnitOfWork<SendMessageTx>;
@@ -1,8 +1,9 @@
1
1
  import { isPingContentType, PING_CONTENT_TYPE } from '@aeolus-fleet/common';
2
- import { resolveSelector } from '../registry/public.js';
2
+ import { checkReach, resolveSelector } from '../registry/public.js';
3
3
  import { refuse } from '../shared/errors.js';
4
4
  import { recordEvent } from '../shared/events.js';
5
- import { ok } from '../shared/result.js';
5
+ import { err, ok } from '../shared/result.js';
6
+ import { isAnswerToSender } from './answer.js';
6
7
  import { contentType } from './content-type.js';
7
8
  import { withinDailyMessageLimit } from './daily-message-limit.js';
8
9
  import { idempotencyKey } from '../shared/idempotency-key.js';
@@ -28,7 +29,13 @@ import { sendRequestText } from './send-request.js';
28
29
  * a retry still gets its OK after the recipient was retired. Locks, in this
29
30
  * order: the sender's key, so two sends with one key take turns and the second
30
31
  * finds the first one's message; then the ship the message is addressed to,
31
- * held against a retire.
32
+ * held against a retire; then the fleet's network settings, held shared
33
+ * against a change of rules.
34
+ *
35
+ * With network rules set, a send no rule allows is refused (decision 0034):
36
+ * its unit of work commits only the refusal's record, and the sender gets a
37
+ * refusal without reasons. argo, and an answer to the sender of a message the
38
+ * ship received, always go through.
32
39
  */
33
40
  export function createSendMessage(deps) {
34
41
  return async (caller, input) => {
@@ -39,7 +46,15 @@ export function createSendMessage(deps) {
39
46
  if (!request.isOk) {
40
47
  return request;
41
48
  }
42
- return deps.uow.run((tx) => sendWithin({ tx, clock: deps.clock, ids: deps.ids }, { caller, request: request.value }));
49
+ const outcome = await deps.uow.run(async (tx) => {
50
+ const sent = await sendWithin({ tx, clock: deps.clock, ids: deps.ids }, { caller, request: request.value });
51
+ // A send the network rules refused stored only its refusal's record: committed, then refused.
52
+ return !sent.isOk && sent.error.kind === 'NOT_REACHABLE' ? ok({ prevented: sent.error }) : sent;
53
+ });
54
+ if (!outcome.isOk) {
55
+ return outcome;
56
+ }
57
+ return 'prevented' in outcome.value ? err(outcome.value.prevented) : ok(outcome.value);
43
58
  };
44
59
  }
45
60
  /**
@@ -81,12 +96,23 @@ export async function sendWithin(deps, send) {
81
96
  return recipient;
82
97
  }
83
98
  const at = clock.now();
99
+ const repliedTo = inReplyTo === undefined ? undefined : await tx.messages.find(fleetId, inReplyTo);
100
+ const repliedDelivery = repliedTo && (await tx.deliveries.findOfMessage(fleetId, repliedTo.id));
101
+ const reach = await checkReach({ tx, ids }, {
102
+ fleetId,
103
+ senderShipId,
104
+ recipient: recipient.value,
105
+ isAnswerToSender: isAnswerToSender({ senderShipId, recipient: recipient.value }, repliedTo && repliedDelivery && { message: repliedTo, delivery: repliedDelivery }),
106
+ at,
107
+ });
108
+ if (!reach.isOk) {
109
+ return reach;
110
+ }
84
111
  const withinLimit = await withinDailyMessageLimit(tx, { fleetId, time: at });
85
112
  if (!withinLimit.isOk) {
86
113
  return withinLimit;
87
114
  }
88
- const repliedTo = inReplyTo === undefined ? undefined : await tx.messages.find(fleetId, inReplyTo);
89
- const accepted = acceptMessage({ recipient: recipient.value, repliedTo }, {
115
+ const accepted = acceptMessage({ recipient: recipient.value, repliedTo, ...reach.value }, {
90
116
  messageId: ids('message'),
91
117
  deliveryId: ids('delivery'),
92
118
  fleetId,
@@ -1 +1 @@
1
- {"version":3,"file":"send-message.js","sourceRoot":"","sources":["../../../src/domain/messaging/send-message.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"send-message.js","sourceRoot":"","sources":["../../../src/domain/messaging/send-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAoC,MAAM,sBAAsB,CAAC;AAE9G,OAAO,EAAE,UAAU,EAAE,eAAe,EAA2F,MAAM,uBAAuB,CAAC;AAG7J,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAiB,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAA4B,MAAM,0BAA0B,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAA0C,MAAM,cAAc,CAAC;AAC/F,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAqCpD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAKjC;IACC,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;QAC7B,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5E,OAAO,MAAM,CAAC,uBAAuB,EAAE,GAAG,iBAAiB,sDAAsD,CAAC,CAAC;QACrH,CAAC;QACD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAkF,EAAE;YAC9H,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;YAC5G,8FAA8F;YAC9F,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClG,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACzF,CAAC,CAAC;AACJ,CAAC;AAaD;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAAoB,EAAE,MAAqB;IACrE,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACjD,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QACpB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,GAAG,GAAG,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,GAAG,CAAC;IACb,CAAC;IACD,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACtC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAC7B,eAAe,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAC5F,CAAC;IACF,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC;AACpJ,CAAC;AAED,wGAAwG;AACxG,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAA2D,EAC3D,IAA8C;IAE9C,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;IACtD,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;IAC1D,MAAM,SAAS,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;IACzF,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACnE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAChE,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QACpB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,SAAS,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACnG,MAAM,eAAe,GAAG,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IAChG,MAAM,KAAK,GAAG,MAAM,UAAU,CAC5B,EAAE,EAAE,EAAE,GAAG,EAAE,EACX;QACE,OAAO;QACP,YAAY;QACZ,SAAS,EAAE,SAAS,CAAC,KAAK;QAC1B,gBAAgB,EAAE,gBAAgB,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,CAAC,KAAK,EAAE,EAAE,SAAS,IAAI,eAAe,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;QACnK,EAAE;KACH,CACF,CAAC;IACF,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,uBAAuB,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7E,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QACtB,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,MAAM,QAAQ,GAAG,aAAa,CAC5B,EAAE,SAAS,EAAE,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,EACzD;QACE,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC;QACzB,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC;QAC3B,OAAO;QACP,YAAY;QACZ,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;QAC7B,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW;QACrC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;QACzB,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;QAC5B,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc;QAC3C,WAAW;QACX,SAAS;QACT,EAAE;KACH,CACF,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC;IACrD,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IACvG,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { FleetId, IdGenerator, ShipId } from '@aeolus-fleet/common';
2
+ import { type DomainError } from '../shared/errors.js';
3
+ import { type Result } from '../shared/result.js';
4
+ import type { Recipient } from '../shared/selector.js';
5
+ import type { LabelRepository, NetworkSettingsRepository, ReachRefusalRepository, ShipRepository } from './ports.js';
6
+ /** The ports a send's reach check reads and writes, inside the send's unit of work. */
7
+ export interface CheckReachTx {
8
+ networkSettings: Pick<NetworkSettingsRepository, 'findForShare'>;
9
+ ships: Pick<ShipRepository, 'find' | 'listActiveOfType'>;
10
+ labels: Pick<LabelRepository, 'carriedBy' | 'find'>;
11
+ reachRefusals: ReachRefusalRepository;
12
+ }
13
+ /** One fixed message, so a refused sender learns nothing about the rules (decision 0034). */
14
+ export type NotReachable = DomainError<'NOT_REACHABLE'>;
15
+ /** What a send may go on with: for a type, the ships of it the sender may reach, or none for any ship of it. */
16
+ export interface Reach {
17
+ reachableShipIds?: readonly ShipId[];
18
+ }
19
+ /**
20
+ * Whether the fleet's network rules let the sender reach the recipient a
21
+ * selector resolved to, at send time: Messaging's question to Registry before
22
+ * it stores a message (decision 0034). The settings stay held shared until
23
+ * the unit of work ends, so a change of rules waits for the send, and a send
24
+ * that comes after it is checked against the new version.
25
+ *
26
+ * For a type, the ships of it the sender may reach now are the ones that may
27
+ * claim the delivery, fixed here; none of them refuses the send. With no
28
+ * rules, or from argo, who reaches every ship, any ship of the type may.
29
+ *
30
+ * A refusal is recorded here, in the send's unit of work, with the ships and
31
+ * the label values they carry now and the settings version: the send stores
32
+ * nothing else, so its caller commits only the record. `isAnswerToSender` says
33
+ * the send answers the sender of a message the sending ship received.
34
+ */
35
+ export declare function checkReach(deps: {
36
+ tx: CheckReachTx;
37
+ ids: IdGenerator;
38
+ }, send: {
39
+ fleetId: FleetId;
40
+ senderShipId: ShipId;
41
+ recipient: Recipient;
42
+ isAnswerToSender: boolean;
43
+ at: Date;
44
+ }): Promise<Result<Reach, NotReachable>>;
@@ -0,0 +1,75 @@
1
+ import { refuse } from '../shared/errors.js';
2
+ import { ok } from '../shared/result.js';
3
+ import { allowsReach } from './network-settings.js';
4
+ /**
5
+ * Whether the fleet's network rules let the sender reach the recipient a
6
+ * selector resolved to, at send time: Messaging's question to Registry before
7
+ * it stores a message (decision 0034). The settings stay held shared until
8
+ * the unit of work ends, so a change of rules waits for the send, and a send
9
+ * that comes after it is checked against the new version.
10
+ *
11
+ * For a type, the ships of it the sender may reach now are the ones that may
12
+ * claim the delivery, fixed here; none of them refuses the send. With no
13
+ * rules, or from argo, who reaches every ship, any ship of the type may.
14
+ *
15
+ * A refusal is recorded here, in the send's unit of work, with the ships and
16
+ * the label values they carry now and the settings version: the send stores
17
+ * nothing else, so its caller commits only the record. `isAnswerToSender` says
18
+ * the send answers the sender of a message the sending ship received.
19
+ */
20
+ export async function checkReach(deps, send) {
21
+ const { tx, ids } = deps;
22
+ const { fleetId, recipient } = send;
23
+ const settings = await tx.networkSettings.findForShare(fleetId);
24
+ const senderShip = await tx.ships.find(fleetId, send.senderShipId);
25
+ if (settings.rules === null || !senderShip || senderShip.kind === 'operator') {
26
+ return ok({});
27
+ }
28
+ const sender = await shipAsItIs(tx, senderShip);
29
+ const allows = (to) => allowsReach(settings, { sender: reaching(sender), recipient: reaching(to), isAnswerToSender: send.isAnswerToSender });
30
+ const refusal = { fleetId, at: send.at, sender: refused(sender), settingsVersion: settings.version };
31
+ if (recipient.kind === 'type') {
32
+ const ships = [];
33
+ for (const ship of await tx.ships.listActiveOfType(fleetId, recipient.type)) {
34
+ ships.push(await shipAsItIs(tx, ship));
35
+ }
36
+ const reachable = ships.filter(allows);
37
+ if (reachable.length > 0) {
38
+ return ok({ reachableShipIds: reachable.map(({ ship }) => ship.id) });
39
+ }
40
+ await tx.reachRefusals.record({ ...refusal, id: ids('reachRefusal'), recipient: { kind: 'type', type: recipient.type, ships: ships.map(refused) } });
41
+ return refuse('NOT_REACHABLE', NOT_REACHABLE_MESSAGE);
42
+ }
43
+ const reachedShip = await tx.ships.find(fleetId, recipient.shipId);
44
+ if (!reachedShip) {
45
+ // resolveSelector found it in this unit of work: a ship is never deleted, only retired.
46
+ return ok({});
47
+ }
48
+ const reached = await shipAsItIs(tx, reachedShip);
49
+ if (allows(reached)) {
50
+ return ok({});
51
+ }
52
+ await tx.reachRefusals.record({ ...refusal, id: ids('reachRefusal'), recipient: { kind: 'ship', ship: refused(reached) } });
53
+ return refuse('NOT_REACHABLE', NOT_REACHABLE_MESSAGE);
54
+ }
55
+ const NOT_REACHABLE_MESSAGE = 'The network rules do not allow this send';
56
+ /** The ship with the label values it carries now, by key then value, with their texts. */
57
+ async function shipAsItIs(tx, ship) {
58
+ const labels = [];
59
+ for (const carried of await tx.labels.carriedBy(ship.fleetId, ship.id)) {
60
+ const label = await tx.labels.find(ship.fleetId, carried.labelId);
61
+ const value = label?.values.find((held) => held.id === carried.valueId);
62
+ if (label && value) {
63
+ labels.push({ labelId: label.id, key: label.key, valueId: value.id, value: value.value });
64
+ }
65
+ }
66
+ labels.sort((first, second) => first.key.localeCompare(second.key) || first.value.localeCompare(second.value));
67
+ return { ship, labels };
68
+ }
69
+ function reaching({ ship, labels }) {
70
+ return { kind: ship.kind, labels: labels.map((label) => label.valueId) };
71
+ }
72
+ function refused({ ship, labels }) {
73
+ return { id: ship.id, name: ship.name, labels };
74
+ }
75
+ //# sourceMappingURL=check-reach.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-reach.js","sourceRoot":"","sources":["../../../src/domain/registry/check-reach.ts"],"names":[],"mappings":"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"}
@@ -5,13 +5,13 @@ import { type Result } from '../shared/result.js';
5
5
  import { type ListedShip } from './list-fleet.js';
6
6
  import { type CrewRequest } from './crew-request.js';
7
7
  import type { FleetListing } from './ports.js';
8
- import type { ShipReport } from './ship-report.js';
8
+ import { type ShownReport } from './ship-report.js';
9
9
  /** One ship for its page: as the fleet lists it, with its crew's report whole, when it was commissioned and since when it is crewed. */
10
10
  export interface ShipDetail extends Omit<ListedShip, 'report' | 'crewRequest'> {
11
11
  /** The ship's crew request, settings included; null when it holds none. */
12
12
  crewRequest: (NonNullable<ListedShip['crewRequest']> & Pick<CrewRequest, 'settings'>) | null;
13
- /** The crew's last report, details included; null until it reports, and while no session crews the ship. */
14
- report: ShipReport | null;
13
+ /** The crew's last report, details and their size included; null until it reports, and while no session crews the ship. */
14
+ report: ShownReport | null;
15
15
  commissionedAt: Date;
16
16
  /** Since when the session crewing it has held it; null while no session does. */
17
17
  crewedSince: Date | null;
@@ -2,6 +2,7 @@ import { refuse } from '../shared/errors.js';
2
2
  import { ok } from '../shared/result.js';
3
3
  import { listedShipOf } from './list-fleet.js';
4
4
  import { checkReaches } from './crew-request.js';
5
+ import { shownReportOf } from './ship-report.js';
5
6
  /** The scopes that read every ship; crew:run reads only the ships assigned to the caller's ship. */
6
7
  const READ_SCOPES = ['fleet:read'];
7
8
  /**
@@ -24,7 +25,7 @@ export function createGetShip(deps) {
24
25
  const counts = await deps.listing.deliveryCounts(caller.fleetId, shipId);
25
26
  return ok({
26
27
  ...listed,
27
- report: facts.openLease?.report ?? null,
28
+ report: facts.openLease?.report ? shownReportOf(facts.openLease.report) : null,
28
29
  crewRequest: listed.crewRequest && facts.crewRequest && { ...listed.crewRequest, settings: facts.crewRequest.settings },
29
30
  inFlightDeliveries: counts.inFlight,
30
31
  openDeliveries: counts.open,
@@ -1 +1 @@
1
- {"version":3,"file":"get-ship.js","sourceRoot":"","sources":["../../../src/domain/registry/get-ship.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAmB,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAoB,MAAM,mBAAmB,CAAC;AAwBnE,oGAAoG;AACpG,MAAM,WAAW,GAAG,CAAC,YAAY,CAAU,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAA+B;IAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAClC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,MAAM,CAAC,gBAAgB,EAAE,WAAW,MAAM,gBAAgB,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;QACjH,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACzE,OAAO,EAAE,CAAC;YACR,GAAG,MAAM;YACT,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,IAAI,IAAI;YACvC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,IAAI,EAAE,GAAG,MAAM,CAAC,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE;YACvH,kBAAkB,EAAE,MAAM,CAAC,QAAQ;YACnC,cAAc,EAAE,MAAM,CAAC,IAAI;YAC3B,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS;YACpC,WAAW,EAAE,KAAK,CAAC,SAAS,EAAE,SAAS,IAAI,IAAI;SAChD,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The fleet's network settings (decision 0034): which ships may send to
3
+ * which. A rule says that the ships matching one label selector may send to
4
+ * the ships matching another; allow-only, no deny rules, no precedence. A
5
+ * fleet holds its rules, or none (all-to-all), with a version that moves on
6
+ * every set, so a refusal names the settings that refused it.
7
+ */
8
+ import { type FleetId, type LabelValueId, type ShipKind } from '@aeolus-fleet/common';
9
+ import { type DomainError } from '../shared/errors.js';
10
+ import type { Actor, NewEvent } from '../shared/events.js';
11
+ import { type Result } from '../shared/result.js';
12
+ /** The ships carrying every one of these label values may send to the ships carrying every one of those. */
13
+ export interface NetworkRule {
14
+ from: readonly LabelValueId[];
15
+ to: readonly LabelValueId[];
16
+ }
17
+ export interface NetworkSettings {
18
+ fleetId: FleetId;
19
+ /** The rules every send is checked against; none is all-to-all, an empty list allows only the fixed exceptions. */
20
+ rules: readonly NetworkRule[] | null;
21
+ /** 0 until the fleet first sets rules; one more on every set. */
22
+ version: number;
23
+ }
24
+ /** A fleet that never set rules: none, at version 0. */
25
+ export declare function noNetworkSettings(fleetId: FleetId): NetworkSettings;
26
+ export type SetNetworkRulesRefusal = DomainError<'INVALID_NETWORK_RULES'>;
27
+ /**
28
+ * The fleet's rules from now on, replacing the ones it had, at the next
29
+ * version, with NetworkRulesSet. The rules are within the decision's limits:
30
+ * at most 200, each selector at most 20 label values, as a ship carries no
31
+ * more, each once. A value id need not exist: an unknown one matches no ship,
32
+ * as in label selection.
33
+ */
34
+ export declare function setNetworkRules(current: NetworkSettings, change: {
35
+ rules: readonly NetworkRule[] | null;
36
+ at: Date;
37
+ actor: Actor;
38
+ }): Result<{
39
+ settings: NetworkSettings;
40
+ events: NewEvent[];
41
+ }, SetNetworkRulesRefusal>;
42
+ /** A ship as a send's check sees it: its kind, for the argo exception, and the label values it carries. */
43
+ export interface ReachingShip {
44
+ kind: ShipKind;
45
+ labels: readonly LabelValueId[];
46
+ }
47
+ /**
48
+ * Whether the settings let the sender reach the recipient. With no rules,
49
+ * every ship reaches every ship. The fixed exceptions hold whatever the
50
+ * rules: argo reaches every ship and every ship reaches argo, and a ship
51
+ * answers the sender of a message it received. Otherwise a rule must match
52
+ * the sender with its `from` and the recipient with its `to`.
53
+ */
54
+ export declare function allowsReach(settings: NetworkSettings, send: {
55
+ sender: ReachingShip;
56
+ recipient: ReachingShip;
57
+ isAnswerToSender: boolean;
58
+ }): boolean;