@agentplat/mesh 0.3.0-alpha.1 → 0.3.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +247 -2
  2. package/dist/coordination-allocation-contracts.d.ts +598 -0
  3. package/dist/coordination-allocation-contracts.d.ts.map +1 -0
  4. package/dist/coordination-allocation-contracts.js +2 -0
  5. package/dist/coordination-allocation-contracts.js.map +1 -0
  6. package/dist/coordination-allocation-state.d.ts +19 -0
  7. package/dist/coordination-allocation-state.d.ts.map +1 -0
  8. package/dist/coordination-allocation-state.js +5496 -0
  9. package/dist/coordination-allocation-state.js.map +1 -0
  10. package/dist/coordination-allocation.d.ts +10 -0
  11. package/dist/coordination-allocation.d.ts.map +1 -0
  12. package/dist/coordination-allocation.js +2743 -0
  13. package/dist/coordination-allocation.js.map +1 -0
  14. package/dist/coordination-contracts.d.ts +78 -0
  15. package/dist/coordination-contracts.d.ts.map +1 -0
  16. package/dist/coordination-contracts.js +2 -0
  17. package/dist/coordination-contracts.js.map +1 -0
  18. package/dist/coordination-discovery-contracts.d.ts +150 -0
  19. package/dist/coordination-discovery-contracts.d.ts.map +1 -0
  20. package/dist/coordination-discovery-contracts.js +2 -0
  21. package/dist/coordination-discovery-contracts.js.map +1 -0
  22. package/dist/coordination-discovery-state.d.ts +12 -0
  23. package/dist/coordination-discovery-state.d.ts.map +1 -0
  24. package/dist/coordination-discovery-state.js +542 -0
  25. package/dist/coordination-discovery-state.js.map +1 -0
  26. package/dist/coordination-discovery.d.ts +19 -0
  27. package/dist/coordination-discovery.d.ts.map +1 -0
  28. package/dist/coordination-discovery.js +850 -0
  29. package/dist/coordination-discovery.js.map +1 -0
  30. package/dist/coordination-execution.d.ts +6 -0
  31. package/dist/coordination-execution.d.ts.map +1 -0
  32. package/dist/coordination-execution.js +854 -0
  33. package/dist/coordination-execution.js.map +1 -0
  34. package/dist/coordination-inbound-contracts.d.ts +150 -0
  35. package/dist/coordination-inbound-contracts.d.ts.map +1 -0
  36. package/dist/coordination-inbound-contracts.js +2 -0
  37. package/dist/coordination-inbound-contracts.js.map +1 -0
  38. package/dist/coordination-inbound-state.d.ts +26 -0
  39. package/dist/coordination-inbound-state.d.ts.map +1 -0
  40. package/dist/coordination-inbound-state.js +331 -0
  41. package/dist/coordination-inbound-state.js.map +1 -0
  42. package/dist/coordination-inbound.d.ts +16 -0
  43. package/dist/coordination-inbound.d.ts.map +1 -0
  44. package/dist/coordination-inbound.js +944 -0
  45. package/dist/coordination-inbound.js.map +1 -0
  46. package/dist/coordination-lease-renewal.d.ts +8 -0
  47. package/dist/coordination-lease-renewal.d.ts.map +1 -0
  48. package/dist/coordination-lease-renewal.js +518 -0
  49. package/dist/coordination-lease-renewal.js.map +1 -0
  50. package/dist/coordination-objective-topic-contracts.d.ts +70 -0
  51. package/dist/coordination-objective-topic-contracts.d.ts.map +1 -0
  52. package/dist/coordination-objective-topic-contracts.js +2 -0
  53. package/dist/coordination-objective-topic-contracts.js.map +1 -0
  54. package/dist/coordination-objective-topic.d.ts +6 -0
  55. package/dist/coordination-objective-topic.d.ts.map +1 -0
  56. package/dist/coordination-objective-topic.js +561 -0
  57. package/dist/coordination-objective-topic.js.map +1 -0
  58. package/dist/coordination-objective-work-contracts.d.ts +212 -0
  59. package/dist/coordination-objective-work-contracts.d.ts.map +1 -0
  60. package/dist/coordination-objective-work-contracts.js +2 -0
  61. package/dist/coordination-objective-work-contracts.js.map +1 -0
  62. package/dist/coordination-objective-work-state.d.ts +10 -0
  63. package/dist/coordination-objective-work-state.d.ts.map +1 -0
  64. package/dist/coordination-objective-work-state.js +1075 -0
  65. package/dist/coordination-objective-work-state.js.map +1 -0
  66. package/dist/coordination-objective-work-time.d.ts +9 -0
  67. package/dist/coordination-objective-work-time.d.ts.map +1 -0
  68. package/dist/coordination-objective-work-time.js +48 -0
  69. package/dist/coordination-objective-work-time.js.map +1 -0
  70. package/dist/coordination-objective-work.d.ts +11 -0
  71. package/dist/coordination-objective-work.d.ts.map +1 -0
  72. package/dist/coordination-objective-work.js +1090 -0
  73. package/dist/coordination-objective-work.js.map +1 -0
  74. package/dist/coordination-recovery.d.ts +13 -0
  75. package/dist/coordination-recovery.d.ts.map +1 -0
  76. package/dist/coordination-recovery.js +951 -0
  77. package/dist/coordination-recovery.js.map +1 -0
  78. package/dist/coordination-reducer.d.ts +8 -0
  79. package/dist/coordination-reducer.d.ts.map +1 -0
  80. package/dist/coordination-reducer.js +81 -0
  81. package/dist/coordination-reducer.js.map +1 -0
  82. package/dist/coordination-state.d.ts +13 -0
  83. package/dist/coordination-state.d.ts.map +1 -0
  84. package/dist/coordination-state.js +335 -0
  85. package/dist/coordination-state.js.map +1 -0
  86. package/dist/coordination-topic-contracts.d.ts +82 -0
  87. package/dist/coordination-topic-contracts.d.ts.map +1 -0
  88. package/dist/coordination-topic-contracts.js +2 -0
  89. package/dist/coordination-topic-contracts.js.map +1 -0
  90. package/dist/coordination-topic.d.ts +6 -0
  91. package/dist/coordination-topic.d.ts.map +1 -0
  92. package/dist/coordination-topic.js +561 -0
  93. package/dist/coordination-topic.js.map +1 -0
  94. package/dist/coordination.d.ts +21 -0
  95. package/dist/coordination.d.ts.map +1 -0
  96. package/dist/coordination.js +21 -0
  97. package/dist/coordination.js.map +1 -0
  98. package/dist/sha256.d.ts +3 -0
  99. package/dist/sha256.d.ts.map +1 -0
  100. package/dist/sha256.js +117 -0
  101. package/dist/sha256.js.map +1 -0
  102. package/package.json +7 -3
@@ -0,0 +1,944 @@
1
+ import { verifyMeshEnvelope } from '@agentplat/mesh-crypto';
2
+ import { canonicalizeMeshJson, compareMeshTimestamps, DEFAULT_MESH_PROTOCOL_LIMITS, validateMeshEnvelopeContext, } from '@agentplat/mesh-protocol';
3
+ import { assertFrozenMeshCoordinationInboundState, createMeshAllocationInboundRuntimeState, createMeshDiscoveryInboundRuntimeState, createMeshObjectiveInboundRuntimeState, synchronizeMeshObjectiveLogicalTime, } from './coordination-inbound-state.js';
4
+ import { evaluateVerifiedMeshDiscoveryEnvelope } from './coordination-discovery.js';
5
+ import { createMeshDiscoveryRuntimeState } from './coordination-discovery-state.js';
6
+ import { createMeshObjectiveWorkRuntimeState, evaluateVerifiedMeshObjectiveEnvelope, } from './coordination-objective-work.js';
7
+ import { evaluateVerifiedMeshAllocationEnvelope } from './coordination-allocation.js';
8
+ import { createMeshAllocationRuntimeState } from './coordination-allocation-state.js';
9
+ import { assertMeshLogicalTime, createFrozenRecord, recordEntries, } from './state.js';
10
+ const cryptoRejectionCodes = new Set([
11
+ 'crypto_unavailable',
12
+ 'crypto_operation_failed',
13
+ 'invalid_envelope',
14
+ 'invalid_verification_time',
15
+ 'unsupported_algorithm',
16
+ 'payload_hash_mismatch',
17
+ 'key_not_found',
18
+ 'key_resolution_failed',
19
+ 'key_binding_mismatch',
20
+ 'invalid_key_record',
21
+ 'invalid_key_material',
22
+ 'key_not_yet_valid',
23
+ 'key_expired',
24
+ 'key_revoked',
25
+ 'signature_invalid',
26
+ ]);
27
+ const trustedObjectiveDecisionBindings = new WeakMap();
28
+ /**
29
+ * Binds local trust dependencies once, outside the remote-message path.
30
+ */
31
+ export function createMeshDiscoveryInboundProcessor(options) {
32
+ assertProcessorOptions(options);
33
+ const resolve = options.resolver.resolve.bind(options.resolver);
34
+ const crypto = snapshotCrypto(options.crypto);
35
+ const configuration = Object.freeze({
36
+ resolver: Object.freeze({ resolve }),
37
+ cryptoPolicy: Object.freeze({
38
+ allowedAlgorithms: Object.freeze([
39
+ ...options.cryptoPolicy.allowedAlgorithms,
40
+ ]),
41
+ }),
42
+ crypto,
43
+ ...(options.protocolOptions === undefined
44
+ ? {}
45
+ : {
46
+ protocolOptions: Object.freeze({
47
+ ...(options.protocolOptions.limits === undefined
48
+ ? {}
49
+ : {
50
+ limits: Object.freeze({
51
+ ...options.protocolOptions.limits,
52
+ }),
53
+ }),
54
+ }),
55
+ }),
56
+ ...(options.supportedCriticalExtensions === undefined
57
+ ? {}
58
+ : {
59
+ supportedCriticalExtensions: Object.freeze([
60
+ ...options.supportedCriticalExtensions,
61
+ ]),
62
+ }),
63
+ });
64
+ return Object.freeze({
65
+ process: (state, request) => processMeshDiscoveryEnvelope(state, request, configuration),
66
+ });
67
+ }
68
+ /** Binds local trust dependencies once, outside the Objective message path. */
69
+ export function createMeshObjectiveInboundProcessor(options) {
70
+ assertProcessorOptions(options);
71
+ const resolve = options.resolver.resolve.bind(options.resolver);
72
+ const crypto = snapshotCrypto(options.crypto);
73
+ const configuration = Object.freeze({
74
+ resolver: Object.freeze({ resolve }),
75
+ cryptoPolicy: Object.freeze({
76
+ allowedAlgorithms: Object.freeze([
77
+ ...options.cryptoPolicy.allowedAlgorithms,
78
+ ]),
79
+ }),
80
+ crypto,
81
+ ...(options.protocolOptions === undefined
82
+ ? {}
83
+ : {
84
+ protocolOptions: Object.freeze({
85
+ ...(options.protocolOptions.limits === undefined
86
+ ? {}
87
+ : {
88
+ limits: Object.freeze({
89
+ ...options.protocolOptions.limits,
90
+ }),
91
+ }),
92
+ }),
93
+ }),
94
+ ...(options.supportedCriticalExtensions === undefined
95
+ ? {}
96
+ : {
97
+ supportedCriticalExtensions: Object.freeze([
98
+ ...options.supportedCriticalExtensions,
99
+ ]),
100
+ }),
101
+ });
102
+ return Object.freeze({
103
+ process: async (state, request) => {
104
+ const decision = await processMeshObjectiveEnvelope(state, request, configuration);
105
+ trustedObjectiveDecisionBindings.set(decision, Object.freeze({ state, request }));
106
+ return decision;
107
+ },
108
+ });
109
+ }
110
+ /** Binds local trust dependencies once, outside the allocation message path. */
111
+ export function createMeshAllocationInboundProcessor(options) {
112
+ assertProcessorOptions(options);
113
+ const resolve = options.resolver.resolve.bind(options.resolver);
114
+ const crypto = snapshotCrypto(options.crypto);
115
+ const configuration = Object.freeze({
116
+ resolver: Object.freeze({ resolve }),
117
+ cryptoPolicy: Object.freeze({
118
+ allowedAlgorithms: Object.freeze([
119
+ ...options.cryptoPolicy.allowedAlgorithms,
120
+ ]),
121
+ }),
122
+ crypto,
123
+ ...(options.protocolOptions === undefined
124
+ ? {}
125
+ : {
126
+ protocolOptions: Object.freeze({
127
+ ...(options.protocolOptions.limits === undefined
128
+ ? {}
129
+ : {
130
+ limits: Object.freeze({
131
+ ...options.protocolOptions.limits,
132
+ }),
133
+ }),
134
+ }),
135
+ }),
136
+ ...(options.supportedCriticalExtensions === undefined
137
+ ? {}
138
+ : {
139
+ supportedCriticalExtensions: Object.freeze([
140
+ ...options.supportedCriticalExtensions,
141
+ ]),
142
+ }),
143
+ });
144
+ return Object.freeze({
145
+ process: (state, request) => processMeshAllocationEnvelope(state, request, configuration),
146
+ });
147
+ }
148
+ /**
149
+ * Package-internal attestation used by the reference topic driver. It prevents
150
+ * a processor wrapper from substituting a decision produced for different
151
+ * state or input while keeping the public decision contract serializable.
152
+ */
153
+ export function isTrustedMeshObjectiveInboundDecision(decision, state, request) {
154
+ if (!decision || typeof decision !== 'object')
155
+ return false;
156
+ const binding = trustedObjectiveDecisionBindings.get(decision);
157
+ return binding?.state === state && binding.request === request;
158
+ }
159
+ /**
160
+ * Authenticates one signed discovery envelope before admission, replay and
161
+ * projection. Rejections after replay admission retain only security state.
162
+ */
163
+ async function processMeshDiscoveryEnvelope(state, request, configuration) {
164
+ assertRuntimeState(state);
165
+ assertRequest(request);
166
+ const receivedAt = request.receivedAt;
167
+ const verifiedAt = request.verifiedAt;
168
+ const resolver = configuration.resolver;
169
+ const crypto = configuration.crypto;
170
+ const cryptoPolicy = configuration.cryptoPolicy;
171
+ const protocolOptions = configuration.protocolOptions;
172
+ const supportedCriticalExtensions = configuration.supportedCriticalExtensions;
173
+ assertMeshLogicalTime(receivedAt);
174
+ if (receivedAt <
175
+ Math.max(state.coordination.lastLogicalTime, state.discovery.lastLogicalTime, state.inbound.lastLogicalTime)) {
176
+ return rejection(state, 'logical_time_regressed');
177
+ }
178
+ const context = validateMeshEnvelopeContext(request.envelope, {
179
+ tenantId: state.discovery.identity.tenantId,
180
+ meshId: state.discovery.identity.meshId,
181
+ peerId: state.discovery.identity.peerId,
182
+ receivedAt: verifiedAt,
183
+ subscribedTopics: state.discovery.subscriptions,
184
+ ...(supportedCriticalExtensions === undefined
185
+ ? {}
186
+ : { supportedCriticalExtensions }),
187
+ }, protocolOptions);
188
+ if (!context.ok) {
189
+ return rejection(state, contextRejection(context.issues[0]?.code, request.envelope, state.discovery.subscriptions));
190
+ }
191
+ const contextualEnvelope = context.value;
192
+ const familyFailure = validateDiscoveryFamily(contextualEnvelope);
193
+ if (familyFailure)
194
+ return rejection(state, familyFailure);
195
+ let verification;
196
+ try {
197
+ verification = await verifyMeshEnvelope({
198
+ envelope: contextualEnvelope,
199
+ resolver,
200
+ policy: cryptoPolicy,
201
+ verifiedAt,
202
+ crypto,
203
+ protocolOptions,
204
+ });
205
+ }
206
+ catch {
207
+ return rejection(state, 'crypto_operation_failed');
208
+ }
209
+ let verifiedEnvelope;
210
+ try {
211
+ if (!verification ||
212
+ typeof verification !== 'object' ||
213
+ verification.verified !== true) {
214
+ const code = verification?.verified === false &&
215
+ cryptoRejectionCodes.has(verification.code)
216
+ ? verification.code
217
+ : 'crypto_operation_failed';
218
+ return rejection(state, code);
219
+ }
220
+ const rebound = validateMeshEnvelopeContext(verification.envelope, {
221
+ tenantId: state.discovery.identity.tenantId,
222
+ meshId: state.discovery.identity.meshId,
223
+ peerId: state.discovery.identity.peerId,
224
+ receivedAt: verifiedAt,
225
+ subscribedTopics: state.discovery.subscriptions,
226
+ ...(supportedCriticalExtensions === undefined
227
+ ? {}
228
+ : { supportedCriticalExtensions }),
229
+ }, protocolOptions);
230
+ if (!rebound.ok ||
231
+ !sameCanonicalEnvelope(contextualEnvelope, rebound.value, protocolOptions)) {
232
+ return rejection(state, 'crypto_operation_failed');
233
+ }
234
+ verifiedEnvelope =
235
+ rebound.value;
236
+ }
237
+ catch {
238
+ return rejection(state, 'crypto_operation_failed');
239
+ }
240
+ const authorityFailure = validateAdmissionAndOwnership(state, verifiedEnvelope, verifiedAt);
241
+ if (authorityFailure)
242
+ return rejection(state, authorityFailure);
243
+ const replay = advanceReplayState(state.inbound, verifiedEnvelope, receivedAt);
244
+ if ('code' in replay)
245
+ return rejection(state, replay.code);
246
+ const replayRuntime = createMeshDiscoveryInboundRuntimeState(state.coordination, state.discovery, replay.inbound);
247
+ if (isAuthenticatedDomainDuplicate(state, verifiedEnvelope)) {
248
+ return acceptance(replayRuntime, verifiedEnvelope, true);
249
+ }
250
+ const projection = evaluateVerifiedMeshDiscoveryEnvelope(createMeshDiscoveryRuntimeState(state.coordination, state.discovery), {
251
+ envelope: verifiedEnvelope,
252
+ verifiedAt,
253
+ receivedAt,
254
+ ...(supportedCriticalExtensions === undefined
255
+ ? {}
256
+ : { supportedCriticalExtensions }),
257
+ });
258
+ if (!projection.accepted) {
259
+ return rejection(replayRuntime, projection.code);
260
+ }
261
+ return acceptance(createMeshDiscoveryInboundRuntimeState(projection.state.coordination, projection.state.discovery, replay.inbound), verifiedEnvelope, projection.duplicate);
262
+ }
263
+ /**
264
+ * Authenticates one signed Objective envelope before admission, replay and
265
+ * projection. Rejections after replay admission retain only security state.
266
+ */
267
+ async function processMeshObjectiveEnvelope(state, request, configuration) {
268
+ assertObjectiveRuntimeState(state);
269
+ assertObjectiveRequest(request);
270
+ const receivedAt = request.receivedAt;
271
+ const verifiedAt = request.verifiedAt;
272
+ assertMeshLogicalTime(receivedAt);
273
+ if (receivedAt <
274
+ Math.max(state.coordination.lastLogicalTime, state.discovery.lastLogicalTime, state.objectives.lastLogicalTime, state.inbound.lastLogicalTime)) {
275
+ return objectiveRejection(state, 'logical_time_regressed');
276
+ }
277
+ const context = validateMeshEnvelopeContext(request.envelope, {
278
+ tenantId: state.discovery.identity.tenantId,
279
+ meshId: state.discovery.identity.meshId,
280
+ peerId: state.discovery.identity.peerId,
281
+ receivedAt: verifiedAt,
282
+ subscribedTopics: state.discovery.subscriptions,
283
+ ...(configuration.supportedCriticalExtensions === undefined
284
+ ? {}
285
+ : {
286
+ supportedCriticalExtensions: configuration.supportedCriticalExtensions,
287
+ }),
288
+ }, configuration.protocolOptions);
289
+ if (!context.ok) {
290
+ return objectiveRejection(state, objectiveContextRejection(context.issues[0]?.code, request.envelope, state.discovery.subscriptions));
291
+ }
292
+ const contextualEnvelope = context.value;
293
+ const familyFailure = validateObjectiveFamily(contextualEnvelope);
294
+ if (familyFailure)
295
+ return objectiveRejection(state, familyFailure);
296
+ let verification;
297
+ try {
298
+ verification = await verifyMeshEnvelope({
299
+ envelope: contextualEnvelope,
300
+ resolver: configuration.resolver,
301
+ policy: configuration.cryptoPolicy,
302
+ verifiedAt,
303
+ crypto: configuration.crypto,
304
+ protocolOptions: configuration.protocolOptions,
305
+ });
306
+ }
307
+ catch {
308
+ return objectiveRejection(state, 'crypto_operation_failed');
309
+ }
310
+ let verifiedEnvelope;
311
+ try {
312
+ if (!verification ||
313
+ typeof verification !== 'object' ||
314
+ verification.verified !== true) {
315
+ const code = verification?.verified === false &&
316
+ cryptoRejectionCodes.has(verification.code)
317
+ ? verification.code
318
+ : 'crypto_operation_failed';
319
+ return objectiveRejection(state, code);
320
+ }
321
+ const rebound = validateMeshEnvelopeContext(verification.envelope, {
322
+ tenantId: state.discovery.identity.tenantId,
323
+ meshId: state.discovery.identity.meshId,
324
+ peerId: state.discovery.identity.peerId,
325
+ receivedAt: verifiedAt,
326
+ subscribedTopics: state.discovery.subscriptions,
327
+ ...(configuration.supportedCriticalExtensions === undefined
328
+ ? {}
329
+ : {
330
+ supportedCriticalExtensions: configuration.supportedCriticalExtensions,
331
+ }),
332
+ }, configuration.protocolOptions);
333
+ if (!rebound.ok ||
334
+ !sameCanonicalEnvelope(contextualEnvelope, rebound.value, configuration.protocolOptions)) {
335
+ return objectiveRejection(state, 'crypto_operation_failed');
336
+ }
337
+ verifiedEnvelope =
338
+ rebound.value;
339
+ }
340
+ catch {
341
+ return objectiveRejection(state, 'crypto_operation_failed');
342
+ }
343
+ const admissionFailure = validateObjectiveAdmission(state, verifiedEnvelope, verifiedAt);
344
+ if (admissionFailure)
345
+ return objectiveRejection(state, admissionFailure);
346
+ const authorityFailure = validateObjectiveIssuerAuthority(state, verifiedEnvelope, verifiedAt);
347
+ if (authorityFailure)
348
+ return objectiveRejection(state, authorityFailure);
349
+ const replay = advanceReplayState(state.inbound, verifiedEnvelope, receivedAt);
350
+ if ('code' in replay)
351
+ return objectiveRejection(state, replay.code);
352
+ const replayRuntime = createMeshObjectiveInboundRuntimeState(state.coordination, state.discovery, state.objectives, replay.inbound);
353
+ const projection = evaluateVerifiedMeshObjectiveEnvelope(createMeshObjectiveWorkRuntimeState(state.coordination, state.discovery, synchronizeMeshObjectiveLogicalTime(state.objectives, state.coordination.lastLogicalTime)), {
354
+ envelope: verifiedEnvelope,
355
+ verifiedAt,
356
+ receivedAt,
357
+ ...(configuration.supportedCriticalExtensions === undefined
358
+ ? {}
359
+ : {
360
+ supportedCriticalExtensions: configuration.supportedCriticalExtensions,
361
+ }),
362
+ });
363
+ if (!projection.accepted)
364
+ return objectiveRejection(replayRuntime, projection.code);
365
+ return objectiveAcceptance(createMeshObjectiveInboundRuntimeState(projection.state.coordination, projection.state.discovery, projection.state.objectives, replay.inbound), verifiedEnvelope, projection.duplicate);
366
+ }
367
+ /**
368
+ * Authenticates one signed allocation envelope before admission, replay and
369
+ * the authoritative allocation reducer. Rejections after replay retain only
370
+ * inbound security accounting.
371
+ */
372
+ async function processMeshAllocationEnvelope(state, request, configuration) {
373
+ assertAllocationRuntimeState(state);
374
+ assertAllocationRequest(request);
375
+ const receivedAt = request.receivedAt;
376
+ const verifiedAt = request.verifiedAt;
377
+ assertMeshLogicalTime(receivedAt);
378
+ if (receivedAt <
379
+ Math.max(state.coordination.lastLogicalTime, state.discovery.lastLogicalTime, state.objectives.lastLogicalTime, state.allocation.lastLogicalTime, state.inbound.lastLogicalTime)) {
380
+ return allocationRejection(state, 'logical_time_regressed');
381
+ }
382
+ const context = validateMeshEnvelopeContext(request.envelope, {
383
+ tenantId: state.discovery.identity.tenantId,
384
+ meshId: state.discovery.identity.meshId,
385
+ peerId: state.discovery.identity.peerId,
386
+ receivedAt: verifiedAt,
387
+ subscribedTopics: state.discovery.subscriptions,
388
+ ...(configuration.supportedCriticalExtensions === undefined
389
+ ? {}
390
+ : {
391
+ supportedCriticalExtensions: configuration.supportedCriticalExtensions,
392
+ }),
393
+ }, configuration.protocolOptions);
394
+ if (!context.ok) {
395
+ return allocationRejection(state, allocationContextRejection(context.issues[0]?.code, request.envelope, state.discovery.subscriptions));
396
+ }
397
+ const contextualEnvelope = context.value;
398
+ const familyFailure = validateAllocationFamily(contextualEnvelope);
399
+ if (familyFailure)
400
+ return allocationRejection(state, familyFailure);
401
+ let verification;
402
+ try {
403
+ verification = await verifyMeshEnvelope({
404
+ envelope: contextualEnvelope,
405
+ resolver: configuration.resolver,
406
+ policy: configuration.cryptoPolicy,
407
+ verifiedAt,
408
+ crypto: configuration.crypto,
409
+ protocolOptions: configuration.protocolOptions,
410
+ });
411
+ }
412
+ catch {
413
+ return allocationRejection(state, 'crypto_operation_failed');
414
+ }
415
+ let verifiedEnvelope;
416
+ try {
417
+ if (!verification ||
418
+ typeof verification !== 'object' ||
419
+ verification.verified !== true) {
420
+ const code = verification?.verified === false &&
421
+ cryptoRejectionCodes.has(verification.code)
422
+ ? verification.code
423
+ : 'crypto_operation_failed';
424
+ return allocationRejection(state, code);
425
+ }
426
+ const rebound = validateMeshEnvelopeContext(verification.envelope, {
427
+ tenantId: state.discovery.identity.tenantId,
428
+ meshId: state.discovery.identity.meshId,
429
+ peerId: state.discovery.identity.peerId,
430
+ receivedAt: verifiedAt,
431
+ subscribedTopics: state.discovery.subscriptions,
432
+ ...(configuration.supportedCriticalExtensions === undefined
433
+ ? {}
434
+ : {
435
+ supportedCriticalExtensions: configuration.supportedCriticalExtensions,
436
+ }),
437
+ }, configuration.protocolOptions);
438
+ if (!rebound.ok ||
439
+ !sameCanonicalEnvelope(contextualEnvelope, rebound.value, configuration.protocolOptions)) {
440
+ return allocationRejection(state, 'crypto_operation_failed');
441
+ }
442
+ verifiedEnvelope =
443
+ rebound.value;
444
+ }
445
+ catch {
446
+ return allocationRejection(state, 'crypto_operation_failed');
447
+ }
448
+ const admissionFailure = validateAllocationAdmission(state, verifiedEnvelope, verifiedAt);
449
+ if (admissionFailure)
450
+ return allocationRejection(state, admissionFailure);
451
+ const replay = advanceReplayState(state.inbound, verifiedEnvelope, receivedAt);
452
+ if ('code' in replay)
453
+ return allocationRejection(state, replay.code);
454
+ const replayRuntime = createMeshAllocationInboundRuntimeState(state.coordination, state.discovery, state.objectives, state.allocation, replay.inbound);
455
+ const projection = evaluateVerifiedMeshAllocationEnvelope(createMeshAllocationRuntimeState(state.coordination, state.discovery, state.objectives, state.allocation), {
456
+ envelope: verifiedEnvelope,
457
+ verifiedAt,
458
+ receivedAt,
459
+ ...(configuration.supportedCriticalExtensions === undefined
460
+ ? {}
461
+ : {
462
+ supportedCriticalExtensions: configuration.supportedCriticalExtensions,
463
+ }),
464
+ });
465
+ if (!projection.accepted)
466
+ return allocationRejection(replayRuntime, projection.code);
467
+ return allocationAcceptance(createMeshAllocationInboundRuntimeState(projection.state.coordination, projection.state.discovery, projection.state.objectives, projection.state.allocation, replay.inbound), verifiedEnvelope, projection.duplicate);
468
+ }
469
+ function validateObjectiveFamily(envelope) {
470
+ const payload = envelope.payload;
471
+ if (payload.type !== 'objective.announce' &&
472
+ payload.type !== 'objective.revise' &&
473
+ payload.type !== 'objective.cancel') {
474
+ return 'unsupported_message_type';
475
+ }
476
+ if (envelope.audience.kind === 'mesh' &&
477
+ envelope.audience.topic !== 'objective') {
478
+ return 'audience_mismatch';
479
+ }
480
+ return payload.type !== 'objective.cancel' &&
481
+ envelope.sender.peerId !== payload.issuerPeerId
482
+ ? 'issuer_not_authorized'
483
+ : undefined;
484
+ }
485
+ function validateAllocationFamily(envelope) {
486
+ const type = envelope.payload.type;
487
+ if (type !== 'work.offer' &&
488
+ type !== 'work.bid' &&
489
+ type !== 'work.award' &&
490
+ type !== 'work.accept' &&
491
+ type !== 'work.decline' &&
492
+ type !== 'work.progress' &&
493
+ type !== 'work.checkpoint' &&
494
+ type !== 'work.result' &&
495
+ type !== 'work.release' &&
496
+ type !== 'work.cancel' &&
497
+ type !== 'lease.renew' &&
498
+ type !== 'lease.takeover_proposal' &&
499
+ type !== 'lease.vote' &&
500
+ type !== 'lease.certificate') {
501
+ return 'unsupported_message_type';
502
+ }
503
+ return undefined;
504
+ }
505
+ function validateObjectiveAdmission(state, envelope, verifiedAt) {
506
+ const admission = state.discovery.admittedPeers[envelope.sender.peerId];
507
+ if (!admission)
508
+ return 'sender_not_admitted';
509
+ if (!admission.instanceIds.includes(envelope.sender.instanceId)) {
510
+ return 'sender_instance_not_admitted';
511
+ }
512
+ const expiry = compareMeshTimestamps(verifiedAt, admission.validUntil);
513
+ return !expiry.ok || expiry.value >= 0
514
+ ? 'sender_admission_expired'
515
+ : undefined;
516
+ }
517
+ function validateAllocationAdmission(state, envelope, verifiedAt) {
518
+ const admission = state.discovery.admittedPeers[envelope.sender.peerId];
519
+ if (!admission)
520
+ return 'sender_not_admitted';
521
+ if (!admission.instanceIds.includes(envelope.sender.instanceId)) {
522
+ return 'sender_instance_not_admitted';
523
+ }
524
+ const expiry = compareMeshTimestamps(verifiedAt, admission.validUntil);
525
+ return !expiry.ok || expiry.value >= 0
526
+ ? 'sender_admission_expired'
527
+ : undefined;
528
+ }
529
+ function validateObjectiveIssuerAuthority(state, envelope, verifiedAt) {
530
+ const authority = state.objectives.issuerAuthorities[envelope.sender.peerId];
531
+ if (!authority)
532
+ return 'issuer_not_authorized';
533
+ if (!authority.keyIds.includes(envelope.proof.keyId)) {
534
+ return 'issuer_key_not_authorized';
535
+ }
536
+ const expiry = compareMeshTimestamps(verifiedAt, authority.validUntil);
537
+ return !expiry.ok || expiry.value >= 0
538
+ ? 'issuer_authority_expired'
539
+ : undefined;
540
+ }
541
+ function validateDiscoveryFamily(envelope) {
542
+ const type = envelope.payload.type;
543
+ if (type !== 'peer.card' &&
544
+ type !== 'peer.goodbye' &&
545
+ type !== 'capability.advertise' &&
546
+ type !== 'capability.withdraw') {
547
+ return 'unsupported_message_type';
548
+ }
549
+ if (envelope.audience.kind !== 'mesh')
550
+ return undefined;
551
+ const expectedTopic = type === 'peer.card' || type === 'peer.goodbye'
552
+ ? 'membership'
553
+ : 'capability';
554
+ return envelope.audience.topic === expectedTopic
555
+ ? undefined
556
+ : 'audience_mismatch';
557
+ }
558
+ function validateAdmissionAndOwnership(state, envelope, verifiedAt) {
559
+ const admission = state.discovery.admittedPeers[envelope.sender.peerId];
560
+ if (!admission)
561
+ return 'sender_not_admitted';
562
+ if (!admission.instanceIds.includes(envelope.sender.instanceId)) {
563
+ return 'sender_instance_not_admitted';
564
+ }
565
+ const admissionExpiry = compareMeshTimestamps(verifiedAt, admission.validUntil);
566
+ if (!admissionExpiry.ok || admissionExpiry.value >= 0) {
567
+ return 'sender_admission_expired';
568
+ }
569
+ const payload = envelope.payload;
570
+ switch (payload.type) {
571
+ case 'peer.card':
572
+ return payload.subjectPeerId === envelope.sender.peerId &&
573
+ payload.instanceId === envelope.sender.instanceId
574
+ ? undefined
575
+ : 'message_not_authorized';
576
+ case 'peer.goodbye':
577
+ return payload.instanceId === envelope.sender.instanceId
578
+ ? undefined
579
+ : 'message_not_authorized';
580
+ case 'capability.advertise': {
581
+ if (payload.ownerPeerId !== envelope.sender.peerId) {
582
+ return 'message_not_authorized';
583
+ }
584
+ const card = state.discovery.peerCards[payload.ownerPeerId];
585
+ return card && card.instanceId !== envelope.sender.instanceId
586
+ ? 'message_not_authorized'
587
+ : undefined;
588
+ }
589
+ case 'capability.withdraw': {
590
+ const capability = state.discovery.capabilities[JSON.stringify([envelope.sender.peerId, payload.capabilityId])];
591
+ return capability && capability.instanceId !== envelope.sender.instanceId
592
+ ? 'message_not_authorized'
593
+ : undefined;
594
+ }
595
+ }
596
+ }
597
+ function advanceReplayState(inbound, envelope, receivedAt) {
598
+ const retainedIds = recordEntries(inbound.messageIds).filter(([, expiresAt]) => expiresAt > receivedAt);
599
+ if (retainedIds.some(([messageId]) => messageId === envelope.messageId)) {
600
+ return { code: 'message_replayed' };
601
+ }
602
+ if (retainedIds.length >= inbound.limits.maximumTrackedMessageIds ||
603
+ receivedAt > Number.MAX_SAFE_INTEGER - inbound.limits.messageIdRetentionMs) {
604
+ return { code: 'replay_capacity_exceeded' };
605
+ }
606
+ const replayKey = JSON.stringify([
607
+ envelope.sender.peerId,
608
+ envelope.sender.instanceId,
609
+ ]);
610
+ const current = inbound.replay[replayKey];
611
+ if (!current &&
612
+ Object.keys(inbound.replay).length >= inbound.limits.maximumReplayWindows) {
613
+ return { code: 'replay_capacity_exceeded' };
614
+ }
615
+ let nextWindow;
616
+ if (!current) {
617
+ nextWindow = Object.freeze({
618
+ highestSequence: envelope.sequence,
619
+ seenOffsets: Object.freeze([0]),
620
+ });
621
+ }
622
+ else if (envelope.sequence > current.highestSequence) {
623
+ const advance = envelope.sequence - current.highestSequence;
624
+ nextWindow = Object.freeze({
625
+ highestSequence: envelope.sequence,
626
+ seenOffsets: Object.freeze(advance >= inbound.limits.replayWindowSize
627
+ ? [0]
628
+ : [
629
+ 0,
630
+ ...current.seenOffsets
631
+ .map((offset) => offset + advance)
632
+ .filter((offset) => offset < inbound.limits.replayWindowSize),
633
+ ]),
634
+ });
635
+ }
636
+ else {
637
+ const offset = current.highestSequence - envelope.sequence;
638
+ if (offset >= inbound.limits.replayWindowSize) {
639
+ return { code: 'sequence_outside_window' };
640
+ }
641
+ if (current.seenOffsets.includes(offset)) {
642
+ return { code: 'message_replayed' };
643
+ }
644
+ nextWindow = Object.freeze({
645
+ highestSequence: current.highestSequence,
646
+ seenOffsets: Object.freeze([...current.seenOffsets, offset].sort((left, right) => left - right)),
647
+ });
648
+ }
649
+ return {
650
+ inbound: Object.freeze({
651
+ ...inbound,
652
+ replay: createFrozenRecord([
653
+ ...recordEntries(inbound.replay).filter(([key]) => key !== replayKey),
654
+ [replayKey, nextWindow],
655
+ ]),
656
+ messageIds: createFrozenRecord([
657
+ ...retainedIds,
658
+ [envelope.messageId, receivedAt + inbound.limits.messageIdRetentionMs],
659
+ ]),
660
+ lastLogicalTime: receivedAt,
661
+ }),
662
+ };
663
+ }
664
+ function isAuthenticatedDomainDuplicate(state, envelope) {
665
+ const recordId = envelope.payload.type === 'peer.card' ||
666
+ envelope.payload.type === 'peer.goodbye'
667
+ ? envelope.payload.peerCardId
668
+ : envelope.payload.advertisementId;
669
+ const record = state.coordination.domainRecords[JSON.stringify([envelope.payload.type, recordId])];
670
+ return (record !== undefined &&
671
+ record.contentDigest === envelope.payloadHash.slice('sha256:'.length) &&
672
+ isCurrentDuplicateHead(state, envelope));
673
+ }
674
+ function isCurrentDuplicateHead(state, envelope) {
675
+ const payload = envelope.payload;
676
+ switch (payload.type) {
677
+ case 'peer.card': {
678
+ const card = state.discovery.peerCards[payload.subjectPeerId];
679
+ return (card?.peerCardId === payload.peerCardId &&
680
+ card.cardRevision === payload.cardRevision &&
681
+ card.instanceId === envelope.sender.instanceId);
682
+ }
683
+ case 'peer.goodbye': {
684
+ const card = state.discovery.peerCards[envelope.sender.peerId];
685
+ return (card?.status === 'departed' &&
686
+ card.peerCardId === payload.peerCardId &&
687
+ card.cardRevision === payload.cardRevision &&
688
+ card.instanceId === envelope.sender.instanceId);
689
+ }
690
+ case 'capability.advertise': {
691
+ const capability = state.discovery.capabilities[JSON.stringify([payload.ownerPeerId, payload.capabilityId])];
692
+ return (capability?.advertisementId === payload.advertisementId &&
693
+ capability.capabilityRevision === payload.capabilityRevision &&
694
+ capability.instanceId === envelope.sender.instanceId);
695
+ }
696
+ case 'capability.withdraw': {
697
+ const capability = state.discovery.capabilities[JSON.stringify([envelope.sender.peerId, payload.capabilityId])];
698
+ return (capability?.status === 'withdrawn' &&
699
+ capability.advertisementId === payload.advertisementId &&
700
+ capability.capabilityRevision === payload.capabilityRevision &&
701
+ capability.instanceId === envelope.sender.instanceId);
702
+ }
703
+ }
704
+ }
705
+ function sameCanonicalEnvelope(requested, verified, protocolOptions) {
706
+ const requestedCanonical = canonicalizeMeshJson(requested, protocolOptions);
707
+ const verifiedCanonical = canonicalizeMeshJson(verified, protocolOptions);
708
+ return (requestedCanonical.ok &&
709
+ verifiedCanonical.ok &&
710
+ requestedCanonical.value === verifiedCanonical.value);
711
+ }
712
+ function contextRejection(code, envelope, subscriptions) {
713
+ switch (code) {
714
+ case 'scope_mismatch':
715
+ return 'scope_mismatch';
716
+ case 'invalid_audience':
717
+ return envelope.audience.kind === 'mesh' &&
718
+ !subscriptions.includes(envelope.audience.topic)
719
+ ? 'topic_not_subscribed'
720
+ : 'audience_mismatch';
721
+ case 'message_expired':
722
+ case 'message_from_future':
723
+ case 'unknown_critical_extension':
724
+ return code;
725
+ default:
726
+ return 'invalid_envelope';
727
+ }
728
+ }
729
+ function objectiveContextRejection(code, envelope, subscriptions) {
730
+ switch (code) {
731
+ case 'scope_mismatch':
732
+ return 'scope_mismatch';
733
+ case 'invalid_audience':
734
+ return envelope.audience.kind === 'mesh' &&
735
+ !subscriptions.includes('objective')
736
+ ? 'topic_not_subscribed'
737
+ : 'audience_mismatch';
738
+ case 'message_expired':
739
+ case 'message_from_future':
740
+ case 'unknown_critical_extension':
741
+ return code;
742
+ default:
743
+ return 'invalid_envelope';
744
+ }
745
+ }
746
+ function allocationContextRejection(code, envelope, subscriptions) {
747
+ switch (code) {
748
+ case 'scope_mismatch':
749
+ return 'scope_mismatch';
750
+ case 'invalid_audience':
751
+ return envelope.audience.kind === 'mesh' &&
752
+ !subscriptions.includes(envelope.audience.topic)
753
+ ? 'topic_not_subscribed'
754
+ : 'audience_mismatch';
755
+ case 'message_expired':
756
+ case 'message_from_future':
757
+ case 'unknown_critical_extension':
758
+ return code;
759
+ default:
760
+ return 'invalid_verified_envelope';
761
+ }
762
+ }
763
+ function acceptance(state, envelope, duplicate) {
764
+ return Object.freeze({
765
+ accepted: true,
766
+ duplicate,
767
+ envelope,
768
+ state,
769
+ });
770
+ }
771
+ function rejection(state, code) {
772
+ return Object.freeze({ accepted: false, code, state });
773
+ }
774
+ function objectiveAcceptance(state, envelope, duplicate) {
775
+ return Object.freeze({ accepted: true, duplicate, envelope, state });
776
+ }
777
+ function allocationAcceptance(state, envelope, duplicate) {
778
+ return Object.freeze({ accepted: true, duplicate, envelope, state });
779
+ }
780
+ function objectiveRejection(state, code) {
781
+ return Object.freeze({ accepted: false, code, state });
782
+ }
783
+ function allocationRejection(state, code) {
784
+ return Object.freeze({ accepted: false, code, state });
785
+ }
786
+ function assertRuntimeState(state) {
787
+ if (!state ||
788
+ typeof state !== 'object' ||
789
+ Object.getPrototypeOf(state) !== Object.prototype ||
790
+ !hasExactDataKeys(state, ['coordination', 'discovery', 'inbound'], ['coordination', 'discovery', 'inbound']) ||
791
+ !Object.isFrozen(state)) {
792
+ throw new TypeError('Mesh discovery inbound runtime state must be immutable');
793
+ }
794
+ assertFrozenMeshCoordinationInboundState(state.inbound);
795
+ createMeshDiscoveryInboundRuntimeState(state.coordination, state.discovery, state.inbound);
796
+ }
797
+ function assertObjectiveRuntimeState(state) {
798
+ if (!state ||
799
+ typeof state !== 'object' ||
800
+ Object.getPrototypeOf(state) !== Object.prototype ||
801
+ !hasExactDataKeys(state, ['coordination', 'discovery', 'inbound', 'objectives'], ['coordination', 'discovery', 'inbound', 'objectives']) ||
802
+ !Object.isFrozen(state)) {
803
+ throw new TypeError('Mesh Objective inbound runtime state must be immutable');
804
+ }
805
+ assertFrozenMeshCoordinationInboundState(state.inbound);
806
+ createMeshObjectiveInboundRuntimeState(state.coordination, state.discovery, state.objectives, state.inbound);
807
+ }
808
+ function assertAllocationRuntimeState(state) {
809
+ if (!state ||
810
+ typeof state !== 'object' ||
811
+ Object.getPrototypeOf(state) !== Object.prototype ||
812
+ !hasExactDataKeys(state, ['allocation', 'coordination', 'discovery', 'inbound', 'objectives'], ['allocation', 'coordination', 'discovery', 'inbound', 'objectives']) ||
813
+ !Object.isFrozen(state)) {
814
+ throw new TypeError('Mesh allocation inbound runtime state must be immutable');
815
+ }
816
+ assertFrozenMeshCoordinationInboundState(state.inbound);
817
+ createMeshAllocationInboundRuntimeState(state.coordination, state.discovery, state.objectives, state.allocation, state.inbound);
818
+ }
819
+ function assertRequest(request) {
820
+ if (!request || typeof request !== 'object') {
821
+ throw new TypeError('Mesh discovery inbound request is required');
822
+ }
823
+ const prototype = Object.getPrototypeOf(request);
824
+ if ((prototype !== null && prototype !== Object.prototype) ||
825
+ !hasExactDataKeys(request, ['envelope', 'receivedAt', 'verifiedAt'], ['envelope', 'receivedAt', 'verifiedAt'])) {
826
+ throw new TypeError('Invalid Mesh discovery inbound request');
827
+ }
828
+ }
829
+ function assertObjectiveRequest(request) {
830
+ if (!request || typeof request !== 'object') {
831
+ throw new TypeError('Mesh Objective inbound request is required');
832
+ }
833
+ const prototype = Object.getPrototypeOf(request);
834
+ if ((prototype !== null && prototype !== Object.prototype) ||
835
+ !hasExactDataKeys(request, ['envelope', 'receivedAt', 'verifiedAt'], ['envelope', 'receivedAt', 'verifiedAt'])) {
836
+ throw new TypeError('Invalid Mesh Objective inbound request');
837
+ }
838
+ }
839
+ function assertAllocationRequest(request) {
840
+ if (!request || typeof request !== 'object') {
841
+ throw new TypeError('Mesh allocation inbound request is required');
842
+ }
843
+ const prototype = Object.getPrototypeOf(request);
844
+ if ((prototype !== null && prototype !== Object.prototype) ||
845
+ !hasExactDataKeys(request, ['envelope', 'receivedAt', 'verifiedAt'], ['envelope', 'receivedAt', 'verifiedAt'])) {
846
+ throw new TypeError('Invalid Mesh allocation inbound request');
847
+ }
848
+ }
849
+ function snapshotCrypto(injected) {
850
+ const candidate = injected ?? globalThis.crypto;
851
+ const subtle = candidate?.subtle;
852
+ if (!subtle ||
853
+ typeof subtle.digest !== 'function' ||
854
+ typeof subtle.verify !== 'function') {
855
+ throw new TypeError('Mesh discovery inbound processor requires Web Crypto');
856
+ }
857
+ const digest = subtle.digest.bind(subtle);
858
+ const verify = subtle.verify.bind(subtle);
859
+ return Object.freeze({
860
+ subtle: Object.freeze({ digest, verify }),
861
+ });
862
+ }
863
+ function assertProcessorOptions(options) {
864
+ if (!options || typeof options !== 'object') {
865
+ throw new TypeError('Mesh discovery inbound processor options are required');
866
+ }
867
+ const prototype = Object.getPrototypeOf(options);
868
+ if ((prototype !== null && prototype !== Object.prototype) ||
869
+ !hasExactDataKeys(options, [
870
+ 'crypto',
871
+ 'cryptoPolicy',
872
+ 'protocolOptions',
873
+ 'resolver',
874
+ 'supportedCriticalExtensions',
875
+ ], ['cryptoPolicy', 'resolver']) ||
876
+ !options.resolver ||
877
+ typeof options.resolver.resolve !== 'function' ||
878
+ !options.cryptoPolicy ||
879
+ typeof options.cryptoPolicy !== 'object' ||
880
+ Object.getPrototypeOf(options.cryptoPolicy) !== Object.prototype ||
881
+ !hasExactDataKeys(options.cryptoPolicy, ['allowedAlgorithms'], ['allowedAlgorithms']) ||
882
+ !isDenseDataArray(options.cryptoPolicy.allowedAlgorithms) ||
883
+ options.cryptoPolicy.allowedAlgorithms.length < 1 ||
884
+ options.cryptoPolicy.allowedAlgorithms.some((algorithm) => typeof algorithm !== 'string') ||
885
+ (options.supportedCriticalExtensions !== undefined &&
886
+ (!isDenseDataArray(options.supportedCriticalExtensions) ||
887
+ options.supportedCriticalExtensions.length >
888
+ DEFAULT_MESH_PROTOCOL_LIMITS.maximumCriticalExtensions ||
889
+ new Set(options.supportedCriticalExtensions).size !==
890
+ options.supportedCriticalExtensions.length ||
891
+ options.supportedCriticalExtensions.some((extension) => typeof extension !== 'string' || extension.length < 1))) ||
892
+ (options.protocolOptions !== undefined &&
893
+ (!isPlainDataRecord(options.protocolOptions) ||
894
+ !hasExactDataKeys(options.protocolOptions, ['limits'], []) ||
895
+ (options.protocolOptions.limits !== undefined &&
896
+ !isPlainDataRecord(options.protocolOptions.limits))))) {
897
+ throw new TypeError('Invalid Mesh discovery inbound processor options');
898
+ }
899
+ }
900
+ function isPlainDataRecord(value) {
901
+ if (!value || typeof value !== 'object' || Array.isArray(value))
902
+ return false;
903
+ const prototype = Object.getPrototypeOf(value);
904
+ return ((prototype === null || prototype === Object.prototype) &&
905
+ hasOnlyDataProperties(value));
906
+ }
907
+ function hasOnlyDataProperties(value) {
908
+ return (Object.getOwnPropertySymbols(value).length === 0 &&
909
+ Object.getOwnPropertyNames(value).every((key) => {
910
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
911
+ return (descriptor !== undefined &&
912
+ 'value' in descriptor &&
913
+ descriptor.enumerable === true);
914
+ }));
915
+ }
916
+ function hasExactDataKeys(value, supportedKeys, requiredKeys) {
917
+ const supported = new Set(supportedKeys);
918
+ return (hasOnlyDataProperties(value) &&
919
+ Object.getOwnPropertyNames(value).every((key) => supported.has(key)) &&
920
+ requiredKeys.every((key) => Object.hasOwn(value, key)));
921
+ }
922
+ function isDenseDataArray(value) {
923
+ if (!Array.isArray(value) ||
924
+ Object.getPrototypeOf(value) !== Array.prototype ||
925
+ Object.getOwnPropertySymbols(value).length > 0) {
926
+ return false;
927
+ }
928
+ const names = Object.getOwnPropertyNames(value);
929
+ if (names.length !== value.length + 1)
930
+ return false;
931
+ for (let index = 0; index < value.length; index += 1) {
932
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
933
+ if (descriptor === undefined ||
934
+ !('value' in descriptor) ||
935
+ descriptor.enumerable !== true) {
936
+ return false;
937
+ }
938
+ }
939
+ const lengthDescriptor = Object.getOwnPropertyDescriptor(value, 'length');
940
+ return (lengthDescriptor !== undefined &&
941
+ 'value' in lengthDescriptor &&
942
+ lengthDescriptor.enumerable === false);
943
+ }
944
+ //# sourceMappingURL=coordination-inbound.js.map