@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.
- package/README.md +1 -1
- package/dist/adapters/http/request-credentials.d.ts +2 -9
- package/dist/adapters/http/request-credentials.js +8 -1
- package/dist/adapters/http/request-credentials.js.map +1 -1
- package/dist/adapters/http/server.js +2 -1
- package/dist/adapters/http/server.js.map +1 -1
- package/dist/adapters/mcp/mcp-endpoint.js +11 -1
- package/dist/adapters/mcp/mcp-endpoint.js.map +1 -1
- package/dist/adapters/prisma/generated/browser.d.ts +8 -0
- package/dist/adapters/prisma/generated/client.d.ts +8 -0
- package/dist/adapters/prisma/generated/enums.d.ts +2 -0
- package/dist/adapters/prisma/generated/enums.js +3 -1
- package/dist/adapters/prisma/generated/enums.js.map +1 -1
- package/dist/adapters/prisma/generated/internal/class.d.ts +11 -0
- package/dist/adapters/prisma/generated/internal/class.js +4 -4
- package/dist/adapters/prisma/generated/internal/class.js.map +1 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespace.d.ts +94 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespace.js +18 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespace.js.map +1 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.d.ts +18 -0
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js +18 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
- package/dist/adapters/prisma/generated/models/Delivery.d.ts +71 -1
- package/dist/adapters/prisma/generated/models/Fleet.d.ts +275 -0
- package/dist/adapters/prisma/generated/models/Lease.d.ts +113 -1
- package/dist/adapters/prisma/generated/models/NetworkSettings.d.ts +151 -19
- package/dist/adapters/prisma/generated/models/ReachRefusal.d.ts +71 -1
- package/dist/adapters/prisma/generated/models/ScopeNamespace.d.ts +1220 -0
- package/dist/adapters/prisma/generated/models/ScopeNamespace.js +2 -0
- package/dist/adapters/prisma/generated/models/ScopeNamespace.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Ship.d.ts +983 -55
- package/dist/adapters/prisma/generated/models.d.ts +1 -0
- package/dist/adapters/prisma/health.js +27 -7
- package/dist/adapters/prisma/health.js.map +1 -1
- package/dist/adapters/prisma/history.js +14 -70
- package/dist/adapters/prisma/history.js.map +1 -1
- package/dist/adapters/prisma/messaging.js +27 -34
- package/dist/adapters/prisma/messaging.js.map +1 -1
- package/dist/adapters/prisma/network.js +39 -12
- package/dist/adapters/prisma/network.js.map +1 -1
- package/dist/adapters/prisma/registry.js +65 -11
- package/dist/adapters/prisma/registry.js.map +1 -1
- package/dist/adapters/prisma/rows.d.ts +3 -0
- package/dist/adapters/prisma/rows.js +20 -7
- package/dist/adapters/prisma/rows.js.map +1 -1
- package/dist/adapters/prisma/scope-namespaces.d.ts +4 -0
- package/dist/adapters/prisma/scope-namespaces.js +39 -0
- package/dist/adapters/prisma/scope-namespaces.js.map +1 -0
- package/dist/adapters/prisma/unit-of-work.d.ts +2 -1
- package/dist/adapters/prisma/unit-of-work.js +2 -0
- package/dist/adapters/prisma/unit-of-work.js.map +1 -1
- package/dist/adapters/rest/rest-api.js +2 -2
- package/dist/adapters/rest/rest-api.js.map +1 -1
- package/dist/adapters/trpc/console.d.ts +1 -1
- package/dist/adapters/trpc/console.js +6 -4
- package/dist/adapters/trpc/console.js.map +1 -1
- package/dist/adapters/trpc/context.d.ts +20 -4
- package/dist/adapters/trpc/fleet.d.ts +179 -82
- package/dist/adapters/trpc/fleet.js +117 -53
- package/dist/adapters/trpc/fleet.js.map +1 -1
- package/dist/adapters/trpc/router.d.ts +231 -80
- package/dist/adapters/trpc/ship-contract.js +4 -0
- package/dist/adapters/trpc/ship-contract.js.map +1 -1
- package/dist/adapters/trpc/ship-protocol.js +7 -5
- package/dist/adapters/trpc/ship-protocol.js.map +1 -1
- package/dist/adapters/trpc/ship.d.ts +71 -3
- package/dist/adapters/trpc/ship.js +42 -5
- package/dist/adapters/trpc/ship.js.map +1 -1
- package/dist/adapters/trpc/trpc.d.ts +6 -5
- package/dist/adapters/trpc/trpc.js +76 -21
- package/dist/adapters/trpc/trpc.js.map +1 -1
- package/dist/domain/messaging/check-inbox.d.ts +5 -5
- package/dist/domain/messaging/check-inbox.js +9 -7
- package/dist/domain/messaging/check-inbox.js.map +1 -1
- package/dist/domain/messaging/dismiss-delivery.d.ts +9 -4
- package/dist/domain/messaging/dismiss-delivery.js +26 -19
- package/dist/domain/messaging/dismiss-delivery.js.map +1 -1
- package/dist/domain/messaging/message.d.ts +11 -5
- package/dist/domain/messaging/message.js +11 -4
- package/dist/domain/messaging/message.js.map +1 -1
- package/dist/domain/messaging/ping-ship.d.ts +3 -3
- package/dist/domain/messaging/ping-ship.js +6 -2
- package/dist/domain/messaging/ping-ship.js.map +1 -1
- package/dist/domain/messaging/ports.d.ts +9 -3
- package/dist/domain/messaging/receive-deliveries.d.ts +2 -0
- package/dist/domain/messaging/receive-deliveries.js +1 -0
- package/dist/domain/messaging/receive-deliveries.js.map +1 -1
- package/dist/domain/messaging/resend-delivery.d.ts +5 -2
- package/dist/domain/messaging/resend-delivery.js +8 -4
- package/dist/domain/messaging/resend-delivery.js.map +1 -1
- package/dist/domain/messaging/send-message.d.ts +9 -2
- package/dist/domain/messaging/send-message.js +12 -2
- package/dist/domain/messaging/send-message.js.map +1 -1
- package/dist/domain/messaging/send-request.d.ts +3 -1
- package/dist/domain/messaging/send-request.js +4 -2
- package/dist/domain/messaging/send-request.js.map +1 -1
- package/dist/domain/registry/assign-label.d.ts +2 -1
- package/dist/domain/registry/assign-label.js +3 -2
- package/dist/domain/registry/assign-label.js.map +1 -1
- package/dist/domain/registry/check-reach.d.ts +63 -4
- package/dist/domain/registry/check-reach.js +107 -11
- package/dist/domain/registry/check-reach.js.map +1 -1
- package/dist/domain/registry/commission-ship.d.ts +17 -8
- package/dist/domain/registry/commission-ship.js +24 -10
- package/dist/domain/registry/commission-ship.js.map +1 -1
- package/dist/domain/registry/crew-request.d.ts +1 -1
- package/dist/domain/registry/declare-scopes.d.ts +38 -0
- package/dist/domain/registry/declare-scopes.js +34 -0
- package/dist/domain/registry/declare-scopes.js.map +1 -0
- package/dist/domain/registry/declared-network-rules.d.ts +2 -1
- package/dist/domain/registry/declared-network-rules.js +11 -5
- package/dist/domain/registry/declared-network-rules.js.map +1 -1
- package/dist/domain/registry/discover.d.ts +28 -0
- package/dist/domain/registry/discover.js +54 -0
- package/dist/domain/registry/discover.js.map +1 -0
- package/dist/domain/registry/explain-reach.d.ts +12 -12
- package/dist/domain/registry/explain-reach.js +35 -12
- package/dist/domain/registry/explain-reach.js.map +1 -1
- package/dist/domain/registry/get-ship.d.ts +11 -3
- package/dist/domain/registry/get-ship.js +8 -2
- package/dist/domain/registry/get-ship.js.map +1 -1
- package/dist/domain/registry/get-starting-prompt.d.ts +18 -2
- package/dist/domain/registry/get-starting-prompt.js +7 -7
- package/dist/domain/registry/get-starting-prompt.js.map +1 -1
- package/dist/domain/registry/grant-scopes.d.ts +34 -0
- package/dist/domain/registry/grant-scopes.js +35 -0
- package/dist/domain/registry/grant-scopes.js.map +1 -0
- package/dist/domain/registry/label.d.ts +12 -7
- package/dist/domain/registry/label.js +21 -4
- package/dist/domain/registry/label.js.map +1 -1
- package/dist/domain/registry/list-fleet.d.ts +19 -6
- package/dist/domain/registry/list-fleet.js +18 -3
- package/dist/domain/registry/list-fleet.js.map +1 -1
- package/dist/domain/registry/list-scopes.d.ts +24 -0
- package/dist/domain/registry/list-scopes.js +22 -0
- package/dist/domain/registry/list-scopes.js.map +1 -0
- package/dist/domain/registry/managed-or-assigned.d.ts +25 -0
- package/dist/domain/registry/managed-or-assigned.js +23 -0
- package/dist/domain/registry/managed-or-assigned.js.map +1 -0
- package/dist/domain/registry/named-namespaces.d.ts +19 -0
- package/dist/domain/registry/named-namespaces.js +19 -0
- package/dist/domain/registry/named-namespaces.js.map +1 -0
- package/dist/domain/registry/network-settings.d.ts +84 -24
- package/dist/domain/registry/network-settings.js +134 -45
- package/dist/domain/registry/network-settings.js.map +1 -1
- package/dist/domain/registry/ports.d.ts +63 -1
- package/dist/domain/registry/public.d.ts +3 -2
- package/dist/domain/registry/public.js +3 -2
- package/dist/domain/registry/public.js.map +1 -1
- package/dist/domain/registry/reach-refusal.d.ts +12 -4
- package/dist/domain/registry/read-assigned-crew-requests.d.ts +12 -3
- package/dist/domain/registry/read-assigned-crew-requests.js +8 -8
- package/dist/domain/registry/read-assigned-crew-requests.js.map +1 -1
- package/dist/domain/registry/read-built-in-rules.d.ts +20 -0
- package/dist/domain/registry/read-built-in-rules.js +23 -0
- package/dist/domain/registry/read-built-in-rules.js.map +1 -0
- package/dist/domain/registry/read-clear-requests.d.ts +5 -3
- package/dist/domain/registry/read-clear-requests.js +7 -5
- package/dist/domain/registry/read-clear-requests.js.map +1 -1
- package/dist/domain/registry/read-on-behalf.d.ts +20 -0
- package/dist/domain/registry/read-on-behalf.js +31 -0
- package/dist/domain/registry/read-on-behalf.js.map +1 -0
- package/dist/domain/registry/read-reach.d.ts +62 -0
- package/dist/domain/registry/read-reach.js +78 -0
- package/dist/domain/registry/read-reach.js.map +1 -0
- package/dist/domain/registry/recrew-ship.d.ts +3 -2
- package/dist/domain/registry/recrew-ship.js +6 -1
- package/dist/domain/registry/recrew-ship.js.map +1 -1
- package/dist/domain/registry/release-ship.d.ts +6 -3
- package/dist/domain/registry/release-ship.js +7 -7
- package/dist/domain/registry/release-ship.js.map +1 -1
- package/dist/domain/registry/remove-crew-request.d.ts +4 -3
- package/dist/domain/registry/remove-crew-request.js +6 -1
- package/dist/domain/registry/remove-crew-request.js.map +1 -1
- package/dist/domain/registry/rename-ship.d.ts +7 -5
- package/dist/domain/registry/rename-ship.js +9 -3
- package/dist/domain/registry/rename-ship.js.map +1 -1
- package/dist/domain/registry/request-crew.d.ts +5 -4
- package/dist/domain/registry/request-crew.js +6 -1
- package/dist/domain/registry/request-crew.js.map +1 -1
- package/dist/domain/registry/request-worktree-clear.d.ts +3 -2
- package/dist/domain/registry/request-worktree-clear.js +6 -1
- package/dist/domain/registry/request-worktree-clear.js.map +1 -1
- package/dist/domain/registry/retire-ship.d.ts +16 -7
- package/dist/domain/registry/retire-ship.js +46 -5
- package/dist/domain/registry/retire-ship.js.map +1 -1
- package/dist/domain/registry/scope-grant.d.ts +53 -0
- package/dist/domain/registry/scope-grant.js +74 -0
- package/dist/domain/registry/scope-grant.js.map +1 -0
- package/dist/domain/registry/scope-namespace.d.ts +68 -0
- package/dist/domain/registry/scope-namespace.js +82 -0
- package/dist/domain/registry/scope-namespace.js.map +1 -0
- package/dist/domain/registry/set-built-in-rule.d.ts +28 -0
- package/dist/domain/registry/set-built-in-rule.js +33 -0
- package/dist/domain/registry/set-built-in-rule.js.map +1 -0
- package/dist/domain/registry/set-network-rules.d.ts +3 -3
- package/dist/domain/registry/set-network-rules.js +2 -2
- package/dist/domain/registry/set-owner.d.ts +30 -0
- package/dist/domain/registry/set-owner.js +37 -0
- package/dist/domain/registry/set-owner.js.map +1 -0
- package/dist/domain/registry/set-statement.d.ts +27 -0
- package/dist/domain/registry/set-statement.js +28 -0
- package/dist/domain/registry/set-statement.js.map +1 -0
- package/dist/domain/registry/ship.d.ts +70 -10
- package/dist/domain/registry/ship.js +95 -10
- package/dist/domain/registry/ship.js.map +1 -1
- package/dist/domain/registry/statement.d.ts +32 -0
- package/dist/domain/registry/statement.js +39 -0
- package/dist/domain/registry/statement.js.map +1 -0
- package/dist/domain/registry/unassign-label.js +1 -1
- package/dist/domain/registry/unassign-label.js.map +1 -1
- package/dist/domain/registry/whoami.d.ts +5 -1
- package/dist/domain/registry/whoami.js +7 -4
- package/dist/domain/registry/whoami.js.map +1 -1
- package/dist/domain/shared/caller.d.ts +5 -2
- package/dist/domain/shared/caller.js.map +1 -1
- package/dist/domain/shared/errors.d.ts +1 -1
- package/dist/domain/shared/errors.js.map +1 -1
- package/dist/domain/shared/events-read.d.ts +16 -0
- package/dist/domain/shared/events-read.js +15 -0
- package/dist/domain/shared/events-read.js.map +1 -0
- package/dist/domain/shared/follow-fleet.d.ts +8 -2
- package/dist/domain/shared/follow-fleet.js +14 -4
- package/dist/domain/shared/follow-fleet.js.map +1 -1
- package/dist/domain/shared/health.d.ts +9 -2
- package/dist/domain/shared/health.js +9 -3
- package/dist/domain/shared/health.js.map +1 -1
- package/dist/domain/shared/history.d.ts +9 -42
- package/dist/domain/shared/history.js +9 -0
- package/dist/domain/shared/history.js.map +1 -1
- package/dist/domain/shared/read-fleet-events.d.ts +8 -2
- package/dist/domain/shared/read-fleet-events.js +10 -4
- package/dist/domain/shared/read-fleet-events.js.map +1 -1
- package/dist/domain/shared/read-health.d.ts +4 -1
- package/dist/domain/shared/read-health.js +7 -2
- package/dist/domain/shared/read-health.js.map +1 -1
- package/dist/domain/shared/read-inbox.d.ts +6 -3
- package/dist/domain/shared/read-inbox.js +14 -4
- package/dist/domain/shared/read-inbox.js.map +1 -1
- package/dist/domain/shared/read-message.d.ts +6 -2
- package/dist/domain/shared/read-message.js +6 -2
- package/dist/domain/shared/read-message.js.map +1 -1
- package/dist/domain/shared/read-needs-attention.d.ts +4 -1
- package/dist/domain/shared/read-needs-attention.js +8 -3
- package/dist/domain/shared/read-needs-attention.js.map +1 -1
- package/dist/domain/shared/read-ship-messages.d.ts +6 -2
- package/dist/domain/shared/read-ship-messages.js +7 -2
- package/dist/domain/shared/read-ship-messages.js.map +1 -1
- package/dist/domain/shared/read-ship-timeline.d.ts +5 -2
- package/dist/domain/shared/read-ship-timeline.js +11 -6
- package/dist/domain/shared/read-ship-timeline.js.map +1 -1
- package/dist/domain/shared/read-ship-way.d.ts +11 -4
- package/dist/domain/shared/read-ship-way.js +9 -2
- package/dist/domain/shared/read-ship-way.js.map +1 -1
- package/dist/domain/shared/stuck.d.ts +10 -1
- package/dist/domain/shared/stuck.js +1 -1
- package/dist/domain/shared/stuck.js.map +1 -1
- package/dist/wiring.d.ts +18 -4
- package/dist/wiring.js +37 -18
- package/dist/wiring.js.map +1 -1
- package/package.json +2 -2
- package/src/adapters/prisma/migrations/20261018100000_force_scope/migration.sql +8 -0
- package/src/adapters/prisma/migrations/20261018110000_forced_delivery/migration.sql +4 -0
- package/src/adapters/prisma/migrations/20261018120000_person_and_app_ships/migration.sql +3 -0
- package/src/adapters/prisma/migrations/20261018130000_owners/migration.sql +14 -0
- package/src/adapters/prisma/migrations/20261018140000_owners_on_reach_refusals/migration.sql +14 -0
- package/src/adapters/prisma/migrations/20261018150000_network_verbs/migration.sql +9 -0
- package/src/adapters/prisma/migrations/20261018160000_built_in_rules/migration.sql +13 -0
- package/src/adapters/prisma/migrations/20261018170000_network_rules_a_list/migration.sql +5 -0
- package/src/adapters/prisma/migrations/20261018180000_verb_on_reach_refusals/migration.sql +4 -0
- package/src/adapters/prisma/migrations/20261018200000_lease_statements/migration.sql +3 -0
- package/src/adapters/prisma/migrations/20261018210000_declare_and_grant_scopes/migration.sql +8 -0
- package/src/adapters/prisma/migrations/20261018220000_plugin_scopes/migration.sql +14 -0
- package/src/adapters/prisma/migrations/20261018230000_scope_namespaces/migration.sql +20 -0
- package/src/adapters/prisma/migrations/20261018240000_trierarch_plugin_crew_run/migration.sql +44 -0
- package/src/adapters/prisma/migrations/20261018250000_scope_catalogue/migration.sql +66 -0
- package/src/adapters/prisma/migrations/20261019090000_reach_refusal_asked_by/migration.sql +2 -0
- package/src/adapters/prisma/migrations/20261019100000_on_behalf_scope/migration.sql +59 -0
- package/src/adapters/prisma/migrations/20261019110000_events_fleet_id_occurred_at/migration.sql +2 -0
- package/src/adapters/prisma/schema.prisma +47 -2
- package/dist/domain/shared/read-no-ship-can-take.d.ts +0 -13
- package/dist/domain/shared/read-no-ship-can-take.js +0 -12
- package/dist/domain/shared/read-no-ship-can-take.js.map +0 -1
- package/dist/domain/shared/read-overdue.d.ts +0 -13
- package/dist/domain/shared/read-overdue.js +0 -12
- package/dist/domain/shared/read-overdue.js.map +0 -1
|
@@ -18,7 +18,8 @@ export type AssignLabel = (caller: Caller, input: {
|
|
|
18
18
|
valueId: LabelValueId;
|
|
19
19
|
}) => Promise<Result<undefined, AssignLabelFailure>>;
|
|
20
20
|
/**
|
|
21
|
-
* Use case: a label's owner gives a ship one of its values, by the value's id (decision 0031)
|
|
21
|
+
* Use case: a label's owner gives a ship one of its values, by the value's id (decision 0031):
|
|
22
|
+
* its own ship or one it commissioned, argo any (decision 0046).
|
|
22
23
|
* Its scope (labels:assign) is checked before this runs. In one unit of
|
|
23
24
|
* work, locking the ship first, as a retire does, so two assignments to one
|
|
24
25
|
* ship take turns at its label limit and a retired ship gets none; then
|
|
@@ -3,7 +3,8 @@ import { recordEvent, shipActor } from '../shared/events.js';
|
|
|
3
3
|
import { ok } from '../shared/result.js';
|
|
4
4
|
import { assignLabel } from './label.js';
|
|
5
5
|
/**
|
|
6
|
-
* Use case: a label's owner gives a ship one of its values, by the value's id (decision 0031)
|
|
6
|
+
* Use case: a label's owner gives a ship one of its values, by the value's id (decision 0031):
|
|
7
|
+
* its own ship or one it commissioned, argo any (decision 0046).
|
|
7
8
|
* Its scope (labels:assign) is checked before this runs. In one unit of
|
|
8
9
|
* work, locking the ship first, as a retire does, so two assignments to one
|
|
9
10
|
* ship take turns at its label limit and a retired ship gets none; then
|
|
@@ -23,7 +24,7 @@ export function createAssignLabel(deps) {
|
|
|
23
24
|
return refuse('LABEL_VALUE_NOT_FOUND', `The fleet has no label value ${input.valueId}`);
|
|
24
25
|
}
|
|
25
26
|
const owner = await tx.ships.find(fleetId, label.ownerShipId);
|
|
26
|
-
const assigned = assignLabel({ label, ownerName: owner?.name ?? label.ownerShipId, ship, carried: await tx.labels.carriedBy(fleetId, ship.id) }, { callerShipId: caller.shipId, valueId: input.valueId, at: deps.clock.now(), actor: shipActor(caller.shipId) });
|
|
27
|
+
const assigned = assignLabel({ label, ownerName: owner?.name ?? label.ownerShipId, ship, carried: await tx.labels.carriedBy(fleetId, ship.id) }, { callerShipId: caller.shipId, callerKind: caller.kind, valueId: input.valueId, at: deps.clock.now(), actor: shipActor(caller.shipId) });
|
|
27
28
|
if (!assigned.isOk) {
|
|
28
29
|
return assigned;
|
|
29
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assign-label.js","sourceRoot":"","sources":["../../../src/domain/registry/assign-label.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAA2B,MAAM,YAAY,CAAC;AAalE
|
|
1
|
+
{"version":3,"file":"assign-label.js","sourceRoot":"","sources":["../../../src/domain/registry/assign-label.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAA2B,MAAM,YAAY,CAAC;AAalE;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAwE;IACxG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAkD,EAAE;QACxE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,KAAK,CAAC,MAAM,iBAAiB,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1E,sFAAsF;QACtF,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/D,OAAO,MAAM,CAAC,uBAAuB,EAAE,gCAAgC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,WAAW,CAC1B,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,EAClH,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CACxI,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,IAAI,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YAC9B,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACpD,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { FleetId, IdGenerator, ShipId } from '@aeolus-fleet/common';
|
|
2
2
|
import { type DomainError } from '../shared/errors.js';
|
|
3
3
|
import { type Result } from '../shared/result.js';
|
|
4
|
+
import type { UnitOfWork } from '../shared/unit-of-work.js';
|
|
4
5
|
import type { Recipient } from '../shared/selector.js';
|
|
5
6
|
import type { CarriedLabel } from './label.js';
|
|
6
7
|
import { type NetworkSettings, type ReachingShip, type RulesInForce } from './network-settings.js';
|
|
@@ -28,8 +29,9 @@ export interface Reach {
|
|
|
28
29
|
* that comes after it is checked against the new version.
|
|
29
30
|
*
|
|
30
31
|
* For a type, the ships of it the sender may reach now are the ones that may
|
|
31
|
-
* claim the delivery, fixed here; none of them refuses the send. With
|
|
32
|
-
*
|
|
32
|
+
* claim the delivery, fixed here; none of them refuses the send. With open
|
|
33
|
+
* on for send, or from argo, who reaches every ship, any ship of the type
|
|
34
|
+
* may.
|
|
33
35
|
*
|
|
34
36
|
* A refusal is recorded here, in the send's unit of work, with the ships and
|
|
35
37
|
* the label values they carry now and the settings version: the send stores
|
|
@@ -49,6 +51,55 @@ export declare function checkReach(deps: {
|
|
|
49
51
|
isAnswerToSender: boolean;
|
|
50
52
|
at: Date;
|
|
51
53
|
}): Promise<Result<Reach, NotReachable>>;
|
|
54
|
+
/** The ports a read's reach check reads and writes, inside the read's unit of work. */
|
|
55
|
+
export type CheckReadTx = Omit<CheckReachTx, 'ships'> & {
|
|
56
|
+
ships: Pick<ShipRepository, 'find'>;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Whether the read rules let the reader read one ship now, for a read that
|
|
60
|
+
* a ship outside read reach refuses rather than filters (decision 0034). A
|
|
61
|
+
* ship always reads itself. A refusal is recorded here, in the read's unit of
|
|
62
|
+
* work, as a send's is, with the verb read: its caller commits only the record.
|
|
63
|
+
*/
|
|
64
|
+
export declare function checkRead(deps: {
|
|
65
|
+
tx: CheckReadTx;
|
|
66
|
+
ids: IdGenerator;
|
|
67
|
+
}, read: {
|
|
68
|
+
fleetId: FleetId;
|
|
69
|
+
readerShipId: ShipId;
|
|
70
|
+
askedBy: ShipId | null;
|
|
71
|
+
shipId: ShipId;
|
|
72
|
+
at: Date;
|
|
73
|
+
}): Promise<Result<undefined, NotReachable>>;
|
|
74
|
+
/** The ports a manage call's reach check reads and writes, inside the call's unit of work. */
|
|
75
|
+
export type CheckManageTx = CheckReadTx;
|
|
76
|
+
/**
|
|
77
|
+
* Whether the manage rules let the manager manage the ship now (decision
|
|
78
|
+
* 0034): every fleet:manage call is checked on its target ship, argo
|
|
79
|
+
* reaching every ship and an owner's ship the ships it owns. A refusal is
|
|
80
|
+
* recorded here, in the call's unit of work, with the verb manage: its caller
|
|
81
|
+
* commits only the record. A call that already holds the fleet's network
|
|
82
|
+
* settings for update hands them in, so the check takes no second lock on
|
|
83
|
+
* them.
|
|
84
|
+
*/
|
|
85
|
+
export declare function checkManage(deps: {
|
|
86
|
+
tx: CheckManageTx;
|
|
87
|
+
ids: IdGenerator;
|
|
88
|
+
}, manage: {
|
|
89
|
+
fleetId: FleetId;
|
|
90
|
+
managerShipId: ShipId;
|
|
91
|
+
shipId: ShipId;
|
|
92
|
+
at: Date;
|
|
93
|
+
settings?: NetworkSettings;
|
|
94
|
+
}): Promise<Result<undefined, NotReachable>>;
|
|
95
|
+
/**
|
|
96
|
+
* Runs a call in one unit of work that commits the record of a reach
|
|
97
|
+
* refusal: refused by the network rules, the call stores nothing but that
|
|
98
|
+
* record and answers the refusal; any other refusal rolls everything back.
|
|
99
|
+
*/
|
|
100
|
+
export declare function keepingReachRefusal<Tx, T, E extends {
|
|
101
|
+
kind: string;
|
|
102
|
+
}>(uow: UnitOfWork<Tx>, work: (tx: Tx) => Promise<Result<T, E | NotReachable>>): Promise<Result<T, E | NotReachable>>;
|
|
52
103
|
/** The rules in force at the send: the plugin's crew last seen, read without a lock, says whether it responds. */
|
|
53
104
|
export declare function rulesInForceAt(tx: Pick<CheckReachTx, 'leases'>, at: {
|
|
54
105
|
settings: NetworkSettings;
|
|
@@ -57,7 +108,15 @@ export declare function rulesInForceAt(tx: Pick<CheckReachTx, 'leases'>, at: {
|
|
|
57
108
|
export interface ShipAsItIs {
|
|
58
109
|
ship: Ship;
|
|
59
110
|
labels: CarriedLabel[];
|
|
111
|
+
/** Its owner's ship by id and name, none for argo and the viewer (decision 0045). */
|
|
112
|
+
owner: {
|
|
113
|
+
id: ShipId;
|
|
114
|
+
name: string;
|
|
115
|
+
} | null;
|
|
60
116
|
}
|
|
61
|
-
/** The ship with the label values it carries now, by key then value, with their texts. */
|
|
62
|
-
export declare function shipAsItIs(tx:
|
|
117
|
+
/** The ship with the label values it carries now, by key then value, with their texts, and its owner. */
|
|
118
|
+
export declare function shipAsItIs(tx: {
|
|
119
|
+
labels: CheckReachTx['labels'];
|
|
120
|
+
ships: Pick<ShipRepository, 'find'>;
|
|
121
|
+
}, ship: Ship): Promise<ShipAsItIs>;
|
|
63
122
|
export declare function reaching({ ship, labels }: ShipAsItIs): ReachingShip;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { refuse } from '../shared/errors.js';
|
|
2
|
-
import { ok } from '../shared/result.js';
|
|
2
|
+
import { err, ok } from '../shared/result.js';
|
|
3
3
|
import { allowsReach, isNetworkPluginResponding, rulesInForce } from './network-settings.js';
|
|
4
4
|
/**
|
|
5
5
|
* Whether the fleet's network rules let the sender reach the recipient a
|
|
@@ -9,8 +9,9 @@ import { allowsReach, isNetworkPluginResponding, rulesInForce } from './network-
|
|
|
9
9
|
* that comes after it is checked against the new version.
|
|
10
10
|
*
|
|
11
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
|
|
13
|
-
*
|
|
12
|
+
* claim the delivery, fixed here; none of them refuses the send. With open
|
|
13
|
+
* on for send, or from argo, who reaches every ship, any ship of the type
|
|
14
|
+
* may.
|
|
14
15
|
*
|
|
15
16
|
* A refusal is recorded here, in the send's unit of work, with the ships and
|
|
16
17
|
* the label values they carry now and the settings version: the send stores
|
|
@@ -26,12 +27,12 @@ export async function checkReach(deps, send) {
|
|
|
26
27
|
const settings = await tx.networkSettings.findForShare(fleetId);
|
|
27
28
|
const inForce = await rulesInForceAt(tx, { settings, now: send.at });
|
|
28
29
|
const senderShip = await tx.ships.find(fleetId, send.senderShipId);
|
|
29
|
-
if (inForce.
|
|
30
|
+
if (inForce.builtIns.open.send || !senderShip || senderShip.kind === 'operator') {
|
|
30
31
|
return ok({});
|
|
31
32
|
}
|
|
32
33
|
const sender = await shipAsItIs(tx, senderShip);
|
|
33
|
-
const allows = (to) => allowsReach(inForce, { sender: reaching(sender), recipient: reaching(to), isAnswerToSender: send.isAnswerToSender });
|
|
34
|
-
const refusal = { fleetId, at: send.at, sender: refused(sender), settingsVersion: settings.version, whilePluginUnavailable: inForce.whilePluginUnavailable };
|
|
34
|
+
const allows = (to) => allowsReach(inForce, { verb: 'send', sender: reaching(sender), recipient: reaching(to), isAnswerToSender: send.isAnswerToSender });
|
|
35
|
+
const refusal = { fleetId, at: send.at, sender: refused(sender), askedBy: null, verb: 'send', settingsVersion: settings.version, whilePluginUnavailable: inForce.whilePluginUnavailable };
|
|
35
36
|
if (recipient.kind === 'type') {
|
|
36
37
|
const ships = [];
|
|
37
38
|
for (const ship of await tx.ships.listActiveOfType(fleetId, recipient.type)) {
|
|
@@ -57,6 +58,100 @@ export async function checkReach(deps, send) {
|
|
|
57
58
|
return refuse('NOT_REACHABLE', NOT_REACHABLE_MESSAGE);
|
|
58
59
|
}
|
|
59
60
|
const NOT_REACHABLE_MESSAGE = 'The network rules do not allow this send';
|
|
61
|
+
/**
|
|
62
|
+
* Whether the read rules let the reader read one ship now, for a read that
|
|
63
|
+
* a ship outside read reach refuses rather than filters (decision 0034). A
|
|
64
|
+
* ship always reads itself. A refusal is recorded here, in the read's unit of
|
|
65
|
+
* work, as a send's is, with the verb read: its caller commits only the record.
|
|
66
|
+
*/
|
|
67
|
+
export async function checkRead(deps, read) {
|
|
68
|
+
const { tx, ids } = deps;
|
|
69
|
+
const { fleetId, at } = read;
|
|
70
|
+
const settings = await tx.networkSettings.findForShare(fleetId);
|
|
71
|
+
const inForce = await rulesInForceAt(tx, { settings, now: at });
|
|
72
|
+
const readerShip = await tx.ships.find(fleetId, read.readerShipId);
|
|
73
|
+
const readShip = await tx.ships.find(fleetId, read.shipId);
|
|
74
|
+
if (!readerShip || !readShip || readerShip.id === readShip.id) {
|
|
75
|
+
return ok(undefined);
|
|
76
|
+
}
|
|
77
|
+
const reader = await shipAsItIs(tx, readerShip);
|
|
78
|
+
const ship = await shipAsItIs(tx, readShip);
|
|
79
|
+
if (allowsReach(inForce, { verb: 'read', sender: reaching(reader), recipient: reaching(ship), isAnswerToSender: false })) {
|
|
80
|
+
return ok(undefined);
|
|
81
|
+
}
|
|
82
|
+
const askedBy = read.askedBy === null ? undefined : await tx.ships.find(fleetId, read.askedBy);
|
|
83
|
+
await tx.reachRefusals.record({
|
|
84
|
+
fleetId,
|
|
85
|
+
id: ids('reachRefusal'),
|
|
86
|
+
at,
|
|
87
|
+
sender: refused(reader),
|
|
88
|
+
askedBy: askedBy ? refused(await shipAsItIs(tx, askedBy)) : null,
|
|
89
|
+
recipient: { kind: 'ship', ship: refused(ship) },
|
|
90
|
+
verb: 'read',
|
|
91
|
+
settingsVersion: settings.version,
|
|
92
|
+
whilePluginUnavailable: inForce.whilePluginUnavailable,
|
|
93
|
+
});
|
|
94
|
+
return refuse('NOT_REACHABLE', 'The network rules do not allow this read');
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Whether the manage rules let the manager manage the ship now (decision
|
|
98
|
+
* 0034): every fleet:manage call is checked on its target ship, argo
|
|
99
|
+
* reaching every ship and an owner's ship the ships it owns. A refusal is
|
|
100
|
+
* recorded here, in the call's unit of work, with the verb manage: its caller
|
|
101
|
+
* commits only the record. A call that already holds the fleet's network
|
|
102
|
+
* settings for update hands them in, so the check takes no second lock on
|
|
103
|
+
* them.
|
|
104
|
+
*/
|
|
105
|
+
export async function checkManage(deps, manage) {
|
|
106
|
+
const { tx, ids } = deps;
|
|
107
|
+
const { fleetId, at } = manage;
|
|
108
|
+
const settings = manage.settings ?? (await tx.networkSettings.findForShare(fleetId));
|
|
109
|
+
const inForce = await rulesInForceAt(tx, { settings, now: at });
|
|
110
|
+
const managerShip = await tx.ships.find(fleetId, manage.managerShipId);
|
|
111
|
+
const managedShip = await tx.ships.find(fleetId, manage.shipId);
|
|
112
|
+
if (!managerShip || !managedShip) {
|
|
113
|
+
return ok(undefined);
|
|
114
|
+
}
|
|
115
|
+
const manager = await shipAsItIs(tx, managerShip);
|
|
116
|
+
const ship = await shipAsItIs(tx, managedShip);
|
|
117
|
+
if (allowsReach(inForce, { verb: 'manage', sender: reaching(manager), recipient: reaching(ship), isAnswerToSender: false })) {
|
|
118
|
+
return ok(undefined);
|
|
119
|
+
}
|
|
120
|
+
await tx.reachRefusals.record({
|
|
121
|
+
fleetId,
|
|
122
|
+
id: ids('reachRefusal'),
|
|
123
|
+
at,
|
|
124
|
+
sender: refused(manager),
|
|
125
|
+
askedBy: null,
|
|
126
|
+
recipient: { kind: 'ship', ship: refused(ship) },
|
|
127
|
+
verb: 'manage',
|
|
128
|
+
settingsVersion: settings.version,
|
|
129
|
+
whilePluginUnavailable: inForce.whilePluginUnavailable,
|
|
130
|
+
});
|
|
131
|
+
return refuse('NOT_REACHABLE', 'The network rules do not allow this manage');
|
|
132
|
+
}
|
|
133
|
+
/** Whether a refusal is the reach check's: its record commits, though the call is refused. */
|
|
134
|
+
function isNotReachable(error) {
|
|
135
|
+
return error.kind === 'NOT_REACHABLE';
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Runs a call in one unit of work that commits the record of a reach
|
|
139
|
+
* refusal: refused by the network rules, the call stores nothing but that
|
|
140
|
+
* record and answers the refusal; any other refusal rolls everything back.
|
|
141
|
+
*/
|
|
142
|
+
export async function keepingReachRefusal(uow, work) {
|
|
143
|
+
const outcome = await uow.run(async (tx) => {
|
|
144
|
+
const done = await work(tx);
|
|
145
|
+
if (done.isOk) {
|
|
146
|
+
return ok({ done: done.value });
|
|
147
|
+
}
|
|
148
|
+
return isNotReachable(done.error) ? ok({ prevented: done.error }) : err(done.error);
|
|
149
|
+
});
|
|
150
|
+
if (!outcome.isOk) {
|
|
151
|
+
return outcome;
|
|
152
|
+
}
|
|
153
|
+
return 'prevented' in outcome.value ? err(outcome.value.prevented) : ok(outcome.value.done);
|
|
154
|
+
}
|
|
60
155
|
/** The rules in force at the send: the plugin's crew last seen, read without a lock, says whether it responds. */
|
|
61
156
|
export async function rulesInForceAt(tx, at) {
|
|
62
157
|
const { settings, now } = at;
|
|
@@ -67,7 +162,7 @@ export async function rulesInForceAt(tx, at) {
|
|
|
67
162
|
const lastSeenAt = await tx.leases.findLastSeen(settings.fleetId, plugin.shipId);
|
|
68
163
|
return rulesInForce(settings, isNetworkPluginResponding(plugin, { lastSeenAt, now }));
|
|
69
164
|
}
|
|
70
|
-
/** The ship with the label values it carries now, by key then value, with their texts. */
|
|
165
|
+
/** The ship with the label values it carries now, by key then value, with their texts, and its owner. */
|
|
71
166
|
export async function shipAsItIs(tx, ship) {
|
|
72
167
|
const labels = [];
|
|
73
168
|
for (const carried of await tx.labels.carriedBy(ship.fleetId, ship.id)) {
|
|
@@ -78,12 +173,13 @@ export async function shipAsItIs(tx, ship) {
|
|
|
78
173
|
}
|
|
79
174
|
}
|
|
80
175
|
labels.sort((first, second) => first.key.localeCompare(second.key) || first.value.localeCompare(second.value));
|
|
81
|
-
|
|
176
|
+
const owner = ship.owner === null ? undefined : await tx.ships.find(ship.fleetId, ship.owner);
|
|
177
|
+
return { ship, labels, owner: owner ? { id: owner.id, name: owner.name } : null };
|
|
82
178
|
}
|
|
83
179
|
export function reaching({ ship, labels }) {
|
|
84
|
-
return { kind: ship.kind, labels: labels.map(({ labelId, valueId }) => ({ labelId, valueId })) };
|
|
180
|
+
return { id: ship.id, owner: ship.owner, kind: ship.kind, labels: labels.map(({ labelId, valueId }) => ({ labelId, valueId })) };
|
|
85
181
|
}
|
|
86
|
-
function refused({ ship, labels }) {
|
|
87
|
-
return { id: ship.id, name: ship.name, labels };
|
|
182
|
+
function refused({ ship, labels, owner }) {
|
|
183
|
+
return { id: ship.id, name: ship.name, labels, owner };
|
|
88
184
|
}
|
|
89
185
|
//# sourceMappingURL=check-reach.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-reach.js","sourceRoot":"","sources":["../../../src/domain/registry/check-reach.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"check-reach.js","sourceRoot":"","sources":["../../../src/domain/registry/check-reach.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { CommissionedShipKind, IdGenerator, ShipId } from '@aeolus-fleet/common';
|
|
2
2
|
import type { SecretTools } from '../identity/public.js';
|
|
3
3
|
import type { Caller } from '../shared/caller.js';
|
|
4
4
|
import type { Clock } from '../shared/clock.js';
|
|
@@ -6,17 +6,22 @@ import { type DomainError } from '../shared/errors.js';
|
|
|
6
6
|
import { type Result } from '../shared/result.js';
|
|
7
7
|
import type { UnitOfWork } from '../shared/unit-of-work.js';
|
|
8
8
|
import { type AppliedLimitsTx } from './applied-limits.js';
|
|
9
|
+
import { type NamedNamespacesTx } from './named-namespaces.js';
|
|
9
10
|
import type { ShipRepository } from './ports.js';
|
|
10
11
|
import { type CommissionRefusal } from './ship.js';
|
|
11
12
|
import { type StartingPromptTx } from './starting-prompt.js';
|
|
12
|
-
export interface CommissionShipTx extends StartingPromptTx, AppliedLimitsTx {
|
|
13
|
+
export interface CommissionShipTx extends StartingPromptTx, AppliedLimitsTx, NamedNamespacesTx {
|
|
13
14
|
ships: ShipRepository;
|
|
14
15
|
}
|
|
15
16
|
export interface CommissionShipInput {
|
|
16
17
|
name: string;
|
|
17
18
|
type: string;
|
|
19
|
+
/** An agent when left out; only argo commissions a person or app ship (decision 0044). */
|
|
20
|
+
kind?: CommissionedShipKind;
|
|
18
21
|
note?: string;
|
|
19
|
-
|
|
22
|
+
scopes?: readonly string[];
|
|
23
|
+
/** The ship that asked the caller, a plugin's ship holding fleet:on-behalf, for this one: the new ship gets its owner (decision 0045). */
|
|
24
|
+
ownerOf?: ShipId;
|
|
20
25
|
/** The caller's own key for this commission, so a retry never commissions twice. */
|
|
21
26
|
idempotencyKey: string;
|
|
22
27
|
}
|
|
@@ -34,14 +39,18 @@ export interface CommissionedShip {
|
|
|
34
39
|
isClaimed: boolean;
|
|
35
40
|
} | null;
|
|
36
41
|
}
|
|
37
|
-
export type CommissionShipRefusal = CommissionRefusal | DomainError<'INVALID_IDEMPOTENCY_KEY' | 'IDEMPOTENCY_KEY_REUSED' | 'SHIP_LIMIT_REACHED'>;
|
|
42
|
+
export type CommissionShipRefusal = CommissionRefusal | DomainError<'INVALID_IDEMPOTENCY_KEY' | 'IDEMPOTENCY_KEY_REUSED' | 'SHIP_LIMIT_REACHED' | 'SHIP_NOT_FOUND'>;
|
|
38
43
|
export type CommissionShip = (caller: Caller, input: CommissionShipInput) => Promise<Result<CommissionedShip, CommissionShipRefusal>>;
|
|
39
44
|
/**
|
|
40
|
-
* Use case: the caller commissions
|
|
45
|
+
* Use case: the caller commissions a ship in its own fleet, an agent unless
|
|
46
|
+
* it states another kind (only argo commissions a person or app ship). The ship
|
|
41
47
|
* awaits crew and gets its first starting prompt, all in one transaction. The
|
|
42
|
-
* caller's scope (fleet:
|
|
43
|
-
* the agent scopes and
|
|
44
|
-
*
|
|
48
|
+
* caller's scope (fleet:commission) is checked before this runs. The ship gets
|
|
49
|
+
* the agent scopes and the scopes asked for, each one the caller's ship may
|
|
50
|
+
* grant, read from the server (decision 0046); each plugin namespace they
|
|
51
|
+
* name is locked after the name. Its owner is the caller's owner; a caller
|
|
52
|
+
* holding fleet:on-behalf may name the ship that asked it instead, whose owner
|
|
53
|
+
* it gets (decision 0045). The caller's idempotency key makes
|
|
45
54
|
* a retry safe: the same key with the same request answers the ship it
|
|
46
55
|
* commissioned, with no secret, and changes nothing; the same key with another
|
|
47
56
|
* request is refused.
|
|
@@ -1,22 +1,26 @@
|
|
|
1
|
-
import { FLEET_SCOPES } from '@aeolus-fleet/common';
|
|
2
1
|
import { refuse } from '../shared/errors.js';
|
|
3
2
|
import { recordEvent, shipActor } from '../shared/events.js';
|
|
4
3
|
import { idempotencyKey } from '../shared/idempotency-key.js';
|
|
5
4
|
import { ok } from '../shared/result.js';
|
|
6
5
|
import { appliedLimits } from './applied-limits.js';
|
|
7
|
-
import {
|
|
6
|
+
import { lockNamedNamespaces } from './named-namespaces.js';
|
|
7
|
+
import { commissionShip } from './ship.js';
|
|
8
8
|
import { issueStartingPrompt } from './starting-prompt.js';
|
|
9
|
-
/** The request as one text, so a repeat is known by its hash: the
|
|
9
|
+
/** The request as one text, so a repeat is known by its hash: the scopes in a fixed order, each once. */
|
|
10
10
|
function commissionRequestText(input) {
|
|
11
|
-
const
|
|
12
|
-
return JSON.stringify({ name: input.name, type: input.type, note: input.note ?? null,
|
|
11
|
+
const scopes = [...new Set(input.scopes)].toSorted();
|
|
12
|
+
return JSON.stringify({ name: input.name, type: input.type, kind: input.kind ?? 'agent', note: input.note ?? null, scopes, ownerOf: input.ownerOf ?? null });
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* Use case: the caller commissions
|
|
15
|
+
* Use case: the caller commissions a ship in its own fleet, an agent unless
|
|
16
|
+
* it states another kind (only argo commissions a person or app ship). The ship
|
|
16
17
|
* awaits crew and gets its first starting prompt, all in one transaction. The
|
|
17
|
-
* caller's scope (fleet:
|
|
18
|
-
* the agent scopes and
|
|
19
|
-
*
|
|
18
|
+
* caller's scope (fleet:commission) is checked before this runs. The ship gets
|
|
19
|
+
* the agent scopes and the scopes asked for, each one the caller's ship may
|
|
20
|
+
* grant, read from the server (decision 0046); each plugin namespace they
|
|
21
|
+
* name is locked after the name. Its owner is the caller's owner; a caller
|
|
22
|
+
* holding fleet:on-behalf may name the ship that asked it instead, whose owner
|
|
23
|
+
* it gets (decision 0045). The caller's idempotency key makes
|
|
20
24
|
* a retry safe: the same key with the same request answers the ship it
|
|
21
25
|
* commissioned, with no secret, and changes nothing; the same key with another
|
|
22
26
|
* request is refused.
|
|
@@ -53,8 +57,18 @@ export function createCommissionShip(deps) {
|
|
|
53
57
|
return refuse('SHIP_LIMIT_REACHED', `The fleet is at its limit of ${String(shipLimit)} ships, so it takes no new one.`);
|
|
54
58
|
}
|
|
55
59
|
}
|
|
60
|
+
const commissioner = await tx.ships.find(fleetId, caller.shipId);
|
|
61
|
+
const argo = await tx.ships.findOperatorShip(fleetId);
|
|
62
|
+
if (!commissioner || !argo) {
|
|
63
|
+
return refuse('SHIP_NOT_FOUND', `Ship ${caller.shipId} or its fleet's argo does not exist`);
|
|
64
|
+
}
|
|
65
|
+
const askingShip = input.ownerOf === undefined ? undefined : await tx.ships.find(fleetId, input.ownerOf);
|
|
66
|
+
if (input.ownerOf !== undefined && askingShip === undefined) {
|
|
67
|
+
return refuse('SHIP_NOT_FOUND', `Ship ${input.ownerOf}, named as the ship that asked, does not exist`);
|
|
68
|
+
}
|
|
56
69
|
await tx.ships.lockName(fleetId, input.name);
|
|
57
|
-
const
|
|
70
|
+
const namespaces = await lockNamedNamespaces(tx, { fleetId, scopes: input.scopes ?? [] });
|
|
71
|
+
const commissioned = commissionShip({ ...input, id: deps.ids('ship'), fleetId, commissioner, argoShipId: argo.id, askingShip, at, actor, commission: { by: caller.shipId, idempotencyKey: key.value, requestHash } }, { activeShipNamed: await tx.ships.findActiveByName(fleetId, input.name), namespaces });
|
|
58
72
|
if (!commissioned.isOk) {
|
|
59
73
|
return commissioned;
|
|
60
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commission-ship.js","sourceRoot":"","sources":["../../../src/domain/registry/commission-ship.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"commission-ship.js","sourceRoot":"","sources":["../../../src/domain/registry/commission-ship.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAwB,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAA0B,MAAM,uBAAuB,CAAC;AAEpF,OAAO,EAAE,cAAc,EAA0B,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAyB,MAAM,sBAAsB,CAAC;AAqClF,yGAAyG;AACzG,SAAS,qBAAqB,CAAC,KAA0B;IACvD,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACrD,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC;AAC/J,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAKpC;IACC,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAA4D,EAAE;QAClF,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACjD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,GAAG,CAAC;QACb,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3E,MAAM,aAAa,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;QAEhF,MAAM,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC;QACnE,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,QAAQ,CAAC,UAAU,EAAE,WAAW,KAAK,WAAW,EAAE,CAAC;gBACrD,OAAO,MAAM,CAAC,wBAAwB,EAAE,yFAAyF,CAAC,CAAC;YACrI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,WAAW,CAAC,yBAAyB,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YACpF,OAAO,EAAE,CAAC;gBACR,MAAM,EAAE,QAAQ,CAAC,EAAE;gBACnB,MAAM,EAAE,IAAI;gBACZ,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;aACpG,CAAC,CAAC;QACL,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC9D,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,8GAA8G;YAC9G,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACtC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC;gBACvD,OAAO,MAAM,CAAC,oBAAoB,EAAE,gCAAgC,MAAM,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;YAC1H,CAAC;QACH,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,EAAE,CAAC;YAC3B,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,MAAM,CAAC,MAAM,qCAAqC,CAAC,CAAC;QAC9F,CAAC;QACD,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACzG,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC5D,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,KAAK,CAAC,OAAO,gDAAgD,CAAC,CAAC;QACzG,CAAC;QACD,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1F,MAAM,YAAY,GAAG,cAAc,CACjC,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,EAChL,EAAE,eAAe,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,CACtF,CAAC;QACF,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YACvB,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC;QAE5C,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EACnD,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CACxC,CAAC;QACF,OAAO,EAAE,CAAC,EAAE,GAAG,MAAM,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -46,7 +46,7 @@ export interface GiveBack {
|
|
|
46
46
|
}
|
|
47
47
|
type NotFound = DomainError<'CREW_REQUEST_NOT_FOUND'>;
|
|
48
48
|
type Releasing = DomainError<'CREW_REQUEST_RELEASING'>;
|
|
49
|
-
type NotTheCallers = DomainError<'CREW_REQUEST_NOT_ASSIGNED_TO_CALLER'>;
|
|
49
|
+
export type NotTheCallers = DomainError<'CREW_REQUEST_NOT_ASSIGNED_TO_CALLER'>;
|
|
50
50
|
export type RequestCrewRefusal = CrewRequestShipRefusal | Releasing | DomainError<'CREW_REQUEST_SETTINGS_TOO_LARGE'> | DomainError<'CREW_REQUEST_SETTINGS_INVALID'>;
|
|
51
51
|
/**
|
|
52
52
|
* A requester asks that the ship be kept crewed, with these settings: the
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { IdGenerator } 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 { ScopeNamespaceRepository, ShipRepository } from './ports.js';
|
|
8
|
+
import { type DeclaredScope, type DeclareScopesRefusal } from './scope-namespace.js';
|
|
9
|
+
export interface DeclareScopesTx {
|
|
10
|
+
ships: Pick<ShipRepository, 'find' | 'findForUpdate' | 'scopesHeldIn'>;
|
|
11
|
+
scopeNamespaces: Pick<ScopeNamespaceRepository, 'lockNamespace' | 'find' | 'findByDeclarer' | 'save'>;
|
|
12
|
+
events: EventLog;
|
|
13
|
+
}
|
|
14
|
+
/** The namespace as declared, with its whole list of scopes. */
|
|
15
|
+
export interface DeclaredNamespace {
|
|
16
|
+
namespace: string;
|
|
17
|
+
scopes: readonly DeclaredScope[];
|
|
18
|
+
}
|
|
19
|
+
export type DeclareScopes = (caller: Caller, input: {
|
|
20
|
+
namespace: string;
|
|
21
|
+
scopes: readonly {
|
|
22
|
+
scope: string;
|
|
23
|
+
description: string;
|
|
24
|
+
}[];
|
|
25
|
+
}) => Promise<Result<DeclaredNamespace, DeclareScopesRefusal>>;
|
|
26
|
+
/**
|
|
27
|
+
* Use case: the caller's ship declares its plugin namespace with its whole
|
|
28
|
+
* list of scopes, the first time or again (decision 0046). Its scope
|
|
29
|
+
* (scopes:declare) is checked before this runs. In one unit of work, holding
|
|
30
|
+
* the declaring ship, so one ship never takes two namespaces, then the
|
|
31
|
+
* namespace, so two ships never both find it free and a grant of its scopes
|
|
32
|
+
* waits: the namespace and ScopesDeclared.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createDeclareScopes(deps: {
|
|
35
|
+
uow: UnitOfWork<DeclareScopesTx>;
|
|
36
|
+
clock: Clock;
|
|
37
|
+
ids: IdGenerator;
|
|
38
|
+
}): DeclareScopes;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { recordEvent, shipActor } from '../shared/events.js';
|
|
2
|
+
import { ok } from '../shared/result.js';
|
|
3
|
+
import { declareScopes } from './scope-namespace.js';
|
|
4
|
+
/**
|
|
5
|
+
* Use case: the caller's ship declares its plugin namespace with its whole
|
|
6
|
+
* list of scopes, the first time or again (decision 0046). Its scope
|
|
7
|
+
* (scopes:declare) is checked before this runs. In one unit of work, holding
|
|
8
|
+
* the declaring ship, so one ship never takes two namespaces, then the
|
|
9
|
+
* namespace, so two ships never both find it free and a grant of its scopes
|
|
10
|
+
* waits: the namespace and ScopesDeclared.
|
|
11
|
+
*/
|
|
12
|
+
export function createDeclareScopes(deps) {
|
|
13
|
+
return (caller, input) => deps.uow.run(async (tx) => {
|
|
14
|
+
const { fleetId, shipId } = caller;
|
|
15
|
+
await tx.ships.findForUpdate(fleetId, shipId);
|
|
16
|
+
await tx.scopeNamespaces.lockNamespace(fleetId, input.namespace);
|
|
17
|
+
const taken = await tx.scopeNamespaces.find(fleetId, input.namespace);
|
|
18
|
+
const declarer = taken && (await tx.ships.find(fleetId, taken.declaredBy));
|
|
19
|
+
const declared = declareScopes({ fleetId, declarer: shipId, namespace: input.namespace, scopes: input.scopes, at: deps.clock.now(), actor: shipActor(shipId) }, {
|
|
20
|
+
taken: taken && { namespace: taken, declarerName: declarer?.name ?? taken.declaredBy },
|
|
21
|
+
ofDeclarer: await tx.scopeNamespaces.findByDeclarer(fleetId, shipId),
|
|
22
|
+
held: taken === undefined ? [] : await tx.ships.scopesHeldIn(fleetId, input.namespace),
|
|
23
|
+
});
|
|
24
|
+
if (!declared.isOk) {
|
|
25
|
+
return declared;
|
|
26
|
+
}
|
|
27
|
+
await tx.scopeNamespaces.save(declared.value.namespace);
|
|
28
|
+
for (const event of declared.value.events) {
|
|
29
|
+
await recordEvent({ events: tx.events, ids: deps.ids }, event);
|
|
30
|
+
}
|
|
31
|
+
return ok({ namespace: declared.value.namespace.namespace, scopes: declared.value.namespace.scopes });
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=declare-scopes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declare-scopes.js","sourceRoot":"","sources":["../../../src/domain/registry/declare-scopes.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAGtD,OAAO,EAAE,aAAa,EAAiD,MAAM,sBAAsB,CAAC;AAmBpG;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAA0E;IAC5G,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAA4D,EAAE;QAClF,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;QACnC,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9C,MAAM,EAAE,CAAC,eAAe,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QACjE,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QACtE,MAAM,QAAQ,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;QAC3E,MAAM,QAAQ,GAAG,aAAa,CAC5B,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,EAC/H;YACE,KAAK,EAAE,KAAK,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,IAAI,KAAK,CAAC,UAAU,EAAE;YACtF,UAAU,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC;YACpE,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;SACvF,CACF,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,MAAM,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACxD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IACxG,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -32,7 +32,8 @@ export declare function namedInRules(rules: readonly NetworkRule[]): {
|
|
|
32
32
|
* The ship declares its whole list from now on, replacing what it declared
|
|
33
33
|
* before; an empty list withdraws them. At most 20, each rule within
|
|
34
34
|
* decision 0034's own limits, and every term on a label the ship owns: an
|
|
35
|
-
* exact value's label, and the label of a term of any or the same value
|
|
35
|
+
* exact value's label, and the label of a term of any or the same value; a
|
|
36
|
+
* term of the owner is on no label, so it is refused. An
|
|
36
37
|
* id the fleet does not have is refused, as its owner cannot be checked.
|
|
37
38
|
* NetworkRulesDeclared names the ship and the number of rules, never them.
|
|
38
39
|
*/
|
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
* supplies the list. Only rules on labels the ship owns keep them safe: only
|
|
6
6
|
* it assigns those labels, so its rules reach no ship it did not label.
|
|
7
7
|
*/
|
|
8
|
-
import { DECLARED_NETWORK_RULES_MAX } from '@aeolus-fleet/common';
|
|
8
|
+
import { DECLARED_NETWORK_RULES_MAX, isOwnerTerm } from '@aeolus-fleet/common';
|
|
9
9
|
import { refuse } from '../shared/errors.js';
|
|
10
10
|
import { ok } from '../shared/result.js';
|
|
11
|
-
import { copyOfRule, invalidRule } from './network-settings.js';
|
|
11
|
+
import { copyOfRule, invalidRule, termText } from './network-settings.js';
|
|
12
12
|
/** Every label and every exact value the rules' terms name, each once: what the caller looks up before declaring. */
|
|
13
13
|
export function namedInRules(rules) {
|
|
14
14
|
const terms = rules.flatMap((rule) => [...rule.from, ...rule.to]);
|
|
15
15
|
return {
|
|
16
|
-
labelIds: [...new Set(terms.flatMap((term) => (typeof term
|
|
16
|
+
labelIds: [...new Set(terms.flatMap((term) => (typeof term !== 'string' && !isOwnerTerm(term) ? [term.labelId] : [])))],
|
|
17
17
|
valueIds: [...new Set(terms.flatMap((term) => (typeof term === 'string' ? [term] : [])))],
|
|
18
18
|
};
|
|
19
19
|
}
|
|
@@ -21,7 +21,8 @@ export function namedInRules(rules) {
|
|
|
21
21
|
* The ship declares its whole list from now on, replacing what it declared
|
|
22
22
|
* before; an empty list withdraws them. At most 20, each rule within
|
|
23
23
|
* decision 0034's own limits, and every term on a label the ship owns: an
|
|
24
|
-
* exact value's label, and the label of a term of any or the same value
|
|
24
|
+
* exact value's label, and the label of a term of any or the same value; a
|
|
25
|
+
* term of the owner is on no label, so it is refused. An
|
|
25
26
|
* id the fleet does not have is refused, as its owner cannot be checked.
|
|
26
27
|
* NetworkRulesDeclared names the ship and the number of rules, never them.
|
|
27
28
|
*/
|
|
@@ -34,7 +35,12 @@ export function declareNetworkRules(named, change) {
|
|
|
34
35
|
if (invalid !== undefined) {
|
|
35
36
|
return refuse('INVALID_NETWORK_RULES', `${invalid} (decision 0034)`);
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
+
const terms = rules.flatMap((rule) => [...rule.from, ...rule.to]);
|
|
39
|
+
const ownerTerm = terms.find(isOwnerTerm);
|
|
40
|
+
if (ownerTerm !== undefined) {
|
|
41
|
+
return refuse('INVALID_NETWORK_RULES', `A declared rule holds only terms on labels the ship owns: ${termText(ownerTerm)} is a term of the owner (decision 0037)`);
|
|
42
|
+
}
|
|
43
|
+
for (const term of terms.filter((each) => !isOwnerTerm(each))) {
|
|
38
44
|
const owned = checkOwnedTerm(named, { term, shipId });
|
|
39
45
|
if (!owned.isOk) {
|
|
40
46
|
return owned;
|