@agentplat/mesh-sim 0.3.0-beta.2 → 0.3.0-beta.5
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 +447 -2
- package/dist/collective-closed-loop-action.d.ts +80 -0
- package/dist/collective-closed-loop-action.d.ts.map +1 -0
- package/dist/collective-closed-loop-action.js +471 -0
- package/dist/collective-closed-loop-action.js.map +1 -0
- package/dist/collective-closed-loop-contracts.d.ts +75 -0
- package/dist/collective-closed-loop-contracts.d.ts.map +1 -0
- package/dist/collective-closed-loop-contracts.js +420 -0
- package/dist/collective-closed-loop-contracts.js.map +1 -0
- package/dist/collective-closed-loop-fault-matrix.d.ts +101 -0
- package/dist/collective-closed-loop-fault-matrix.d.ts.map +1 -0
- package/dist/collective-closed-loop-fault-matrix.js +253 -0
- package/dist/collective-closed-loop-fault-matrix.js.map +1 -0
- package/dist/collective-closed-loop-recovery.d.ts +70 -0
- package/dist/collective-closed-loop-recovery.d.ts.map +1 -0
- package/dist/collective-closed-loop-recovery.js +823 -0
- package/dist/collective-closed-loop-recovery.js.map +1 -0
- package/dist/collective-closed-loop-reference.d.ts +54 -0
- package/dist/collective-closed-loop-reference.d.ts.map +1 -0
- package/dist/collective-closed-loop-reference.js +1696 -0
- package/dist/collective-closed-loop-reference.js.map +1 -0
- package/dist/collective-closed-loop-replanning.d.ts +27 -0
- package/dist/collective-closed-loop-replanning.d.ts.map +1 -0
- package/dist/collective-closed-loop-replanning.js +151 -0
- package/dist/collective-closed-loop-replanning.js.map +1 -0
- package/dist/collective-closed-loop-resilience-campaign.d.ts +22 -0
- package/dist/collective-closed-loop-resilience-campaign.d.ts.map +1 -0
- package/dist/collective-closed-loop-resilience-campaign.js +196 -0
- package/dist/collective-closed-loop-resilience-campaign.js.map +1 -0
- package/dist/collective-closed-loop-resilience-contracts.d.ts +138 -0
- package/dist/collective-closed-loop-resilience-contracts.d.ts.map +1 -0
- package/dist/collective-closed-loop-resilience-contracts.js +677 -0
- package/dist/collective-closed-loop-resilience-contracts.js.map +1 -0
- package/dist/collective-closed-loop-runner.d.ts +133 -0
- package/dist/collective-closed-loop-runner.d.ts.map +1 -0
- package/dist/collective-closed-loop-runner.js +1429 -0
- package/dist/collective-closed-loop-runner.js.map +1 -0
- package/dist/collective-closed-loop-runtime.d.ts +95 -0
- package/dist/collective-closed-loop-runtime.d.ts.map +1 -0
- package/dist/collective-closed-loop-runtime.js +1192 -0
- package/dist/collective-closed-loop-runtime.js.map +1 -0
- package/dist/collective-effect-provenance.d.ts +5 -0
- package/dist/collective-effect-provenance.d.ts.map +1 -0
- package/dist/collective-effect-provenance.js +32 -0
- package/dist/collective-effect-provenance.js.map +1 -0
- package/dist/collective-environment.d.ts +49 -0
- package/dist/collective-environment.d.ts.map +1 -0
- package/dist/collective-environment.js +907 -0
- package/dist/collective-environment.js.map +1 -0
- package/dist/collective-progressive-scale-overlay.d.ts +39 -0
- package/dist/collective-progressive-scale-overlay.d.ts.map +1 -0
- package/dist/collective-progressive-scale-overlay.js +147 -0
- package/dist/collective-progressive-scale-overlay.js.map +1 -0
- package/dist/collective-progressive-scale.d.ts +202 -0
- package/dist/collective-progressive-scale.d.ts.map +1 -0
- package/dist/collective-progressive-scale.js +755 -0
- package/dist/collective-progressive-scale.js.map +1 -0
- package/dist/collective-statistical-campaign-aggregation.d.ts +97 -0
- package/dist/collective-statistical-campaign-aggregation.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-aggregation.js +446 -0
- package/dist/collective-statistical-campaign-aggregation.js.map +1 -0
- package/dist/collective-statistical-campaign-artifact-stream.d.ts +66 -0
- package/dist/collective-statistical-campaign-artifact-stream.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-artifact-stream.js +207 -0
- package/dist/collective-statistical-campaign-artifact-stream.js.map +1 -0
- package/dist/collective-statistical-campaign-bundle.d.ts +151 -0
- package/dist/collective-statistical-campaign-bundle.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-bundle.js +885 -0
- package/dist/collective-statistical-campaign-bundle.js.map +1 -0
- package/dist/collective-statistical-campaign-executor.d.ts +131 -0
- package/dist/collective-statistical-campaign-executor.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-executor.js +856 -0
- package/dist/collective-statistical-campaign-executor.js.map +1 -0
- package/dist/collective-statistical-campaign-normative-analysis.d.ts +85 -0
- package/dist/collective-statistical-campaign-normative-analysis.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-normative-analysis.js +483 -0
- package/dist/collective-statistical-campaign-normative-analysis.js.map +1 -0
- package/dist/collective-statistical-campaign-normative-operation.d.ts +89 -0
- package/dist/collective-statistical-campaign-normative-operation.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-normative-operation.js +266 -0
- package/dist/collective-statistical-campaign-normative-operation.js.map +1 -0
- package/dist/collective-statistical-campaign-normative-registry.d.ts +24 -0
- package/dist/collective-statistical-campaign-normative-registry.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-normative-registry.js +163 -0
- package/dist/collective-statistical-campaign-normative-registry.js.map +1 -0
- package/dist/collective-statistical-campaign-registered-adapter.d.ts +16 -0
- package/dist/collective-statistical-campaign-registered-adapter.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-registered-adapter.js +518 -0
- package/dist/collective-statistical-campaign-registered-adapter.js.map +1 -0
- package/dist/collective-statistical-campaign-scale.d.ts +85 -0
- package/dist/collective-statistical-campaign-scale.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-scale.js +349 -0
- package/dist/collective-statistical-campaign-scale.js.map +1 -0
- package/dist/collective-trace-journal.d.ts +20 -0
- package/dist/collective-trace-journal.d.ts.map +1 -0
- package/dist/collective-trace-journal.js +105 -0
- package/dist/collective-trace-journal.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/dist/multi-domain-environment-contracts.d.ts +122 -0
- package/dist/multi-domain-environment-contracts.d.ts.map +1 -0
- package/dist/multi-domain-environment-contracts.js +14 -0
- package/dist/multi-domain-environment-contracts.js.map +1 -0
- package/dist/multi-domain-environment-runtime.d.ts +25 -0
- package/dist/multi-domain-environment-runtime.d.ts.map +1 -0
- package/dist/multi-domain-environment-runtime.js +493 -0
- package/dist/multi-domain-environment-runtime.js.map +1 -0
- package/dist/multi-domain-environment-validation.d.ts +33 -0
- package/dist/multi-domain-environment-validation.d.ts.map +1 -0
- package/dist/multi-domain-environment-validation.js +415 -0
- package/dist/multi-domain-environment-validation.js.map +1 -0
- package/dist/multi-domain-environment.d.ts +4 -0
- package/dist/multi-domain-environment.d.ts.map +1 -0
- package/dist/multi-domain-environment.js +4 -0
- package/dist/multi-domain-environment.js.map +1 -0
- package/dist/reducer-scenario.d.ts.map +1 -1
- package/dist/reducer-scenario.js +67 -19
- package/dist/reducer-scenario.js.map +1 -1
- package/dist/scalable-evaluation-contracts.d.ts +835 -0
- package/dist/scalable-evaluation-contracts.d.ts.map +1 -0
- package/dist/scalable-evaluation-contracts.js +22 -0
- package/dist/scalable-evaluation-contracts.js.map +1 -0
- package/dist/scalable-evaluation-durability.d.ts +16 -0
- package/dist/scalable-evaluation-durability.d.ts.map +1 -0
- package/dist/scalable-evaluation-durability.js +339 -0
- package/dist/scalable-evaluation-durability.js.map +1 -0
- package/dist/scalable-evaluation-evidence.d.ts +93 -0
- package/dist/scalable-evaluation-evidence.d.ts.map +1 -0
- package/dist/scalable-evaluation-evidence.js +470 -0
- package/dist/scalable-evaluation-evidence.js.map +1 -0
- package/dist/scalable-evaluation-reference-integrated.d.ts +87 -0
- package/dist/scalable-evaluation-reference-integrated.d.ts.map +1 -0
- package/dist/scalable-evaluation-reference-integrated.js +1318 -0
- package/dist/scalable-evaluation-reference-integrated.js.map +1 -0
- package/dist/scalable-evaluation-runner.d.ts +8 -0
- package/dist/scalable-evaluation-runner.d.ts.map +1 -0
- package/dist/scalable-evaluation-runner.js +1810 -0
- package/dist/scalable-evaluation-runner.js.map +1 -0
- package/dist/scalable-evaluation-runtime.d.ts +86 -0
- package/dist/scalable-evaluation-runtime.d.ts.map +1 -0
- package/dist/scalable-evaluation-runtime.js +1310 -0
- package/dist/scalable-evaluation-runtime.js.map +1 -0
- package/dist/scalable-evaluation-validation.d.ts +59 -0
- package/dist/scalable-evaluation-validation.d.ts.map +1 -0
- package/dist/scalable-evaluation-validation.js +377 -0
- package/dist/scalable-evaluation-validation.js.map +1 -0
- package/dist/scalable-evaluation.d.ts +8 -0
- package/dist/scalable-evaluation.d.ts.map +1 -0
- package/dist/scalable-evaluation.js +8 -0
- package/dist/scalable-evaluation.js.map +1 -0
- package/dist/sharded-simulation-contracts.d.ts +240 -0
- package/dist/sharded-simulation-contracts.d.ts.map +1 -0
- package/dist/sharded-simulation-contracts.js +199 -0
- package/dist/sharded-simulation-contracts.js.map +1 -0
- package/dist/sharded-simulation-runtime.d.ts +64 -0
- package/dist/sharded-simulation-runtime.d.ts.map +1 -0
- package/dist/sharded-simulation-runtime.js +755 -0
- package/dist/sharded-simulation-runtime.js.map +1 -0
- package/dist/sharded-simulation-validation.d.ts +10 -0
- package/dist/sharded-simulation-validation.d.ts.map +1 -0
- package/dist/sharded-simulation-validation.js +250 -0
- package/dist/sharded-simulation-validation.js.map +1 -0
- package/dist/sharded-simulation.d.ts +46 -0
- package/dist/sharded-simulation.d.ts.map +1 -0
- package/dist/sharded-simulation.js +32 -0
- package/dist/sharded-simulation.js.map +1 -0
- package/dist/verified-benchmark-contracts.d.ts +132 -0
- package/dist/verified-benchmark-contracts.d.ts.map +1 -0
- package/dist/verified-benchmark-contracts.js +2 -0
- package/dist/verified-benchmark-contracts.js.map +1 -0
- package/dist/verified-benchmark-runtime.d.ts +20 -0
- package/dist/verified-benchmark-runtime.d.ts.map +1 -0
- package/dist/verified-benchmark-runtime.js +199 -0
- package/dist/verified-benchmark-runtime.js.map +1 -0
- package/dist/verified-benchmark-validation.d.ts +64 -0
- package/dist/verified-benchmark-validation.d.ts.map +1 -0
- package/dist/verified-benchmark-validation.js +481 -0
- package/dist/verified-benchmark-validation.js.map +1 -0
- package/dist/verified-benchmark.d.ts +4 -0
- package/dist/verified-benchmark.d.ts.map +1 -0
- package/dist/verified-benchmark.js +4 -0
- package/dist/verified-benchmark.js.map +1 -0
- package/package.json +18 -8
|
@@ -0,0 +1,1318 @@
|
|
|
1
|
+
import { validateMissionIntentV1, } from "@agentplat/collective-planning";
|
|
2
|
+
import { collectiveQuorumDigestV1 } from "@agentplat/collective-quorum/crypto";
|
|
3
|
+
import { createAssuranceExecutionAuthorityFenceV1, } from "@agentplat/collective-host/assurance-coupled-execution";
|
|
4
|
+
import { isReferenceIntegratedCollectiveStackBoundToPlaneAndRecoveryV1, isReferenceIntegratedCollectiveStackV1, readReferenceIntegratedCollectiveArtifactV1, storeReferenceIntegratedCollectiveArtifactV1, } from "@agentplat/collective-host/reference-integrated-stack";
|
|
5
|
+
import { validateMeshSparseDeliveryV2, validateMeshSparseOverlayProfileV2, validateMeshSparseUpdateV2, invokeMeshSparsePeerPlanePublishV1, invokeMeshSparsePeerPlaneReceiveV1, isMeshSparsePeerPlaneRuntimeV1, MeshSparsePeerPlaneRuntimeV1, } from "@agentplat/mesh/overlay";
|
|
6
|
+
import { validateMultiDomainActionEnvelopeV1, validateMultiDomainEnvironmentDescriptorV1, validateMultiDomainObservationEnvelopeV1, } from "./multi-domain-environment-validation.js";
|
|
7
|
+
import { scalableEvaluationDigestV1, validateScalableEvaluationDefinitionV1, validateScalableEvaluationTeamDescriptorV1, } from "./scalable-evaluation-validation.js";
|
|
8
|
+
import { validateShardedSimulationCrossShardMessageAckV1, validateShardedSimulationEffectReceiptV1, } from "./sharded-simulation-runtime.js";
|
|
9
|
+
import { validateShardedSimulationCrossShardMessageBatchV1 } from "./sharded-simulation-validation.js";
|
|
10
|
+
const DIGEST = /^sha256:[0-9a-f]{64}$/u;
|
|
11
|
+
const MAXIMUM_STEP_MESSAGES = 1_024;
|
|
12
|
+
const MAXIMUM_STEP_ACTIONS = 1_024;
|
|
13
|
+
const MAXIMUM_STEP_MESSAGE_BYTES = 16 * 1024 * 1024;
|
|
14
|
+
const MAXIMUM_INBOUND_MESSAGES_PER_PEER = 65_536;
|
|
15
|
+
const MAXIMUM_STEP_JOURNALS_PER_PEER = 64;
|
|
16
|
+
export const REFERENCE_INTEGRATED_SCALABLE_EVALUATION_IMPLEMENTATION_ID_V1 = "agentplat.reference-integrated-collective-stack.v1";
|
|
17
|
+
const egressBindings = new WeakMap();
|
|
18
|
+
const peerBindings = new WeakMap();
|
|
19
|
+
const teamPorts = new WeakSet();
|
|
20
|
+
const egressPeerOwners = new WeakMap();
|
|
21
|
+
const stackPeerOwners = new WeakMap();
|
|
22
|
+
const peerTeamOwners = new WeakMap();
|
|
23
|
+
const teamPortBindings = new WeakMap();
|
|
24
|
+
/**
|
|
25
|
+
* Nominal evaluation boundary used as both the stack's sparse plane and its
|
|
26
|
+
* recovery-aware execution authority. Protected commits land in an outbox;
|
|
27
|
+
* only the outer evaluation runner applies them to the environment. Capture
|
|
28
|
+
* state is process-local evaluation state, not a production durable sink.
|
|
29
|
+
*/
|
|
30
|
+
export class ReferenceIntegratedScalableEvaluationEgressRuntimeV1 {
|
|
31
|
+
constructor(options) {
|
|
32
|
+
if (new.target !== ReferenceIntegratedScalableEvaluationEgressRuntimeV1)
|
|
33
|
+
fail("reference_integrated_egress_subclass_invalid");
|
|
34
|
+
assertOnlyKeys(options, [
|
|
35
|
+
"plane",
|
|
36
|
+
"descriptor",
|
|
37
|
+
"localPeerId",
|
|
38
|
+
"scope",
|
|
39
|
+
"objectiveDigest",
|
|
40
|
+
"membershipConfigurationDigest",
|
|
41
|
+
"membershipEpoch",
|
|
42
|
+
], [
|
|
43
|
+
"recoveryPeerId",
|
|
44
|
+
"assignmentEpoch",
|
|
45
|
+
"fencingTokenPrefix",
|
|
46
|
+
"maximumCapturedDeliveries",
|
|
47
|
+
"maximumCapturedEffects",
|
|
48
|
+
"maximumSettledReceipts",
|
|
49
|
+
"crypto",
|
|
50
|
+
], "reference_integrated_egress_options");
|
|
51
|
+
if (!options?.plane || typeof options.plane !== "object")
|
|
52
|
+
fail("reference_integrated_plane_invalid");
|
|
53
|
+
const profile = validateMeshSparseOverlayProfileV2(options.plane.profile);
|
|
54
|
+
const descriptor = validateMultiDomainEnvironmentDescriptorV1(options.descriptor);
|
|
55
|
+
safeInteger(options.plane.localPeerIndex, "local_peer_index", 0, profile.maximumPeers - 1);
|
|
56
|
+
const localPeerIndex = options.plane.localPeerIndex;
|
|
57
|
+
identifier(options.localPeerId, "local_peer_id");
|
|
58
|
+
if (options.recoveryPeerId !== undefined)
|
|
59
|
+
identifier(options.recoveryPeerId, "recovery_peer_id");
|
|
60
|
+
const scope = validateScope(options.scope);
|
|
61
|
+
digest(options.objectiveDigest, "objective_digest");
|
|
62
|
+
digest(options.membershipConfigurationDigest, "membership_configuration_digest");
|
|
63
|
+
safeInteger(options.membershipEpoch, "membership_epoch", 1);
|
|
64
|
+
const assignmentEpoch = options.assignmentEpoch ?? 1;
|
|
65
|
+
safeInteger(assignmentEpoch, "assignment_epoch", 0);
|
|
66
|
+
const fencingTokenPrefix = options.fencingTokenPrefix ?? `evaluation-fence:${options.localPeerId}`;
|
|
67
|
+
identifier(fencingTokenPrefix, "fencing_token_prefix");
|
|
68
|
+
const maximumCapturedDeliveries = options.maximumCapturedDeliveries ?? 16_384;
|
|
69
|
+
const maximumCapturedEffects = options.maximumCapturedEffects ?? 4_096;
|
|
70
|
+
const maximumSettledReceipts = options.maximumSettledReceipts ?? 65_536;
|
|
71
|
+
safeInteger(maximumCapturedDeliveries, "maximum_captured_deliveries", 1, 1_000_000);
|
|
72
|
+
safeInteger(maximumCapturedEffects, "maximum_captured_effects", 1, 100_000);
|
|
73
|
+
safeInteger(maximumSettledReceipts, "maximum_settled_receipts", 1, 1_000_000);
|
|
74
|
+
const deliveries = [];
|
|
75
|
+
const deliveryIds = new Set();
|
|
76
|
+
const deliveryQueue = Object.freeze({
|
|
77
|
+
pending: () => 0,
|
|
78
|
+
enqueue: async (request) => {
|
|
79
|
+
const delivery = validateMeshSparseDeliveryV2(profile, request.delivery);
|
|
80
|
+
if (delivery.senderPeerIndex !== localPeerIndex ||
|
|
81
|
+
request.recipient.peerIndex !== delivery.recipientPeerIndex)
|
|
82
|
+
return Object.freeze({
|
|
83
|
+
status: "rejected",
|
|
84
|
+
reasonCode: "evaluation_delivery_binding_invalid",
|
|
85
|
+
});
|
|
86
|
+
if (deliveryIds.has(delivery.deliveryDigest))
|
|
87
|
+
return Object.freeze({ status: "duplicate" });
|
|
88
|
+
if (deliveryIds.size >=
|
|
89
|
+
maximumCapturedDeliveries + maximumSettledReceipts)
|
|
90
|
+
return Object.freeze({
|
|
91
|
+
status: "backpressured",
|
|
92
|
+
reasonCode: "evaluation_delivery_idempotency_window_exhausted",
|
|
93
|
+
});
|
|
94
|
+
if (deliveries.length >= maximumCapturedDeliveries)
|
|
95
|
+
return Object.freeze({
|
|
96
|
+
status: "backpressured",
|
|
97
|
+
reasonCode: "evaluation_delivery_outbox_exhausted",
|
|
98
|
+
});
|
|
99
|
+
const binding = egressBindings.get(this);
|
|
100
|
+
const sequence = binding?.nextDeliverySequence ?? deliveries.length + 1;
|
|
101
|
+
const operationId = binding?.activeOperationId ?? null;
|
|
102
|
+
const body = {
|
|
103
|
+
sequence,
|
|
104
|
+
operationId,
|
|
105
|
+
updateDigest: delivery.update.updateDigest,
|
|
106
|
+
deliveryDigest: delivery.deliveryDigest,
|
|
107
|
+
};
|
|
108
|
+
deliveries.push(immutable({
|
|
109
|
+
...body,
|
|
110
|
+
delivery,
|
|
111
|
+
captureDigest: scalableEvaluationDigestV1("reference-integrated-delivery-capture", body),
|
|
112
|
+
}));
|
|
113
|
+
deliveryIds.add(delivery.deliveryDigest);
|
|
114
|
+
if (binding) {
|
|
115
|
+
binding.nextDeliverySequence += 1;
|
|
116
|
+
binding.latestDeliveryCaptureDigest =
|
|
117
|
+
deliveries.at(-1).captureDigest;
|
|
118
|
+
}
|
|
119
|
+
return Object.freeze({ status: "admitted" });
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
const plane = new MeshSparsePeerPlaneRuntimeV1({
|
|
123
|
+
...options.plane,
|
|
124
|
+
deliveryQueue,
|
|
125
|
+
});
|
|
126
|
+
if (!isMeshSparsePeerPlaneRuntimeV1(plane))
|
|
127
|
+
fail("reference_integrated_sparse_plane_not_genuine");
|
|
128
|
+
egressBindings.set(this, {
|
|
129
|
+
plane,
|
|
130
|
+
profile,
|
|
131
|
+
descriptor,
|
|
132
|
+
localPeerIndex,
|
|
133
|
+
localPeerId: options.localPeerId,
|
|
134
|
+
recoveryPeerId: options.recoveryPeerId ?? null,
|
|
135
|
+
scope,
|
|
136
|
+
objectiveDigest: options.objectiveDigest,
|
|
137
|
+
membershipConfigurationDigest: options.membershipConfigurationDigest,
|
|
138
|
+
membershipEpoch: options.membershipEpoch,
|
|
139
|
+
initialAssignmentEpoch: assignmentEpoch,
|
|
140
|
+
fencingTokenPrefix,
|
|
141
|
+
maximumCapturedDeliveries,
|
|
142
|
+
maximumCapturedEffects,
|
|
143
|
+
maximumSettledReceipts,
|
|
144
|
+
...(options.crypto === undefined ? {} : { crypto: options.crypto }),
|
|
145
|
+
assignments: new Map(),
|
|
146
|
+
deliveries,
|
|
147
|
+
effects: [],
|
|
148
|
+
effectReceipts: new Map(),
|
|
149
|
+
deliveryIds,
|
|
150
|
+
settledDeliveries: new Map(),
|
|
151
|
+
settledEffects: new Map(),
|
|
152
|
+
settledEffectExecutions: new Map(),
|
|
153
|
+
nextDeliverySequence: 1,
|
|
154
|
+
nextEffectSequence: 1,
|
|
155
|
+
activeOperationId: null,
|
|
156
|
+
latestDeliveryCaptureDigest: null,
|
|
157
|
+
latestEffectCaptureDigest: null,
|
|
158
|
+
});
|
|
159
|
+
Object.defineProperties(this, {
|
|
160
|
+
publish: {
|
|
161
|
+
value: canonicalEgressPublish.bind(this),
|
|
162
|
+
writable: false,
|
|
163
|
+
configurable: false,
|
|
164
|
+
},
|
|
165
|
+
resolve: {
|
|
166
|
+
value: canonicalEgressResolve.bind(this),
|
|
167
|
+
writable: false,
|
|
168
|
+
configurable: false,
|
|
169
|
+
},
|
|
170
|
+
install: {
|
|
171
|
+
value: canonicalEgressInstall.bind(this),
|
|
172
|
+
writable: false,
|
|
173
|
+
configurable: false,
|
|
174
|
+
},
|
|
175
|
+
reconcile: {
|
|
176
|
+
value: canonicalEgressReconcile.bind(this),
|
|
177
|
+
writable: false,
|
|
178
|
+
configurable: false,
|
|
179
|
+
},
|
|
180
|
+
commit: {
|
|
181
|
+
value: canonicalEgressCommit.bind(this),
|
|
182
|
+
writable: false,
|
|
183
|
+
configurable: false,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
Object.freeze(this);
|
|
187
|
+
}
|
|
188
|
+
async publish(input) {
|
|
189
|
+
const binding = requireEgress(this);
|
|
190
|
+
const captured = Object.freeze({
|
|
191
|
+
topic: input.topic,
|
|
192
|
+
payloadDigest: input.payloadDigest,
|
|
193
|
+
logicalTime: input.logicalTime,
|
|
194
|
+
lifetime: input.lifetime,
|
|
195
|
+
...(input.fanout === undefined ? {} : { fanout: input.fanout }),
|
|
196
|
+
});
|
|
197
|
+
const result = await invokeMeshSparsePeerPlanePublishV1(binding.plane, captured);
|
|
198
|
+
const update = validateMeshSparseUpdateV2(binding.profile, result.update);
|
|
199
|
+
if (update.originPeerIndex !== binding.localPeerIndex ||
|
|
200
|
+
update.originPeerId !== binding.localPeerId ||
|
|
201
|
+
update.topic !== captured.topic ||
|
|
202
|
+
update.payloadDigest !== captured.payloadDigest ||
|
|
203
|
+
update.createdAtLogicalTime !== captured.logicalTime)
|
|
204
|
+
fail("reference_integrated_publish_binding_invalid");
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
async resolve(input) {
|
|
208
|
+
const binding = requireEgress(this);
|
|
209
|
+
const payload = input.cognitiveRequest.payload;
|
|
210
|
+
const missionIntentId = payload.missionIntentId;
|
|
211
|
+
const planningCycleId = payload.planningCycleId;
|
|
212
|
+
if (input.localPeerId !== binding.localPeerId ||
|
|
213
|
+
input.cognitiveRequest.tenantId !== binding.scope.tenantId ||
|
|
214
|
+
missionIntentId !== binding.scope.missionIntentId ||
|
|
215
|
+
typeof planningCycleId !== "string")
|
|
216
|
+
return null;
|
|
217
|
+
const assignment = assignmentFor(binding, input.task.taskId);
|
|
218
|
+
if (assignment.assignedPeerId !== binding.localPeerId)
|
|
219
|
+
return null;
|
|
220
|
+
return createAssuranceExecutionAuthorityFenceV1({
|
|
221
|
+
schemaVersion: 1,
|
|
222
|
+
scope: {
|
|
223
|
+
...binding.scope,
|
|
224
|
+
objectiveId: planningCycleId,
|
|
225
|
+
workItemId: input.task.taskId,
|
|
226
|
+
},
|
|
227
|
+
executionId: input.executionId,
|
|
228
|
+
awardDigest: input.awardDigest,
|
|
229
|
+
taskDigest: input.task.taskDigest,
|
|
230
|
+
assignedPeerId: assignment.assignedPeerId,
|
|
231
|
+
assignmentEpoch: assignment.assignmentEpoch,
|
|
232
|
+
fencingToken: assignment.fencingToken,
|
|
233
|
+
membershipConfigurationDigest: binding.membershipConfigurationDigest,
|
|
234
|
+
membershipEpoch: binding.membershipEpoch,
|
|
235
|
+
}, binding.crypto);
|
|
236
|
+
}
|
|
237
|
+
async install(input) {
|
|
238
|
+
const binding = requireEgress(this);
|
|
239
|
+
const current = assignmentFor(binding, input.workItemId);
|
|
240
|
+
if (current.assignedPeerId !== input.excludedPeerId ||
|
|
241
|
+
current.assignmentEpoch !== input.expectedAssignmentEpoch ||
|
|
242
|
+
current.fencingToken !== input.expectedFencingToken ||
|
|
243
|
+
input.nextAssignmentEpoch <= current.assignmentEpoch)
|
|
244
|
+
fail("reference_integrated_assignment_install_conflict");
|
|
245
|
+
if (!binding.recoveryPeerId)
|
|
246
|
+
fail("reference_integrated_recovery_peer_unavailable");
|
|
247
|
+
const next = immutable({
|
|
248
|
+
assignedPeerId: binding.recoveryPeerId,
|
|
249
|
+
assignmentEpoch: input.nextAssignmentEpoch,
|
|
250
|
+
fencingToken: `${binding.fencingTokenPrefix}:${input.nextAssignmentEpoch}:${input.operationId}`,
|
|
251
|
+
});
|
|
252
|
+
binding.assignments.set(input.workItemId, next);
|
|
253
|
+
return immutable({
|
|
254
|
+
assignmentEpoch: next.assignmentEpoch,
|
|
255
|
+
fencingToken: next.fencingToken,
|
|
256
|
+
installedAtLogicalMs: input.logicalTimeMs,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
async commit(input) {
|
|
260
|
+
const binding = requireEgress(this);
|
|
261
|
+
input = Object.freeze({
|
|
262
|
+
executionId: input.executionId,
|
|
263
|
+
effect: immutable(input.effect),
|
|
264
|
+
certificate: immutable(input.certificate),
|
|
265
|
+
authorityFence: immutable(input.authorityFence),
|
|
266
|
+
logicalTimeMs: input.logicalTimeMs,
|
|
267
|
+
signal: input.signal,
|
|
268
|
+
});
|
|
269
|
+
if (input.signal.aborted)
|
|
270
|
+
fail("reference_integrated_effect_cancelled");
|
|
271
|
+
if (input.effect.schemaVersion !== 1)
|
|
272
|
+
fail("reference_integrated_effect_proposal_invalid");
|
|
273
|
+
identifier(input.effect.effectClass, "effect_class");
|
|
274
|
+
const expectedProposalDigest = await collectiveQuorumDigestV1({
|
|
275
|
+
domain: "assurance-protected-effect-proposal-v1",
|
|
276
|
+
body: {
|
|
277
|
+
schemaVersion: 1,
|
|
278
|
+
effectClass: input.effect.effectClass,
|
|
279
|
+
payload: input.effect.payload,
|
|
280
|
+
},
|
|
281
|
+
}, binding.crypto);
|
|
282
|
+
if (input.effect.proposalDigest !== expectedProposalDigest)
|
|
283
|
+
fail("reference_integrated_effect_proposal_invalid");
|
|
284
|
+
const prior = binding.effectReceipts.get(input.executionId);
|
|
285
|
+
if (prior) {
|
|
286
|
+
if (prior.proposalDigest !== input.effect.proposalDigest ||
|
|
287
|
+
prior.finalityCertificateDigest !== input.certificate.certificateDigest)
|
|
288
|
+
fail("reference_integrated_effect_idempotency_conflict");
|
|
289
|
+
return prior;
|
|
290
|
+
}
|
|
291
|
+
if (binding.effectReceipts.size >=
|
|
292
|
+
binding.maximumCapturedEffects + binding.maximumSettledReceipts)
|
|
293
|
+
fail("reference_integrated_effect_idempotency_window_exhausted");
|
|
294
|
+
await validateAuthorityFence(binding, input.authorityFence, input);
|
|
295
|
+
if (input.certificate.valueDigest !== input.effect.proposalDigest)
|
|
296
|
+
fail("reference_integrated_effect_finality_invalid");
|
|
297
|
+
const action = validateMultiDomainActionEnvelopeV1(input.effect.payload, binding.descriptor);
|
|
298
|
+
if (binding.effects.length >= binding.maximumCapturedEffects)
|
|
299
|
+
fail("reference_integrated_effect_outbox_exhausted");
|
|
300
|
+
const externalReference = `evaluation-effect:${input.executionId}`;
|
|
301
|
+
const receiptBody = {
|
|
302
|
+
schemaVersion: 1,
|
|
303
|
+
executionId: input.executionId,
|
|
304
|
+
proposalDigest: input.effect.proposalDigest,
|
|
305
|
+
finalityCertificateDigest: input.certificate.certificateDigest,
|
|
306
|
+
status: "committed",
|
|
307
|
+
externalReference,
|
|
308
|
+
reasonCode: "evaluation_outbox_committed",
|
|
309
|
+
};
|
|
310
|
+
const receipt = immutable({
|
|
311
|
+
...receiptBody,
|
|
312
|
+
receiptDigest: await collectiveQuorumDigestV1({
|
|
313
|
+
domain: "assurance-protected-effect-receipt-v1",
|
|
314
|
+
body: receiptBody,
|
|
315
|
+
}, binding.crypto),
|
|
316
|
+
});
|
|
317
|
+
const sequence = binding.nextEffectSequence;
|
|
318
|
+
const operationId = binding.activeOperationId;
|
|
319
|
+
const captureBody = {
|
|
320
|
+
sequence,
|
|
321
|
+
operationId,
|
|
322
|
+
executionId: input.executionId,
|
|
323
|
+
proposalDigest: input.effect.proposalDigest,
|
|
324
|
+
action,
|
|
325
|
+
receiptDigest: receipt.receiptDigest,
|
|
326
|
+
};
|
|
327
|
+
const capture = immutable({
|
|
328
|
+
...captureBody,
|
|
329
|
+
receipt,
|
|
330
|
+
captureDigest: scalableEvaluationDigestV1("reference-integrated-effect-capture", captureBody),
|
|
331
|
+
});
|
|
332
|
+
binding.effects.push(capture);
|
|
333
|
+
binding.nextEffectSequence += 1;
|
|
334
|
+
binding.latestEffectCaptureDigest = capture.captureDigest;
|
|
335
|
+
binding.effectReceipts.set(input.executionId, receipt);
|
|
336
|
+
return receipt;
|
|
337
|
+
}
|
|
338
|
+
async reconcile(input) {
|
|
339
|
+
const binding = requireEgress(this);
|
|
340
|
+
const prior = binding.effectReceipts.get(input.executionId);
|
|
341
|
+
if (!prior)
|
|
342
|
+
return null;
|
|
343
|
+
if (prior.proposalDigest !== input.effect.proposalDigest ||
|
|
344
|
+
prior.finalityCertificateDigest !== input.certificate.certificateDigest ||
|
|
345
|
+
input.authorityFence.executionId !== input.executionId)
|
|
346
|
+
fail("reference_integrated_effect_idempotency_conflict");
|
|
347
|
+
return prior;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
const canonicalEgressPublish = ReferenceIntegratedScalableEvaluationEgressRuntimeV1.prototype.publish;
|
|
351
|
+
const canonicalEgressResolve = ReferenceIntegratedScalableEvaluationEgressRuntimeV1.prototype.resolve;
|
|
352
|
+
const canonicalEgressInstall = ReferenceIntegratedScalableEvaluationEgressRuntimeV1.prototype.install;
|
|
353
|
+
const canonicalEgressReconcile = ReferenceIntegratedScalableEvaluationEgressRuntimeV1.prototype.reconcile;
|
|
354
|
+
const canonicalEgressCommit = ReferenceIntegratedScalableEvaluationEgressRuntimeV1.prototype.commit;
|
|
355
|
+
export function isReferenceIntegratedScalableEvaluationEgressV1(value) {
|
|
356
|
+
return Boolean(value && typeof value === "object" && egressBindings.has(value));
|
|
357
|
+
}
|
|
358
|
+
/** Read-only bounded evidence about the nominal egress; payloads stay private. */
|
|
359
|
+
export function inspectReferenceIntegratedScalableEvaluationEgressV1(value) {
|
|
360
|
+
const binding = requireEgress(value);
|
|
361
|
+
return immutable({
|
|
362
|
+
schemaVersion: 1,
|
|
363
|
+
localPeerIndex: binding.localPeerIndex,
|
|
364
|
+
localPeerId: binding.localPeerId,
|
|
365
|
+
capturedDeliveryCount: binding.deliveries.length,
|
|
366
|
+
capturedEffectCount: binding.effects.length,
|
|
367
|
+
settledDeliveryCount: binding.settledDeliveries.size,
|
|
368
|
+
settledEffectCount: binding.settledEffects.size,
|
|
369
|
+
latestDeliveryCaptureDigest: binding.latestDeliveryCaptureDigest,
|
|
370
|
+
latestEffectCaptureDigest: binding.latestEffectCaptureDigest,
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
export function bindReferenceIntegratedScalableEvaluationPeerV1(input) {
|
|
374
|
+
assertOnlyKeys(input, [
|
|
375
|
+
"peerIndex",
|
|
376
|
+
"stack",
|
|
377
|
+
"egress",
|
|
378
|
+
"missionIntent",
|
|
379
|
+
"observationSchemaDigest",
|
|
380
|
+
], [], "reference_integrated_peer_binding");
|
|
381
|
+
if (!isReferenceIntegratedCollectiveStackV1(input.stack))
|
|
382
|
+
fail("reference_integrated_stack_not_genuine");
|
|
383
|
+
if (!isReferenceIntegratedScalableEvaluationEgressV1(input.egress))
|
|
384
|
+
fail("reference_integrated_egress_not_genuine");
|
|
385
|
+
if (!isReferenceIntegratedCollectiveStackBoundToPlaneAndRecoveryV1(input.stack, {
|
|
386
|
+
plane: input.egress,
|
|
387
|
+
recoveryAssignmentAuthority: input.egress,
|
|
388
|
+
}))
|
|
389
|
+
fail("reference_integrated_stack_egress_binding_invalid");
|
|
390
|
+
const egress = requireEgress(input.egress);
|
|
391
|
+
safeInteger(input.peerIndex, "peer_index", 0, egress.profile.maximumPeers - 1);
|
|
392
|
+
if (input.peerIndex !== egress.localPeerIndex)
|
|
393
|
+
fail("reference_integrated_peer_index_mismatch");
|
|
394
|
+
const missionIntent = validateMissionIntentV1(input.missionIntent);
|
|
395
|
+
if (missionIntent.tenantId !== egress.scope.tenantId ||
|
|
396
|
+
missionIntent.missionIntentId !== egress.scope.missionIntentId ||
|
|
397
|
+
missionIntent.objective.meshId !== egress.scope.meshId ||
|
|
398
|
+
missionIntent.objective.objectiveId !== egress.scope.objectiveId)
|
|
399
|
+
fail("reference_integrated_mission_scope_mismatch");
|
|
400
|
+
if (objectiveScopeDigest(missionIntent) !== egress.objectiveDigest)
|
|
401
|
+
fail("reference_integrated_objective_scope_mismatch");
|
|
402
|
+
digest(input.observationSchemaDigest, "observation_schema_digest");
|
|
403
|
+
if (egressPeerOwners.has(input.egress) || stackPeerOwners.has(input.stack))
|
|
404
|
+
fail("reference_integrated_peer_binding_already_exists");
|
|
405
|
+
const peer = Object.freeze({
|
|
406
|
+
schemaVersion: 1,
|
|
407
|
+
peerIndex: input.peerIndex,
|
|
408
|
+
stack: input.stack,
|
|
409
|
+
egress: input.egress,
|
|
410
|
+
missionIntent,
|
|
411
|
+
observationSchemaDigest: input.observationSchemaDigest,
|
|
412
|
+
});
|
|
413
|
+
peerBindings.set(peer, {
|
|
414
|
+
...peer,
|
|
415
|
+
inbound: new Map(),
|
|
416
|
+
admittedInbound: new Map(),
|
|
417
|
+
journals: new Map(),
|
|
418
|
+
ingressInFlight: new Map(),
|
|
419
|
+
retiredThroughLogicalTime: -1,
|
|
420
|
+
inFlight: null,
|
|
421
|
+
});
|
|
422
|
+
egressPeerOwners.set(input.egress, peer);
|
|
423
|
+
stackPeerOwners.set(input.stack, peer);
|
|
424
|
+
return peer;
|
|
425
|
+
}
|
|
426
|
+
export function isReferenceIntegratedScalableEvaluationPeerV1(value) {
|
|
427
|
+
return Boolean(value && typeof value === "object" && peerBindings.has(value));
|
|
428
|
+
}
|
|
429
|
+
export function createReferenceIntegratedScalableEvaluationTeamPortV1(input) {
|
|
430
|
+
assertOnlyKeys(input, ["descriptor", "definition", "peers"], [], "reference_integrated_team_options");
|
|
431
|
+
const descriptor = validateScalableEvaluationTeamDescriptorV1(input.descriptor);
|
|
432
|
+
if (descriptor.implementationId !==
|
|
433
|
+
REFERENCE_INTEGRATED_SCALABLE_EVALUATION_IMPLEMENTATION_ID_V1)
|
|
434
|
+
fail("reference_integrated_team_implementation_id_invalid");
|
|
435
|
+
if (!Array.isArray(input.peers) || input.peers.length === 0)
|
|
436
|
+
fail("reference_integrated_peers_missing");
|
|
437
|
+
const peers = new Map();
|
|
438
|
+
let definition = null;
|
|
439
|
+
let adapterDescriptorDigest = null;
|
|
440
|
+
let scope = null;
|
|
441
|
+
let objectiveDigest = null;
|
|
442
|
+
for (const peer of input.peers) {
|
|
443
|
+
const binding = peerBindings.get(peer);
|
|
444
|
+
if (!binding)
|
|
445
|
+
fail("reference_integrated_peer_not_genuine");
|
|
446
|
+
if (peerTeamOwners.has(peer))
|
|
447
|
+
fail("reference_integrated_peer_already_owned");
|
|
448
|
+
if (peers.has(binding.peerIndex))
|
|
449
|
+
fail("reference_integrated_peer_duplicate");
|
|
450
|
+
const egress = requireEgress(binding.egress);
|
|
451
|
+
if (definition === null) {
|
|
452
|
+
definition = validateScalableEvaluationDefinitionV1(input.definition, egress.descriptor);
|
|
453
|
+
adapterDescriptorDigest = egress.descriptor.descriptorDigest;
|
|
454
|
+
scope = egress.scope;
|
|
455
|
+
objectiveDigest = egress.objectiveDigest;
|
|
456
|
+
}
|
|
457
|
+
if (!sameEvaluationScope(egress.scope, scope) ||
|
|
458
|
+
egress.objectiveDigest !== objectiveDigest)
|
|
459
|
+
fail("reference_integrated_peer_scope_mismatch");
|
|
460
|
+
if (egress.descriptor.descriptorDigest !== adapterDescriptorDigest ||
|
|
461
|
+
egress.profile.profileId !== definition.profile.profileId ||
|
|
462
|
+
binding.peerIndex >= definition.profile.agentCount ||
|
|
463
|
+
!egress.descriptor.observationSchemas.some((schema) => schema.schemaDigest === binding.observationSchemaDigest))
|
|
464
|
+
fail("reference_integrated_peer_definition_mismatch");
|
|
465
|
+
peers.set(binding.peerIndex, binding);
|
|
466
|
+
}
|
|
467
|
+
if (!definition ||
|
|
468
|
+
!definition.teams.some((team) => team.descriptorDigest === descriptor.descriptorDigest))
|
|
469
|
+
fail("reference_integrated_team_definition_mismatch");
|
|
470
|
+
const port = Object.freeze({
|
|
471
|
+
descriptor,
|
|
472
|
+
stepV1: (step) => stepReferenceIntegratedTeamWithJournalV1({
|
|
473
|
+
step,
|
|
474
|
+
descriptor,
|
|
475
|
+
evaluationDefinitionDigest: definition.definitionDigest,
|
|
476
|
+
peers,
|
|
477
|
+
}),
|
|
478
|
+
ingestAcknowledgedMessageV1: (acknowledged) => ingestAcknowledgedReferenceMessageWithConcurrencyV1({
|
|
479
|
+
acknowledged,
|
|
480
|
+
descriptor,
|
|
481
|
+
evaluationDefinitionDigest: definition.definitionDigest,
|
|
482
|
+
peers,
|
|
483
|
+
}),
|
|
484
|
+
settleActionV1: (settlement) => settleReferenceActionV1({
|
|
485
|
+
settlement,
|
|
486
|
+
descriptor,
|
|
487
|
+
evaluationDefinitionDigest: definition.definitionDigest,
|
|
488
|
+
peers,
|
|
489
|
+
}),
|
|
490
|
+
});
|
|
491
|
+
for (const peer of input.peers)
|
|
492
|
+
peerTeamOwners.set(peer, port);
|
|
493
|
+
teamPortBindings.set(port, {
|
|
494
|
+
descriptor,
|
|
495
|
+
evaluationDefinitionDigest: definition.definitionDigest,
|
|
496
|
+
peers,
|
|
497
|
+
});
|
|
498
|
+
teamPorts.add(port);
|
|
499
|
+
return port;
|
|
500
|
+
}
|
|
501
|
+
export function isReferenceIntegratedScalableEvaluationTeamPortV1(value) {
|
|
502
|
+
return Boolean(value && typeof value === "object" && teamPorts.has(value));
|
|
503
|
+
}
|
|
504
|
+
async function ingestAcknowledgedReferenceMessageWithConcurrencyV1(input) {
|
|
505
|
+
const source = input.peers.get(input.acknowledged?.message?.sourcePeerIndex);
|
|
506
|
+
if (!source)
|
|
507
|
+
return ingestAcknowledgedReferenceMessageV1(input);
|
|
508
|
+
const messageId = input.acknowledged.message.messageId;
|
|
509
|
+
const inputDigest = scalableEvaluationDigestV1("reference-integrated-message-ingress-input", input.acknowledged);
|
|
510
|
+
const prior = source.ingressInFlight.get(messageId);
|
|
511
|
+
if (prior) {
|
|
512
|
+
if (prior.inputDigest !== inputDigest)
|
|
513
|
+
fail("reference_integrated_message_ingress_concurrent_conflict");
|
|
514
|
+
return prior.result;
|
|
515
|
+
}
|
|
516
|
+
const result = ingestAcknowledgedReferenceMessageV1(input);
|
|
517
|
+
source.ingressInFlight.set(messageId, Object.freeze({ inputDigest, result }));
|
|
518
|
+
try {
|
|
519
|
+
return await result;
|
|
520
|
+
}
|
|
521
|
+
finally {
|
|
522
|
+
if (source.ingressInFlight.get(messageId)?.result === result)
|
|
523
|
+
source.ingressInFlight.delete(messageId);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
async function ingestAcknowledgedReferenceMessageV1(input) {
|
|
527
|
+
const acknowledged = input.acknowledged;
|
|
528
|
+
if (!acknowledged ||
|
|
529
|
+
acknowledged.schemaVersion !== 1 ||
|
|
530
|
+
acknowledged.evaluationDefinitionDigest !==
|
|
531
|
+
input.evaluationDefinitionDigest ||
|
|
532
|
+
acknowledged.teamId !== input.descriptor.teamId)
|
|
533
|
+
fail("reference_integrated_message_ingress_scope_invalid");
|
|
534
|
+
identifier(acknowledged.sessionId, "message_ingress_session_id");
|
|
535
|
+
identifier(acknowledged.episodeId, "message_ingress_episode_id");
|
|
536
|
+
identifier(acknowledged.eventId, "message_ingress_event_id");
|
|
537
|
+
safeInteger(acknowledged.logicalTime, "message_ingress_logical_time", 0);
|
|
538
|
+
const batch = validateShardedSimulationCrossShardMessageBatchV1(acknowledged.batch);
|
|
539
|
+
validateShardedSimulationCrossShardMessageAckV1(acknowledged.bridgeAck, batch.batchId, batch.batchDigest, [acknowledged.eventId]);
|
|
540
|
+
const bridgeAck = acknowledged.bridgeAck;
|
|
541
|
+
const message = acknowledged.message;
|
|
542
|
+
const source = input.peers.get(message.sourcePeerIndex);
|
|
543
|
+
const target = input.peers.get(message.targetPeerIndex);
|
|
544
|
+
if (!source || !target)
|
|
545
|
+
fail("reference_integrated_message_ingress_peer_invalid");
|
|
546
|
+
const sourceEgress = requireEgress(source.egress);
|
|
547
|
+
const targetEgress = requireEgress(target.egress);
|
|
548
|
+
if (!sameEvaluationScope(sourceEgress.scope, targetEgress.scope) ||
|
|
549
|
+
sourceEgress.objectiveDigest !== targetEgress.objectiveDigest)
|
|
550
|
+
fail("reference_integrated_message_ingress_scope_invalid");
|
|
551
|
+
const envelope = validateReferenceIntegratedTransportEnvelopeV1(message.transportEnvelope, sourceEgress.profile);
|
|
552
|
+
const delivery = envelope.delivery;
|
|
553
|
+
if (message.messageId !== delivery.deliveryDigest ||
|
|
554
|
+
message.sourcePeerIndex !== delivery.senderPeerIndex ||
|
|
555
|
+
message.targetPeerIndex !== delivery.recipientPeerIndex ||
|
|
556
|
+
message.payloadDigest !== envelope.artifact.messageDigest ||
|
|
557
|
+
envelope.artifact.artifactDigest !== delivery.update.payloadDigest ||
|
|
558
|
+
delivery.update.createdAtLogicalTime > acknowledged.logicalTime ||
|
|
559
|
+
scalableEvaluationDigestV1("team-message-transport-envelope", envelope) !== message.transportEnvelopeDigest ||
|
|
560
|
+
new TextEncoder().encode(JSON.stringify(envelope)).byteLength !==
|
|
561
|
+
message.byteLength ||
|
|
562
|
+
batch.sessionId !== acknowledged.sessionId ||
|
|
563
|
+
batch.episodeId !== acknowledged.episodeId ||
|
|
564
|
+
batch.logicalTime !== acknowledged.logicalTime ||
|
|
565
|
+
batch.messages.length !== 1 ||
|
|
566
|
+
batch.messages[0]?.eventId !== acknowledged.eventId ||
|
|
567
|
+
batch.messages[0]?.sourcePeerIndex !== message.sourcePeerIndex ||
|
|
568
|
+
batch.messages[0]?.targetPeerIndex !== message.targetPeerIndex ||
|
|
569
|
+
batch.messages[0]?.logicalTime !== acknowledged.logicalTime ||
|
|
570
|
+
batch.messages[0]?.payloadDigest !== message.transportEnvelopeDigest)
|
|
571
|
+
fail("reference_integrated_message_ingress_binding_invalid");
|
|
572
|
+
validateMeshSparseDeliveryV2(targetEgress.profile, delivery);
|
|
573
|
+
const pendingCapture = sourceEgress.deliveries.find((record) => record.delivery.deliveryDigest === message.messageId);
|
|
574
|
+
const settledCapture = sourceEgress.settledDeliveries.get(message.messageId);
|
|
575
|
+
const sourceJournal = findStagedMessageJournalV1(source, message.messageId);
|
|
576
|
+
const stagedMessage = sourceJournal?.output?.messages.find((candidate) => candidate.messageId === message.messageId);
|
|
577
|
+
if (!sourceJournal ||
|
|
578
|
+
sourceJournal.logicalTime !== acknowledged.logicalTime ||
|
|
579
|
+
!stagedMessage ||
|
|
580
|
+
stagedMessage.transportEnvelopeDigest !== message.transportEnvelopeDigest ||
|
|
581
|
+
stagedMessage.payloadDigest !== message.payloadDigest ||
|
|
582
|
+
(!pendingCapture && !settledCapture))
|
|
583
|
+
fail("reference_integrated_message_ingress_origin_invalid");
|
|
584
|
+
bindJournalSessionV1(sourceJournal, {
|
|
585
|
+
sessionId: acknowledged.sessionId,
|
|
586
|
+
episodeId: acknowledged.episodeId,
|
|
587
|
+
logicalTime: acknowledged.logicalTime,
|
|
588
|
+
});
|
|
589
|
+
if (pendingCapture &&
|
|
590
|
+
(pendingCapture.captureDigest !==
|
|
591
|
+
findDeliveryCaptureDigestV1(source, message.messageId) ||
|
|
592
|
+
pendingCapture.sequence !== envelope.captureSequence ||
|
|
593
|
+
pendingCapture.operationId !== envelope.captureOperationId ||
|
|
594
|
+
pendingCapture.captureDigest !== envelope.captureDigest ||
|
|
595
|
+
pendingCapture.delivery.deliveryDigest !== delivery.deliveryDigest ||
|
|
596
|
+
pendingCapture.delivery.update.updateDigest !==
|
|
597
|
+
delivery.update.updateDigest))
|
|
598
|
+
fail("reference_integrated_message_ingress_origin_invalid");
|
|
599
|
+
if (!pendingCapture && settledCapture !== envelope.captureDigest)
|
|
600
|
+
fail("reference_integrated_message_ingress_origin_invalid");
|
|
601
|
+
const priorInbound = target.inbound.get(message.messageId);
|
|
602
|
+
const priorAdmitted = target.admittedInbound.get(message.messageId);
|
|
603
|
+
if ((priorInbound &&
|
|
604
|
+
priorInbound.transportEnvelopeDigest !==
|
|
605
|
+
message.transportEnvelopeDigest) ||
|
|
606
|
+
(priorAdmitted && priorAdmitted !== message.transportEnvelopeDigest))
|
|
607
|
+
fail("reference_integrated_message_ingress_idempotency_conflict");
|
|
608
|
+
const duplicate = Boolean(priorInbound || priorAdmitted);
|
|
609
|
+
if (pendingCapture &&
|
|
610
|
+
!sourceEgress.settledDeliveries.has(message.messageId) &&
|
|
611
|
+
sourceEgress.settledDeliveries.size >= sourceEgress.maximumSettledReceipts)
|
|
612
|
+
fail("reference_integrated_delivery_idempotency_window_exhausted");
|
|
613
|
+
if (!duplicate) {
|
|
614
|
+
if (target.inbound.size >= MAXIMUM_INBOUND_MESSAGES_PER_PEER)
|
|
615
|
+
fail("reference_integrated_message_ingress_exhausted");
|
|
616
|
+
await storeReferenceIntegratedCollectiveArtifactV1(target.stack, envelope.artifact);
|
|
617
|
+
target.inbound.set(message.messageId, immutable({
|
|
618
|
+
messageId: message.messageId,
|
|
619
|
+
transportEnvelopeDigest: message.transportEnvelopeDigest,
|
|
620
|
+
admittedAtLogicalTime: acknowledged.logicalTime,
|
|
621
|
+
envelope,
|
|
622
|
+
}));
|
|
623
|
+
}
|
|
624
|
+
if (pendingCapture) {
|
|
625
|
+
const captureIndex = sourceEgress.deliveries.indexOf(pendingCapture);
|
|
626
|
+
if (captureIndex < 0)
|
|
627
|
+
fail("reference_integrated_delivery_capture_unavailable");
|
|
628
|
+
sourceEgress.deliveries.splice(captureIndex, 1);
|
|
629
|
+
sourceEgress.settledDeliveries.set(message.messageId, pendingCapture.captureDigest);
|
|
630
|
+
}
|
|
631
|
+
settleJournalMessageV1(source, message.messageId);
|
|
632
|
+
const body = {
|
|
633
|
+
schemaVersion: 1,
|
|
634
|
+
evaluationDefinitionDigest: input.evaluationDefinitionDigest,
|
|
635
|
+
teamId: input.descriptor.teamId,
|
|
636
|
+
sessionId: acknowledged.sessionId,
|
|
637
|
+
episodeId: acknowledged.episodeId,
|
|
638
|
+
logicalTime: acknowledged.logicalTime,
|
|
639
|
+
eventId: acknowledged.eventId,
|
|
640
|
+
messageId: message.messageId,
|
|
641
|
+
transportEnvelopeDigest: message.transportEnvelopeDigest,
|
|
642
|
+
batchDigest: batch.batchDigest,
|
|
643
|
+
bridgeAckDigest: bridgeAck.ackDigest,
|
|
644
|
+
status: duplicate ? "duplicate" : "admitted",
|
|
645
|
+
};
|
|
646
|
+
return immutable({
|
|
647
|
+
...body,
|
|
648
|
+
receiptDigest: scalableEvaluationDigestV1("team-message-ingress-receipt", body),
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
async function settleReferenceActionV1(input) {
|
|
652
|
+
const settlement = input.settlement;
|
|
653
|
+
if (!settlement ||
|
|
654
|
+
settlement.schemaVersion !== 1 ||
|
|
655
|
+
settlement.evaluationDefinitionDigest !==
|
|
656
|
+
input.evaluationDefinitionDigest ||
|
|
657
|
+
settlement.teamId !== input.descriptor.teamId)
|
|
658
|
+
fail("reference_integrated_action_settlement_scope_invalid");
|
|
659
|
+
identifier(settlement.sessionId, "action_settlement_session_id");
|
|
660
|
+
identifier(settlement.episodeId, "action_settlement_episode_id");
|
|
661
|
+
safeInteger(settlement.peerIndex, "action_settlement_peer_index", 0);
|
|
662
|
+
safeInteger(settlement.logicalTime, "action_settlement_logical_time", 0);
|
|
663
|
+
safeInteger(settlement.actionIndex, "action_settlement_index", 0);
|
|
664
|
+
digest(settlement.outputDigest, "action_settlement_output_digest");
|
|
665
|
+
if (!settlement.request ||
|
|
666
|
+
settlement.request.schemaVersion !== 1 ||
|
|
667
|
+
settlement.request.actionId !==
|
|
668
|
+
`evaluation:${settlement.teamId}:${settlement.logicalTime}:${settlement.actionIndex}` ||
|
|
669
|
+
settlement.request.sessionId !== settlement.sessionId ||
|
|
670
|
+
settlement.request.episodeId !== settlement.episodeId ||
|
|
671
|
+
settlement.request.peerIndex !== settlement.peerIndex ||
|
|
672
|
+
settlement.request.logicalTime !== settlement.logicalTime ||
|
|
673
|
+
scalableEvaluationDigestV1("reference-integrated-staged-action", settlement.request.action) !==
|
|
674
|
+
scalableEvaluationDigestV1("reference-integrated-staged-action", settlement.action))
|
|
675
|
+
fail("reference_integrated_action_settlement_request_invalid");
|
|
676
|
+
const receipt = validateShardedSimulationEffectReceiptV1(settlement.effectReceipt, settlement.request);
|
|
677
|
+
const peer = input.peers.get(settlement.peerIndex);
|
|
678
|
+
if (!peer)
|
|
679
|
+
fail("reference_integrated_action_settlement_peer_invalid");
|
|
680
|
+
const journal = [...peer.journals.values()].find((candidate) => candidate.output?.outputDigest === settlement.outputDigest);
|
|
681
|
+
const stagedAction = journal?.output?.actions[settlement.actionIndex];
|
|
682
|
+
if (!journal ||
|
|
683
|
+
!stagedAction ||
|
|
684
|
+
scalableEvaluationDigestV1("reference-integrated-staged-action", stagedAction) !==
|
|
685
|
+
scalableEvaluationDigestV1("reference-integrated-staged-action", settlement.action))
|
|
686
|
+
fail("reference_integrated_action_settlement_binding_invalid");
|
|
687
|
+
bindJournalSessionV1(journal, {
|
|
688
|
+
sessionId: settlement.sessionId,
|
|
689
|
+
episodeId: settlement.episodeId,
|
|
690
|
+
logicalTime: settlement.logicalTime,
|
|
691
|
+
});
|
|
692
|
+
const captureDigest = journal.effectCaptureDigests[settlement.actionIndex];
|
|
693
|
+
if (!captureDigest)
|
|
694
|
+
fail("reference_integrated_action_settlement_capture_invalid");
|
|
695
|
+
const egress = requireEgress(peer.egress);
|
|
696
|
+
const pendingCapture = egress.effects.find((record) => record.captureDigest === captureDigest);
|
|
697
|
+
const settledReceiptDigest = egress.settledEffects.get(captureDigest);
|
|
698
|
+
if (pendingCapture &&
|
|
699
|
+
scalableEvaluationDigestV1("reference-integrated-staged-action", pendingCapture.action) !==
|
|
700
|
+
scalableEvaluationDigestV1("reference-integrated-staged-action", settlement.action))
|
|
701
|
+
fail("reference_integrated_action_settlement_capture_invalid");
|
|
702
|
+
if (!pendingCapture &&
|
|
703
|
+
settledReceiptDigest !== settlement.effectReceipt.receiptDigest)
|
|
704
|
+
fail("reference_integrated_action_settlement_capture_invalid");
|
|
705
|
+
const duplicate = !pendingCapture;
|
|
706
|
+
if (pendingCapture) {
|
|
707
|
+
if (!egress.settledEffects.has(captureDigest) &&
|
|
708
|
+
egress.settledEffects.size >= egress.maximumSettledReceipts)
|
|
709
|
+
fail("reference_integrated_effect_idempotency_window_exhausted");
|
|
710
|
+
egress.effects.splice(egress.effects.indexOf(pendingCapture), 1);
|
|
711
|
+
egress.settledEffects.set(captureDigest, settlement.effectReceipt.receiptDigest);
|
|
712
|
+
egress.settledEffectExecutions.set(captureDigest, pendingCapture.executionId);
|
|
713
|
+
}
|
|
714
|
+
journal.pendingActionIndexes.delete(settlement.actionIndex);
|
|
715
|
+
settleJournalIfCompleteV1(journal);
|
|
716
|
+
const body = {
|
|
717
|
+
schemaVersion: 1,
|
|
718
|
+
evaluationDefinitionDigest: input.evaluationDefinitionDigest,
|
|
719
|
+
teamId: input.descriptor.teamId,
|
|
720
|
+
sessionId: settlement.sessionId,
|
|
721
|
+
episodeId: settlement.episodeId,
|
|
722
|
+
peerIndex: settlement.peerIndex,
|
|
723
|
+
logicalTime: settlement.logicalTime,
|
|
724
|
+
actionIndex: settlement.actionIndex,
|
|
725
|
+
outputDigest: settlement.outputDigest,
|
|
726
|
+
actionDigest: settlement.request.actionDigest,
|
|
727
|
+
effectReceiptDigest: settlement.effectReceipt.receiptDigest,
|
|
728
|
+
status: duplicate ? "duplicate" : "settled",
|
|
729
|
+
};
|
|
730
|
+
return immutable({
|
|
731
|
+
...body,
|
|
732
|
+
receiptDigest: scalableEvaluationDigestV1("team-action-settlement-receipt", body),
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
async function stepReferenceIntegratedTeamWithJournalV1(input) {
|
|
736
|
+
const step = input.step;
|
|
737
|
+
if (!step ||
|
|
738
|
+
step.schemaVersion !== 1 ||
|
|
739
|
+
step.evaluationDefinitionDigest !== input.evaluationDefinitionDigest ||
|
|
740
|
+
step.teamId !== input.descriptor.teamId)
|
|
741
|
+
fail("reference_integrated_step_scope_invalid");
|
|
742
|
+
safeInteger(step.peerIndex, "step_peer_index", 0);
|
|
743
|
+
safeInteger(step.logicalTime, "step_logical_time", 0);
|
|
744
|
+
safeInteger(step.remainingInteractions, "remaining_interactions", 0);
|
|
745
|
+
safeInteger(step.remainingMessages, "remaining_messages", 0);
|
|
746
|
+
safeInteger(step.remainingMessageBytes, "remaining_message_bytes", 0);
|
|
747
|
+
const peer = input.peers.get(step.peerIndex);
|
|
748
|
+
if (!peer)
|
|
749
|
+
fail("reference_integrated_peer_not_bound");
|
|
750
|
+
const egress = requireEgress(peer.egress);
|
|
751
|
+
const observations = step.delivery
|
|
752
|
+
.observations;
|
|
753
|
+
for (const rawObservation of observations) {
|
|
754
|
+
const observation = validateMultiDomainObservationEnvelopeV1(rawObservation, egress.descriptor);
|
|
755
|
+
if (observation.domain !== step.domain ||
|
|
756
|
+
observation.schemaDigest !== peer.observationSchemaDigest ||
|
|
757
|
+
observation.logicalTime !== step.logicalTime)
|
|
758
|
+
fail("reference_integrated_observation_scope_invalid");
|
|
759
|
+
}
|
|
760
|
+
const requestDigest = step.delivery.deliveryDigest;
|
|
761
|
+
digest(requestDigest, "step_delivery_digest");
|
|
762
|
+
const stepInputDigest = scalableEvaluationDigestV1("reference-integrated-team-step-input", {
|
|
763
|
+
evaluationDefinitionDigest: step.evaluationDefinitionDigest,
|
|
764
|
+
teamId: step.teamId,
|
|
765
|
+
peerIndex: step.peerIndex,
|
|
766
|
+
domain: step.domain,
|
|
767
|
+
logicalTime: step.logicalTime,
|
|
768
|
+
deliveryDigest: requestDigest,
|
|
769
|
+
remainingInteractions: step.remainingInteractions,
|
|
770
|
+
remainingMessages: step.remainingMessages,
|
|
771
|
+
remainingMessageBytes: step.remainingMessageBytes,
|
|
772
|
+
});
|
|
773
|
+
if (peer.inFlight) {
|
|
774
|
+
if (peer.inFlight.inputDigest !== stepInputDigest)
|
|
775
|
+
fail("reference_integrated_step_concurrent_conflict");
|
|
776
|
+
return peer.inFlight.result;
|
|
777
|
+
}
|
|
778
|
+
const result = executeReferenceIntegratedTeamStepV1({
|
|
779
|
+
...input,
|
|
780
|
+
peer,
|
|
781
|
+
egress,
|
|
782
|
+
requestDigest,
|
|
783
|
+
stepInputDigest,
|
|
784
|
+
});
|
|
785
|
+
peer.inFlight = Object.freeze({ inputDigest: stepInputDigest, result });
|
|
786
|
+
try {
|
|
787
|
+
return await result;
|
|
788
|
+
}
|
|
789
|
+
finally {
|
|
790
|
+
if (peer.inFlight?.result === result)
|
|
791
|
+
peer.inFlight = null;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
async function executeReferenceIntegratedTeamStepV1(input) {
|
|
795
|
+
const { step, peer, egress, requestDigest, stepInputDigest } = input;
|
|
796
|
+
let journal = peer.journals.get(requestDigest);
|
|
797
|
+
if (journal) {
|
|
798
|
+
if (journal.inputDigest !== stepInputDigest)
|
|
799
|
+
fail("reference_integrated_step_retry_conflict");
|
|
800
|
+
if (journal.phase === "indeterminate")
|
|
801
|
+
fail("reference_integrated_step_indeterminate");
|
|
802
|
+
if (journal.output)
|
|
803
|
+
return journal.output;
|
|
804
|
+
}
|
|
805
|
+
else {
|
|
806
|
+
if (step.logicalTime <= peer.retiredThroughLogicalTime)
|
|
807
|
+
fail("reference_integrated_step_retry_window_expired");
|
|
808
|
+
pruneSettledStepJournalsV1(peer);
|
|
809
|
+
if (peer.journals.size >= MAXIMUM_STEP_JOURNALS_PER_PEER)
|
|
810
|
+
fail("reference_integrated_step_journal_exhausted");
|
|
811
|
+
const initial = await peer.stack.node.loadOptional();
|
|
812
|
+
journal = {
|
|
813
|
+
requestDigest,
|
|
814
|
+
inputDigest: stepInputDigest,
|
|
815
|
+
logicalTime: step.logicalTime,
|
|
816
|
+
preStateDigest: initial?.stateDigest ?? null,
|
|
817
|
+
phase: "prepared",
|
|
818
|
+
postStateDigest: null,
|
|
819
|
+
deliveryCaptureDigests: [],
|
|
820
|
+
effectCaptureDigests: [],
|
|
821
|
+
output: null,
|
|
822
|
+
pendingMessageIds: new Set(),
|
|
823
|
+
pendingActionIndexes: new Set(),
|
|
824
|
+
processedInboundMessageIds: new Set(),
|
|
825
|
+
sessionBinding: null,
|
|
826
|
+
};
|
|
827
|
+
peer.journals.set(requestDigest, journal);
|
|
828
|
+
}
|
|
829
|
+
if (!journal)
|
|
830
|
+
fail("reference_integrated_step_journal_unavailable");
|
|
831
|
+
let state = await peer.stack.node.loadOptional();
|
|
832
|
+
if (journal.phase === "node_mutated") {
|
|
833
|
+
if (!state || state.stateDigest !== journal.postStateDigest) {
|
|
834
|
+
journal.phase = "indeterminate";
|
|
835
|
+
fail("reference_integrated_step_indeterminate");
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
else {
|
|
839
|
+
const currentDigest = state?.stateDigest ?? null;
|
|
840
|
+
if (currentDigest !== journal.preStateDigest) {
|
|
841
|
+
journal.phase = "indeterminate";
|
|
842
|
+
fail("reference_integrated_step_indeterminate");
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
if (journal.phase === "prepared") {
|
|
846
|
+
beginEgressCapture(egress, stepInputDigest);
|
|
847
|
+
try {
|
|
848
|
+
if (state === null) {
|
|
849
|
+
state = await mutateNodeForJournalV1({
|
|
850
|
+
peer,
|
|
851
|
+
journal,
|
|
852
|
+
operation: () => peer.stack.node.initialize(0),
|
|
853
|
+
});
|
|
854
|
+
journal.preStateDigest = state.stateDigest;
|
|
855
|
+
}
|
|
856
|
+
state = await drainReferenceIntegratedInboundV1({
|
|
857
|
+
peer,
|
|
858
|
+
egress,
|
|
859
|
+
journal,
|
|
860
|
+
state,
|
|
861
|
+
logicalTime: step.logicalTime,
|
|
862
|
+
});
|
|
863
|
+
journal.preStateDigest = state.stateDigest;
|
|
864
|
+
if (step.logicalTime < state.logicalTimeHighWaterMs)
|
|
865
|
+
fail("reference_integrated_step_time_rollback");
|
|
866
|
+
if (state.intent === null) {
|
|
867
|
+
if (state.status !== "idle")
|
|
868
|
+
fail("reference_integrated_mission_state_invalid");
|
|
869
|
+
state = await mutateNodeForJournalV1({
|
|
870
|
+
peer,
|
|
871
|
+
journal,
|
|
872
|
+
operation: () => peer.stack.node.submitMission({
|
|
873
|
+
intent: peer.missionIntent,
|
|
874
|
+
logicalTimeMs: step.logicalTime,
|
|
875
|
+
}),
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
else {
|
|
879
|
+
if (state.intent.intentDigest !== peer.missionIntent.intentDigest)
|
|
880
|
+
fail("reference_integrated_mission_substitution");
|
|
881
|
+
state = await mutateNodeForJournalV1({
|
|
882
|
+
peer,
|
|
883
|
+
journal,
|
|
884
|
+
operation: () => peer.stack.node.advance({ logicalTimeMs: step.logicalTime }),
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
journal.postStateDigest = state.stateDigest;
|
|
888
|
+
journal.deliveryCaptureDigests = egress.deliveries
|
|
889
|
+
.filter((record) => record.operationId === stepInputDigest)
|
|
890
|
+
.map((record) => record.captureDigest);
|
|
891
|
+
journal.effectCaptureDigests = egress.effects
|
|
892
|
+
.filter((record) => record.operationId === stepInputDigest)
|
|
893
|
+
.map((record) => record.captureDigest);
|
|
894
|
+
journal.phase = "node_mutated";
|
|
895
|
+
}
|
|
896
|
+
catch (error) {
|
|
897
|
+
const capturesExist = egress.deliveries.some((record) => record.operationId === stepInputDigest) ||
|
|
898
|
+
egress.effects.some((record) => record.operationId === stepInputDigest);
|
|
899
|
+
const current = await peer.stack.node.loadOptional().catch(() => null);
|
|
900
|
+
if (capturesExist ||
|
|
901
|
+
(current?.stateDigest ?? null) !== journal.preStateDigest)
|
|
902
|
+
journal.phase = "indeterminate";
|
|
903
|
+
throw error;
|
|
904
|
+
}
|
|
905
|
+
finally {
|
|
906
|
+
endEgressCapture(egress, stepInputDigest);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
state = await peer.stack.node.load();
|
|
910
|
+
if (journal.phase !== "node_mutated" ||
|
|
911
|
+
state.stateDigest !== journal.postStateDigest) {
|
|
912
|
+
journal.phase = "indeterminate";
|
|
913
|
+
fail("reference_integrated_step_indeterminate");
|
|
914
|
+
}
|
|
915
|
+
const capturedDeliveries = journal.deliveryCaptureDigests.map((identity) => {
|
|
916
|
+
const record = egress.deliveries.find((candidate) => candidate.captureDigest === identity);
|
|
917
|
+
if (!record)
|
|
918
|
+
fail("reference_integrated_delivery_capture_unavailable");
|
|
919
|
+
return record;
|
|
920
|
+
});
|
|
921
|
+
const capturedEffects = journal.effectCaptureDigests.map((identity) => {
|
|
922
|
+
const record = egress.effects.find((candidate) => candidate.captureDigest === identity);
|
|
923
|
+
if (!record)
|
|
924
|
+
fail("reference_integrated_effect_capture_unavailable");
|
|
925
|
+
return record;
|
|
926
|
+
});
|
|
927
|
+
const messages = await Promise.all(capturedDeliveries.map(async (captured) => {
|
|
928
|
+
const artifact = await readReferenceIntegratedCollectiveArtifactV1(peer.stack, captured.delivery.update.payloadDigest);
|
|
929
|
+
if (!artifact)
|
|
930
|
+
fail("reference_integrated_outbox_artifact_missing");
|
|
931
|
+
const message = validateCapturedArtifact(artifact, captured.delivery.update);
|
|
932
|
+
if (captured.operationId === null)
|
|
933
|
+
fail("reference_integrated_delivery_capture_operation_missing");
|
|
934
|
+
const transportEnvelope = immutable({
|
|
935
|
+
schemaVersion: 1,
|
|
936
|
+
kind: "reference_integrated_sparse_delivery",
|
|
937
|
+
captureSequence: captured.sequence,
|
|
938
|
+
captureOperationId: captured.operationId,
|
|
939
|
+
captureDigest: captured.captureDigest,
|
|
940
|
+
delivery: captured.delivery,
|
|
941
|
+
artifact: message,
|
|
942
|
+
});
|
|
943
|
+
const transportEnvelopeDigest = scalableEvaluationDigestV1("team-message-transport-envelope", transportEnvelope);
|
|
944
|
+
const byteLength = new TextEncoder().encode(JSON.stringify(transportEnvelope)).byteLength;
|
|
945
|
+
if (byteLength < 1)
|
|
946
|
+
fail("reference_integrated_message_size_invalid");
|
|
947
|
+
return Object.freeze({
|
|
948
|
+
schemaVersion: 1,
|
|
949
|
+
messageId: captured.delivery.deliveryDigest,
|
|
950
|
+
sourcePeerIndex: captured.delivery.senderPeerIndex,
|
|
951
|
+
targetPeerIndex: captured.delivery.recipientPeerIndex,
|
|
952
|
+
payloadDigest: message.messageDigest,
|
|
953
|
+
transportEnvelope: transportEnvelope,
|
|
954
|
+
transportEnvelopeDigest,
|
|
955
|
+
byteLength,
|
|
956
|
+
});
|
|
957
|
+
}));
|
|
958
|
+
const messageBytes = messages.reduce((total, message) => total + message.byteLength, 0);
|
|
959
|
+
if (messages.length > Math.min(step.remainingMessages, MAXIMUM_STEP_MESSAGES) ||
|
|
960
|
+
messageBytes >
|
|
961
|
+
Math.min(step.remainingMessageBytes, MAXIMUM_STEP_MESSAGE_BYTES))
|
|
962
|
+
fail("reference_integrated_step_message_budget_exceeded");
|
|
963
|
+
if (capturedEffects.length > MAXIMUM_STEP_ACTIONS)
|
|
964
|
+
fail("reference_integrated_step_action_budget_exceeded");
|
|
965
|
+
const actions = capturedEffects.map((captured) => {
|
|
966
|
+
const execution = state.executionReceipts.find((receipt) => receipt.executionId === captured.executionId);
|
|
967
|
+
if (!execution ||
|
|
968
|
+
execution.status !== "completed" ||
|
|
969
|
+
execution.effect?.proposalDigest !== captured.proposalDigest ||
|
|
970
|
+
execution.effectReceipt?.externalReference !==
|
|
971
|
+
captured.receipt.externalReference ||
|
|
972
|
+
execution.effectReceipt.receiptDigest !== captured.receipt.receiptDigest)
|
|
973
|
+
fail("reference_integrated_effect_receipt_mismatch");
|
|
974
|
+
if (captured.action.domain !== step.domain)
|
|
975
|
+
fail("reference_integrated_effect_domain_mismatch");
|
|
976
|
+
return captured.action;
|
|
977
|
+
});
|
|
978
|
+
const publicMetadata = {
|
|
979
|
+
adapterKind: "reference_integrated_collective_stack",
|
|
980
|
+
nodeStateDigest: state.stateDigest,
|
|
981
|
+
outboundDeliveryDigests: capturedDeliveries.map((record) => record.delivery.deliveryDigest),
|
|
982
|
+
effectCaptureDigests: capturedEffects.map((record) => record.captureDigest),
|
|
983
|
+
};
|
|
984
|
+
const body = {
|
|
985
|
+
schemaVersion: 1,
|
|
986
|
+
teamId: input.descriptor.teamId,
|
|
987
|
+
logicalTime: step.logicalTime,
|
|
988
|
+
messages: Object.freeze(messages),
|
|
989
|
+
actions: Object.freeze(actions),
|
|
990
|
+
publicMetadata,
|
|
991
|
+
};
|
|
992
|
+
const output = immutable({
|
|
993
|
+
...body,
|
|
994
|
+
outputDigest: scalableEvaluationDigestV1("team-step-output", body),
|
|
995
|
+
});
|
|
996
|
+
journal.output = output;
|
|
997
|
+
for (const message of output.messages)
|
|
998
|
+
journal.pendingMessageIds.add(message.messageId);
|
|
999
|
+
for (let index = 0; index < output.actions.length; index += 1)
|
|
1000
|
+
journal.pendingActionIndexes.add(index);
|
|
1001
|
+
journal.phase =
|
|
1002
|
+
journal.pendingMessageIds.size === 0 &&
|
|
1003
|
+
journal.pendingActionIndexes.size === 0
|
|
1004
|
+
? "settled"
|
|
1005
|
+
: "output_staged";
|
|
1006
|
+
return output;
|
|
1007
|
+
}
|
|
1008
|
+
function validateCapturedArtifact(value, update) {
|
|
1009
|
+
if (!value || typeof value !== "object")
|
|
1010
|
+
fail("reference_integrated_outbox_artifact_invalid");
|
|
1011
|
+
const artifact = value;
|
|
1012
|
+
if (artifact.schemaVersion !== 1 ||
|
|
1013
|
+
artifact.artifactDigest !== update.payloadDigest ||
|
|
1014
|
+
!DIGEST.test(artifact.messageDigest))
|
|
1015
|
+
fail("reference_integrated_outbox_artifact_invalid");
|
|
1016
|
+
return artifact;
|
|
1017
|
+
}
|
|
1018
|
+
function beginEgressCapture(binding, operationId) {
|
|
1019
|
+
if (binding.activeOperationId !== null &&
|
|
1020
|
+
binding.activeOperationId !== operationId)
|
|
1021
|
+
fail("reference_integrated_capture_concurrent_conflict");
|
|
1022
|
+
binding.activeOperationId = operationId;
|
|
1023
|
+
}
|
|
1024
|
+
function endEgressCapture(binding, operationId) {
|
|
1025
|
+
if (binding.activeOperationId !== operationId)
|
|
1026
|
+
fail("reference_integrated_capture_lease_invalid");
|
|
1027
|
+
binding.activeOperationId = null;
|
|
1028
|
+
}
|
|
1029
|
+
async function mutateNodeForJournalV1(input) {
|
|
1030
|
+
const before = input.journal.preStateDigest;
|
|
1031
|
+
try {
|
|
1032
|
+
return await input.operation();
|
|
1033
|
+
}
|
|
1034
|
+
catch (error) {
|
|
1035
|
+
const current = await input.peer.stack.node
|
|
1036
|
+
.loadOptional()
|
|
1037
|
+
.catch(() => null);
|
|
1038
|
+
if ((current?.stateDigest ?? null) !== before)
|
|
1039
|
+
input.journal.phase = "indeterminate";
|
|
1040
|
+
throw error;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
async function drainReferenceIntegratedInboundV1(input) {
|
|
1044
|
+
let state = input.state;
|
|
1045
|
+
const records = [...input.peer.inbound.values()].sort((left, right) => {
|
|
1046
|
+
const leftArtifact = left.envelope.artifact;
|
|
1047
|
+
const rightArtifact = right.envelope.artifact;
|
|
1048
|
+
return (leftArtifact.logicalTimeMs - rightArtifact.logicalTimeMs ||
|
|
1049
|
+
leftArtifact.sequence - rightArtifact.sequence ||
|
|
1050
|
+
left.messageId.localeCompare(right.messageId));
|
|
1051
|
+
});
|
|
1052
|
+
for (const record of records) {
|
|
1053
|
+
const delivery = record.envelope.delivery;
|
|
1054
|
+
if (!input.peer.admittedInbound.has(record.messageId) &&
|
|
1055
|
+
input.peer.admittedInbound.size >= MAXIMUM_INBOUND_MESSAGES_PER_PEER)
|
|
1056
|
+
fail("reference_integrated_inbound_idempotency_window_exhausted");
|
|
1057
|
+
if (delivery.recipientPeerIndex !== input.peer.peerIndex ||
|
|
1058
|
+
delivery.update.createdAtLogicalTime > input.logicalTime ||
|
|
1059
|
+
delivery.update.expiresAtLogicalTime <= input.logicalTime)
|
|
1060
|
+
fail("reference_integrated_inbound_delivery_invalid");
|
|
1061
|
+
const planeResult = await invokeMeshSparsePeerPlaneReceiveV1(input.egress.plane, {
|
|
1062
|
+
delivery,
|
|
1063
|
+
logicalTime: input.logicalTime,
|
|
1064
|
+
});
|
|
1065
|
+
if (!planeResult.accepted)
|
|
1066
|
+
fail(`reference_integrated_plane_receive_${planeResult.reasonCode ?? "rejected"}`);
|
|
1067
|
+
const artifact = await readReferenceIntegratedCollectiveArtifactV1(input.peer.stack, delivery.update.payloadDigest);
|
|
1068
|
+
if (!artifact ||
|
|
1069
|
+
artifact.messageDigest !== record.envelope.artifact.messageDigest)
|
|
1070
|
+
fail("reference_integrated_inbound_artifact_unavailable");
|
|
1071
|
+
const before = state.stateDigest;
|
|
1072
|
+
let receive;
|
|
1073
|
+
try {
|
|
1074
|
+
receive = await input.peer.stack.node.receive(delivery.update, input.logicalTime);
|
|
1075
|
+
}
|
|
1076
|
+
catch (error) {
|
|
1077
|
+
const current = await input.peer.stack.node
|
|
1078
|
+
.loadOptional()
|
|
1079
|
+
.catch(() => null);
|
|
1080
|
+
if ((current?.stateDigest ?? null) !== before)
|
|
1081
|
+
input.journal.phase = "indeterminate";
|
|
1082
|
+
throw error;
|
|
1083
|
+
}
|
|
1084
|
+
if (receive.status === "rejected")
|
|
1085
|
+
fail(`reference_integrated_receive_${receive.reasonCode}`);
|
|
1086
|
+
if (receive.status === "deferred")
|
|
1087
|
+
continue;
|
|
1088
|
+
if (receive.status !== "accepted" && receive.status !== "duplicate")
|
|
1089
|
+
fail("reference_integrated_receive_status_invalid");
|
|
1090
|
+
input.peer.inbound.delete(record.messageId);
|
|
1091
|
+
input.peer.admittedInbound.set(record.messageId, record.transportEnvelopeDigest);
|
|
1092
|
+
input.journal.processedInboundMessageIds.add(record.messageId);
|
|
1093
|
+
state = await input.peer.stack.node.load();
|
|
1094
|
+
input.journal.preStateDigest = state.stateDigest;
|
|
1095
|
+
}
|
|
1096
|
+
return state;
|
|
1097
|
+
}
|
|
1098
|
+
function validateReferenceIntegratedTransportEnvelopeV1(value, profile) {
|
|
1099
|
+
const record = exactRecord(value, [
|
|
1100
|
+
"schemaVersion",
|
|
1101
|
+
"kind",
|
|
1102
|
+
"captureSequence",
|
|
1103
|
+
"captureOperationId",
|
|
1104
|
+
"captureDigest",
|
|
1105
|
+
"delivery",
|
|
1106
|
+
"artifact",
|
|
1107
|
+
], "reference_integrated_transport_envelope");
|
|
1108
|
+
if (record.schemaVersion !== 1 ||
|
|
1109
|
+
record.kind !== "reference_integrated_sparse_delivery")
|
|
1110
|
+
fail("reference_integrated_transport_envelope_invalid");
|
|
1111
|
+
safeInteger(record.captureSequence, "transport_capture_sequence", 1);
|
|
1112
|
+
digest(record.captureOperationId, "transport_capture_operation_id");
|
|
1113
|
+
digest(record.captureDigest, "transport_capture_digest");
|
|
1114
|
+
const delivery = validateMeshSparseDeliveryV2(profile, record.delivery);
|
|
1115
|
+
if (scalableEvaluationDigestV1("reference-integrated-delivery-capture", {
|
|
1116
|
+
sequence: record.captureSequence,
|
|
1117
|
+
operationId: record.captureOperationId,
|
|
1118
|
+
updateDigest: delivery.update.updateDigest,
|
|
1119
|
+
deliveryDigest: delivery.deliveryDigest,
|
|
1120
|
+
}) !== record.captureDigest)
|
|
1121
|
+
fail("reference_integrated_transport_capture_invalid");
|
|
1122
|
+
const artifact = validateCapturedArtifact(record.artifact, delivery.update);
|
|
1123
|
+
return immutable({
|
|
1124
|
+
schemaVersion: 1,
|
|
1125
|
+
kind: "reference_integrated_sparse_delivery",
|
|
1126
|
+
captureSequence: record.captureSequence,
|
|
1127
|
+
captureOperationId: record.captureOperationId,
|
|
1128
|
+
captureDigest: record.captureDigest,
|
|
1129
|
+
delivery,
|
|
1130
|
+
artifact,
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
function findStagedMessageJournalV1(peer, messageId) {
|
|
1134
|
+
const matches = [...peer.journals.values()].filter((journal) => journal.output?.messages.some((message) => message.messageId === messageId));
|
|
1135
|
+
if (matches.length > 1)
|
|
1136
|
+
fail("reference_integrated_message_journal_conflict");
|
|
1137
|
+
return matches[0] ?? null;
|
|
1138
|
+
}
|
|
1139
|
+
function findDeliveryCaptureDigestV1(peer, messageId) {
|
|
1140
|
+
const matches = [...peer.journals.values()].flatMap((journal) => {
|
|
1141
|
+
const messageIndex = journal.output?.messages.findIndex((message) => message.messageId === messageId);
|
|
1142
|
+
return messageIndex === undefined || messageIndex < 0
|
|
1143
|
+
? []
|
|
1144
|
+
: [journal.deliveryCaptureDigests[messageIndex]];
|
|
1145
|
+
});
|
|
1146
|
+
if (matches.length > 1)
|
|
1147
|
+
fail("reference_integrated_delivery_capture_journal_conflict");
|
|
1148
|
+
return matches[0] ?? null;
|
|
1149
|
+
}
|
|
1150
|
+
function settleJournalMessageV1(peer, messageId) {
|
|
1151
|
+
const journals = [...peer.journals.values()].filter((journal) => journal.output?.messages.some((message) => message.messageId === messageId));
|
|
1152
|
+
if (journals.length !== 1)
|
|
1153
|
+
fail("reference_integrated_message_journal_unavailable");
|
|
1154
|
+
journals[0].pendingMessageIds.delete(messageId);
|
|
1155
|
+
settleJournalIfCompleteV1(journals[0]);
|
|
1156
|
+
}
|
|
1157
|
+
function settleJournalIfCompleteV1(journal) {
|
|
1158
|
+
if (journal.output &&
|
|
1159
|
+
journal.pendingMessageIds.size === 0 &&
|
|
1160
|
+
journal.pendingActionIndexes.size === 0)
|
|
1161
|
+
journal.phase = "settled";
|
|
1162
|
+
}
|
|
1163
|
+
function pruneSettledStepJournalsV1(peer) {
|
|
1164
|
+
while (peer.journals.size >= MAXIMUM_STEP_JOURNALS_PER_PEER) {
|
|
1165
|
+
const settled = [...peer.journals.values()]
|
|
1166
|
+
.filter((journal) => journal.phase === "settled")
|
|
1167
|
+
.sort((left, right) => left.logicalTime - right.logicalTime ||
|
|
1168
|
+
left.requestDigest.localeCompare(right.requestDigest))[0];
|
|
1169
|
+
if (!settled)
|
|
1170
|
+
return;
|
|
1171
|
+
const egress = requireEgress(peer.egress);
|
|
1172
|
+
for (const message of settled.output?.messages ?? []) {
|
|
1173
|
+
egress.settledDeliveries.delete(message.messageId);
|
|
1174
|
+
egress.deliveryIds.delete(message.messageId);
|
|
1175
|
+
}
|
|
1176
|
+
for (const captureDigest of settled.effectCaptureDigests) {
|
|
1177
|
+
const executionId = egress.settledEffectExecutions.get(captureDigest);
|
|
1178
|
+
if (executionId)
|
|
1179
|
+
egress.effectReceipts.delete(executionId);
|
|
1180
|
+
egress.settledEffectExecutions.delete(captureDigest);
|
|
1181
|
+
egress.settledEffects.delete(captureDigest);
|
|
1182
|
+
}
|
|
1183
|
+
for (const messageId of settled.processedInboundMessageIds)
|
|
1184
|
+
peer.admittedInbound.delete(messageId);
|
|
1185
|
+
peer.journals.delete(settled.requestDigest);
|
|
1186
|
+
peer.retiredThroughLogicalTime = Math.max(peer.retiredThroughLogicalTime, settled.logicalTime);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
function bindJournalSessionV1(journal, binding) {
|
|
1190
|
+
if (journal.logicalTime !== binding.logicalTime)
|
|
1191
|
+
fail("reference_integrated_journal_session_binding_invalid");
|
|
1192
|
+
if (journal.sessionBinding) {
|
|
1193
|
+
if (journal.sessionBinding.sessionId !== binding.sessionId ||
|
|
1194
|
+
journal.sessionBinding.episodeId !== binding.episodeId ||
|
|
1195
|
+
journal.sessionBinding.logicalTime !== binding.logicalTime)
|
|
1196
|
+
fail("reference_integrated_journal_session_binding_invalid");
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
journal.sessionBinding = Object.freeze({ ...binding });
|
|
1200
|
+
}
|
|
1201
|
+
function assignmentFor(binding, workItemId) {
|
|
1202
|
+
identifier(workItemId, "work_item_id");
|
|
1203
|
+
const existing = binding.assignments.get(workItemId);
|
|
1204
|
+
if (existing)
|
|
1205
|
+
return existing;
|
|
1206
|
+
const assignment = immutable({
|
|
1207
|
+
assignedPeerId: binding.localPeerId,
|
|
1208
|
+
assignmentEpoch: binding.initialAssignmentEpoch,
|
|
1209
|
+
fencingToken: `${binding.fencingTokenPrefix}:${binding.initialAssignmentEpoch}:${workItemId}`,
|
|
1210
|
+
});
|
|
1211
|
+
binding.assignments.set(workItemId, assignment);
|
|
1212
|
+
return assignment;
|
|
1213
|
+
}
|
|
1214
|
+
async function validateAuthorityFence(binding, fence, input) {
|
|
1215
|
+
const assignment = assignmentFor(binding, fence.scope.workItemId);
|
|
1216
|
+
if (fence.executionId !== input.executionId ||
|
|
1217
|
+
fence.scope.tenantId !== binding.scope.tenantId ||
|
|
1218
|
+
fence.scope.meshId !== binding.scope.meshId ||
|
|
1219
|
+
fence.scope.missionIntentId !== binding.scope.missionIntentId ||
|
|
1220
|
+
fence.assignedPeerId !== assignment.assignedPeerId ||
|
|
1221
|
+
fence.assignmentEpoch !== assignment.assignmentEpoch ||
|
|
1222
|
+
fence.fencingToken !== assignment.fencingToken ||
|
|
1223
|
+
fence.membershipConfigurationDigest !==
|
|
1224
|
+
binding.membershipConfigurationDigest ||
|
|
1225
|
+
fence.membershipEpoch !== binding.membershipEpoch ||
|
|
1226
|
+
!DIGEST.test(fence.awardDigest) ||
|
|
1227
|
+
!DIGEST.test(fence.taskDigest) ||
|
|
1228
|
+
!DIGEST.test(input.effect.proposalDigest))
|
|
1229
|
+
fail("reference_integrated_effect_authority_invalid");
|
|
1230
|
+
safeInteger(input.logicalTimeMs, "effect_logical_time", 0);
|
|
1231
|
+
const { authorityDigest, ...body } = fence;
|
|
1232
|
+
const rebuilt = await createAssuranceExecutionAuthorityFenceV1(body, binding.crypto);
|
|
1233
|
+
if (authorityDigest !== rebuilt.authorityDigest)
|
|
1234
|
+
fail("reference_integrated_effect_authority_invalid");
|
|
1235
|
+
}
|
|
1236
|
+
function validateScope(input) {
|
|
1237
|
+
if (!input || typeof input !== "object")
|
|
1238
|
+
fail("reference_integrated_scope_invalid");
|
|
1239
|
+
const value = exactRecord(input, ["tenantId", "meshId", "missionIntentId", "objectiveId"], "reference_integrated_scope");
|
|
1240
|
+
const tenantId = value.tenantId;
|
|
1241
|
+
const meshId = value.meshId;
|
|
1242
|
+
const missionIntentId = value.missionIntentId;
|
|
1243
|
+
const objectiveId = value.objectiveId;
|
|
1244
|
+
identifier(tenantId, "tenantId");
|
|
1245
|
+
identifier(meshId, "meshId");
|
|
1246
|
+
identifier(missionIntentId, "missionIntentId");
|
|
1247
|
+
identifier(objectiveId, "objectiveId");
|
|
1248
|
+
return immutable({
|
|
1249
|
+
tenantId,
|
|
1250
|
+
meshId,
|
|
1251
|
+
missionIntentId,
|
|
1252
|
+
objectiveId,
|
|
1253
|
+
});
|
|
1254
|
+
}
|
|
1255
|
+
function objectiveScopeDigest(missionIntent) {
|
|
1256
|
+
return scalableEvaluationDigestV1("reference-integrated-objective-scope", missionIntent.objective);
|
|
1257
|
+
}
|
|
1258
|
+
function sameEvaluationScope(left, right) {
|
|
1259
|
+
return (left.tenantId === right.tenantId &&
|
|
1260
|
+
left.meshId === right.meshId &&
|
|
1261
|
+
left.missionIntentId === right.missionIntentId &&
|
|
1262
|
+
left.objectiveId === right.objectiveId);
|
|
1263
|
+
}
|
|
1264
|
+
function requireEgress(value) {
|
|
1265
|
+
const binding = egressBindings.get(value);
|
|
1266
|
+
if (!binding)
|
|
1267
|
+
fail("reference_integrated_egress_not_genuine");
|
|
1268
|
+
return binding;
|
|
1269
|
+
}
|
|
1270
|
+
function exactRecord(input, keys, label) {
|
|
1271
|
+
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
1272
|
+
fail(`${label}_invalid`);
|
|
1273
|
+
const actual = Object.keys(input).sort();
|
|
1274
|
+
const expected = [...keys].sort();
|
|
1275
|
+
if (actual.length !== expected.length ||
|
|
1276
|
+
actual.some((key, index) => key !== expected[index]))
|
|
1277
|
+
fail(`${label}_invalid`);
|
|
1278
|
+
return input;
|
|
1279
|
+
}
|
|
1280
|
+
function assertOnlyKeys(input, required, optional, label) {
|
|
1281
|
+
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
1282
|
+
fail(`${label}_invalid`);
|
|
1283
|
+
const keys = Object.keys(input);
|
|
1284
|
+
if (required.some((key) => !keys.includes(key)) ||
|
|
1285
|
+
keys.some((key) => !required.includes(key) && !optional.includes(key)))
|
|
1286
|
+
fail(`${label}_invalid`);
|
|
1287
|
+
}
|
|
1288
|
+
function identifier(value, label) {
|
|
1289
|
+
if (typeof value !== "string" ||
|
|
1290
|
+
!/^[A-Za-z0-9][A-Za-z0-9._:@/+=-]{0,255}$/u.test(value))
|
|
1291
|
+
fail(`${label}_invalid`);
|
|
1292
|
+
}
|
|
1293
|
+
function digest(value, label) {
|
|
1294
|
+
if (typeof value !== "string" || !DIGEST.test(value))
|
|
1295
|
+
fail(`${label}_invalid`);
|
|
1296
|
+
}
|
|
1297
|
+
function safeInteger(value, label, minimum, maximum = Number.MAX_SAFE_INTEGER) {
|
|
1298
|
+
if (!Number.isSafeInteger(value) ||
|
|
1299
|
+
value < minimum ||
|
|
1300
|
+
value > maximum)
|
|
1301
|
+
fail(`${label}_invalid`);
|
|
1302
|
+
}
|
|
1303
|
+
function immutable(value) {
|
|
1304
|
+
const clone = structuredClone(value);
|
|
1305
|
+
const visit = (item) => {
|
|
1306
|
+
if (!item || typeof item !== "object" || Object.isFrozen(item))
|
|
1307
|
+
return;
|
|
1308
|
+
for (const child of Object.values(item))
|
|
1309
|
+
visit(child);
|
|
1310
|
+
Object.freeze(item);
|
|
1311
|
+
};
|
|
1312
|
+
visit(clone);
|
|
1313
|
+
return clone;
|
|
1314
|
+
}
|
|
1315
|
+
function fail(code) {
|
|
1316
|
+
throw new TypeError(code);
|
|
1317
|
+
}
|
|
1318
|
+
//# sourceMappingURL=scalable-evaluation-reference-integrated.js.map
|