@agentplat/mesh-protocol 0.3.0-alpha.1 → 0.3.0-alpha.2

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.
@@ -6,6 +6,42 @@ const base64UrlPattern = /^[A-Za-z0-9_-]+$/;
6
6
  const rfc3339Pattern = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,9}))?(Z|([+-])(\d{2}):(\d{2}))$/;
7
7
  const base64UrlAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
8
8
  const maximumIssuePathLength = 256;
9
+ const maximumDomainStringBytes = 4_096;
10
+ const maximumProtocolVersions = 8;
11
+ const maximumTransportHints = 8;
12
+ const maximumTransportHintBytes = 2_048;
13
+ const maximumTransportHintsBytes = 8_192;
14
+ const maximumCapabilityIds = 32;
15
+ const maximumMediaTypes = 16;
16
+ const maximumMediaTypeBytes = 128;
17
+ const maximumAttributes = 32;
18
+ const maximumAttributeKeyBytes = 128;
19
+ const maximumAttributeValueBytes = 1_024;
20
+ const maximumAttributesBytes = 16_384;
21
+ const maximumVersionBytes = 128;
22
+ const maximumAdvertisementValidityMs = 24 * 60 * 60 * 1_000;
23
+ const maximumObjectiveValidityMs = 30 * 24 * 60 * 60 * 1_000;
24
+ const maximumObjectiveTextBytes = 4_096;
25
+ const maximumSuccessCriteria = 32;
26
+ const maximumSuccessCriteriaBytes = 16_384;
27
+ const maximumPermittedCapabilityKeys = 32;
28
+ const maximumRecoveryWitnesses = 32;
29
+ const minimumRecoveryWitnesses = 3;
30
+ const maximumAuthorizedObservers = 32;
31
+ const maximumObjectiveWorkItems = 1_000_000;
32
+ const maximumBidWindowMs = 60 * 60 * 1_000;
33
+ const maximumAcceptanceWindowMs = 15 * 60 * 1_000;
34
+ const maximumLeaseDurationMs = 24 * 60 * 60 * 1_000;
35
+ const maximumRecoveryGraceMs = 60 * 60 * 1_000;
36
+ const maximumLeaseRenewals = 100;
37
+ const maximumWorkCapabilityKeys = 32;
38
+ const maximumWorkTextBytes = 4_096;
39
+ const maximumWorkListItems = 32;
40
+ const maximumWorkListBytes = 16_384;
41
+ const maximumCapacityReservationUnits = 1_000_000;
42
+ const maximumWorkBidWindowMs = 60 * 60 * 1_000;
43
+ const maximumWorkDeadlineMs = 30 * 24 * 60 * 60 * 1_000;
44
+ const maximumWorkExecutionLifetimeMs = 5 * 60 * 1_000;
9
45
  const knownMessageTypes = new Set(MESH_MESSAGE_TYPES);
10
46
  const knownTopics = new Set(MESH_AUDIENCE_TOPICS);
11
47
  const utf8Encoder = new TextEncoder();
@@ -71,7 +107,7 @@ export function compareMeshTimestamps(left, right) {
71
107
  }
72
108
  }
73
109
  /**
74
- * Parses and statically validates one complete Alpha 1 envelope.
110
+ * Parses and statically validates one complete implemented Mesh envelope.
75
111
  * This stage does not verify the payload digest or proof.
76
112
  */
77
113
  export function parseSignedMeshEnvelope(input, options = {}) {
@@ -222,7 +258,7 @@ function validateEnvelope(input, limits) {
222
258
  if (!knownMessageTypes.has(type)) {
223
259
  fail('unsupported_message_type', '$["type"]');
224
260
  }
225
- if (!isAlphaOneMessageType(type)) {
261
+ if (!isImplementedMessageType(type)) {
226
262
  fail('unsupported_message_type', '$["type"]');
227
263
  }
228
264
  const sender = validateSender(envelope.sender, limits);
@@ -251,7 +287,7 @@ function validateEnvelope(input, limits) {
251
287
  if (payload.type !== type) {
252
288
  fail('type_payload_mismatch', '$["payload"]["type"]');
253
289
  }
254
- validateMessageSpecificEnvelope(type, audience, objectiveId, causationId);
290
+ validateMessageSpecificEnvelope(type, sender, audience, objectiveId, causationId, payload, sentAt, expiresAt);
255
291
  return {
256
292
  protocol: MESH_PROTOCOL,
257
293
  wireVersion: MESH_WIRE_VERSION,
@@ -310,6 +346,46 @@ function validatePayload(type, input, limits) {
310
346
  };
311
347
  return result;
312
348
  }
349
+ if (type === 'peer.card') {
350
+ const payload = assertClosedRecord(input, [
351
+ 'capabilityIds',
352
+ 'cardRevision',
353
+ 'instanceId',
354
+ 'peerCardId',
355
+ 'protocolVersions',
356
+ 'subjectPeerId',
357
+ 'transportHints',
358
+ 'type',
359
+ 'validFrom',
360
+ 'validUntil',
361
+ ], ['previousPeerCardId'], '$["payload"]', 'invalid_payload');
362
+ const peerCardId = assertIdentifier(payload.peerCardId, '$["payload"]["peerCardId"]', limits);
363
+ const cardRevision = assertPositiveSafeInteger(payload.cardRevision, '$["payload"]["cardRevision"]', 'invalid_payload');
364
+ const previousPeerCardId = payload.previousPeerCardId === undefined
365
+ ? undefined
366
+ : assertIdentifier(payload.previousPeerCardId, '$["payload"]["previousPeerCardId"]', limits);
367
+ validateRevisionPredecessor(cardRevision, previousPeerCardId, '$["payload"]["previousPeerCardId"]');
368
+ if (previousPeerCardId === peerCardId) {
369
+ fail('invalid_payload', '$["payload"]["previousPeerCardId"]');
370
+ }
371
+ const validFrom = assertRfc3339PayloadTimestamp(payload.validFrom, '$["payload"]["validFrom"]');
372
+ const validUntil = assertRfc3339PayloadTimestamp(payload.validUntil, '$["payload"]["validUntil"]');
373
+ assertBoundedValidity(validFrom.instant, validUntil.instant);
374
+ const result = {
375
+ type: assertPayloadType(payload.type, type),
376
+ peerCardId,
377
+ cardRevision,
378
+ subjectPeerId: assertIdentifier(payload.subjectPeerId, '$["payload"]["subjectPeerId"]', limits),
379
+ instanceId: assertIdentifier(payload.instanceId, '$["payload"]["instanceId"]', limits),
380
+ protocolVersions: validateProtocolVersions(payload.protocolVersions),
381
+ transportHints: validateBoundedStringArray(payload.transportHints, '$["payload"]["transportHints"]', maximumTransportHints, maximumTransportHintBytes, maximumTransportHintsBytes, true),
382
+ capabilityIds: validateIdentifierArray(payload.capabilityIds, '$["payload"]["capabilityIds"]', maximumCapabilityIds, limits),
383
+ validFrom: validFrom.text,
384
+ validUntil: validUntil.text,
385
+ ...(previousPeerCardId === undefined ? {} : { previousPeerCardId }),
386
+ };
387
+ return result;
388
+ }
313
389
  if (type === 'peer.ping') {
314
390
  const payload = assertClosedRecord(input, ['type'], [], '$["payload"]', 'invalid_payload');
315
391
  const result = {
@@ -317,11 +393,1040 @@ function validatePayload(type, input, limits) {
317
393
  };
318
394
  return result;
319
395
  }
320
- const payload = assertClosedRecord(input, ['type'], [], '$["payload"]', 'invalid_payload');
321
- const result = {
322
- type: assertPayloadType(payload.type, 'peer.ping_ack'),
396
+ if (type === 'peer.ping_ack') {
397
+ const payload = assertClosedRecord(input, ['type'], [], '$["payload"]', 'invalid_payload');
398
+ const result = {
399
+ type: assertPayloadType(payload.type, type),
400
+ };
401
+ return result;
402
+ }
403
+ if (type === 'peer.goodbye') {
404
+ const payload = assertClosedRecord(input, ['cardRevision', 'instanceId', 'peerCardId', 'type'], [], '$["payload"]', 'invalid_payload');
405
+ const result = {
406
+ type: assertPayloadType(payload.type, type),
407
+ peerCardId: assertIdentifier(payload.peerCardId, '$["payload"]["peerCardId"]', limits),
408
+ cardRevision: assertPositiveSafeInteger(payload.cardRevision, '$["payload"]["cardRevision"]', 'invalid_payload'),
409
+ instanceId: assertIdentifier(payload.instanceId, '$["payload"]["instanceId"]', limits),
410
+ };
411
+ return result;
412
+ }
413
+ if (type === 'capability.advertise') {
414
+ const payload = assertClosedRecord(input, [
415
+ 'advertisementId',
416
+ 'attributes',
417
+ 'capabilityId',
418
+ 'capabilityKey',
419
+ 'capabilityRevision',
420
+ 'inputMediaTypes',
421
+ 'outputMediaTypes',
422
+ 'ownerPeerId',
423
+ 'type',
424
+ 'validFrom',
425
+ 'validUntil',
426
+ 'version',
427
+ ], [
428
+ 'maximumConcurrency',
429
+ 'maximumPayloadBytes',
430
+ 'previousAdvertisementId',
431
+ 'variant',
432
+ ], '$["payload"]', 'invalid_payload');
433
+ const advertisementId = assertIdentifier(payload.advertisementId, '$["payload"]["advertisementId"]', limits);
434
+ const capabilityRevision = assertPositiveSafeInteger(payload.capabilityRevision, '$["payload"]["capabilityRevision"]', 'invalid_payload');
435
+ const previousAdvertisementId = payload.previousAdvertisementId === undefined
436
+ ? undefined
437
+ : assertIdentifier(payload.previousAdvertisementId, '$["payload"]["previousAdvertisementId"]', limits);
438
+ validateRevisionPredecessor(capabilityRevision, previousAdvertisementId, '$["payload"]["previousAdvertisementId"]');
439
+ if (previousAdvertisementId === advertisementId) {
440
+ fail('invalid_payload', '$["payload"]["previousAdvertisementId"]');
441
+ }
442
+ const validFrom = assertRfc3339PayloadTimestamp(payload.validFrom, '$["payload"]["validFrom"]');
443
+ const validUntil = assertRfc3339PayloadTimestamp(payload.validUntil, '$["payload"]["validUntil"]');
444
+ assertBoundedValidity(validFrom.instant, validUntil.instant);
445
+ const result = {
446
+ type: assertPayloadType(payload.type, type),
447
+ advertisementId,
448
+ capabilityId: assertIdentifier(payload.capabilityId, '$["payload"]["capabilityId"]', limits),
449
+ capabilityRevision,
450
+ ownerPeerId: assertIdentifier(payload.ownerPeerId, '$["payload"]["ownerPeerId"]', limits),
451
+ capabilityKey: assertBoundedString(payload.capabilityKey, '$["payload"]["capabilityKey"]', maximumDomainStringBytes),
452
+ version: assertBoundedString(payload.version, '$["payload"]["version"]', maximumVersionBytes),
453
+ ...(payload.variant === undefined
454
+ ? {}
455
+ : {
456
+ variant: assertBoundedString(payload.variant, '$["payload"]["variant"]', maximumVersionBytes),
457
+ }),
458
+ inputMediaTypes: validateBoundedStringArray(payload.inputMediaTypes, '$["payload"]["inputMediaTypes"]', maximumMediaTypes, maximumMediaTypeBytes, undefined, true),
459
+ outputMediaTypes: validateBoundedStringArray(payload.outputMediaTypes, '$["payload"]["outputMediaTypes"]', maximumMediaTypes, maximumMediaTypeBytes, undefined, true),
460
+ attributes: validateAttributes(payload.attributes),
461
+ validFrom: validFrom.text,
462
+ validUntil: validUntil.text,
463
+ ...(payload.maximumConcurrency === undefined
464
+ ? {}
465
+ : {
466
+ maximumConcurrency: assertPositiveSafeInteger(payload.maximumConcurrency, '$["payload"]["maximumConcurrency"]', 'invalid_payload'),
467
+ }),
468
+ ...(payload.maximumPayloadBytes === undefined
469
+ ? {}
470
+ : {
471
+ maximumPayloadBytes: assertPositiveSafeInteger(payload.maximumPayloadBytes, '$["payload"]["maximumPayloadBytes"]', 'invalid_payload'),
472
+ }),
473
+ ...(previousAdvertisementId === undefined
474
+ ? {}
475
+ : { previousAdvertisementId }),
476
+ };
477
+ return result;
478
+ }
479
+ if (type === 'capability.withdraw') {
480
+ const payload = assertClosedRecord(input, ['advertisementId', 'capabilityId', 'capabilityRevision', 'type'], [], '$["payload"]', 'invalid_payload');
481
+ const result = {
482
+ type: assertPayloadType(payload.type, type),
483
+ capabilityId: assertIdentifier(payload.capabilityId, '$["payload"]["capabilityId"]', limits),
484
+ capabilityRevision: assertPositiveSafeInteger(payload.capabilityRevision, '$["payload"]["capabilityRevision"]', 'invalid_payload'),
485
+ advertisementId: assertIdentifier(payload.advertisementId, '$["payload"]["advertisementId"]', limits),
486
+ };
487
+ return result;
488
+ }
489
+ if (type === 'objective.announce') {
490
+ const document = validateObjectiveDocument(input, type, limits);
491
+ if (document.objectiveRevision !== 1) {
492
+ fail('invalid_payload', '$["payload"]["objectiveRevision"]');
493
+ }
494
+ const result = {
495
+ type,
496
+ ...document,
497
+ };
498
+ return result;
499
+ }
500
+ if (type === 'objective.revise') {
501
+ const document = validateObjectiveDocument(input, type, limits);
502
+ if (document.objectiveRevision < 2) {
503
+ fail('invalid_payload', '$["payload"]["objectiveRevision"]');
504
+ }
505
+ const payload = input;
506
+ const previousObjectiveDocumentId = assertIdentifier(payload.previousObjectiveDocumentId, '$["payload"]["previousObjectiveDocumentId"]', limits);
507
+ if (previousObjectiveDocumentId === document.objectiveDocumentId) {
508
+ fail('invalid_payload', '$["payload"]["previousObjectiveDocumentId"]');
509
+ }
510
+ const result = {
511
+ type,
512
+ ...document,
513
+ previousObjectiveDocumentId,
514
+ };
515
+ return result;
516
+ }
517
+ if (type === 'objective.cancel') {
518
+ const payload = assertClosedRecord(input, [
519
+ 'cancellationId',
520
+ 'objectiveDocumentId',
521
+ 'objectiveId',
522
+ 'objectiveRevision',
523
+ 'type',
524
+ ], [], '$["payload"]', 'invalid_payload');
525
+ const result = {
526
+ type: assertPayloadType(payload.type, type),
527
+ cancellationId: assertIdentifier(payload.cancellationId, '$["payload"]["cancellationId"]', limits),
528
+ objectiveId: assertIdentifier(payload.objectiveId, '$["payload"]["objectiveId"]', limits),
529
+ objectiveRevision: assertPositiveSafeInteger(payload.objectiveRevision, '$["payload"]["objectiveRevision"]', 'invalid_payload'),
530
+ objectiveDocumentId: assertIdentifier(payload.objectiveDocumentId, '$["payload"]["objectiveDocumentId"]', limits),
531
+ };
532
+ return result;
533
+ }
534
+ if (type === 'work.offer') {
535
+ return validateWorkOffer(input, limits);
536
+ }
537
+ if (type === 'work.bid') {
538
+ return validateWorkBid(input, limits);
539
+ }
540
+ if (type === 'work.award') {
541
+ return validateWorkAward(input, limits);
542
+ }
543
+ if (type === 'work.accept') {
544
+ return validateWorkAccept(input, limits);
545
+ }
546
+ if (type === 'work.decline') {
547
+ return validateWorkDecline(input, limits);
548
+ }
549
+ if (type === 'work.progress') {
550
+ return validateWorkProgress(input, limits);
551
+ }
552
+ if (type === 'work.checkpoint') {
553
+ return validateWorkCheckpoint(input, limits);
554
+ }
555
+ if (type === 'work.result') {
556
+ return validateWorkResult(input, limits);
557
+ }
558
+ if (type === 'work.release') {
559
+ return validateWorkRelease(input, limits);
560
+ }
561
+ if (type === 'work.cancel') {
562
+ return validateWorkCancel(input, limits);
563
+ }
564
+ if (type === 'lease.renew') {
565
+ return validateLeaseRenew(input, limits);
566
+ }
567
+ if (type === 'lease.takeover_proposal') {
568
+ return validateLeaseTakeoverProposal(input, limits);
569
+ }
570
+ if (type === 'lease.vote') {
571
+ return validateLeaseVote(input, limits);
572
+ }
573
+ if (type === 'lease.certificate') {
574
+ return validateLeaseCertificate(input, limits);
575
+ }
576
+ return fail('unsupported_message_type', '$["type"]');
577
+ }
578
+ function validateWorkOffer(input, limits) {
579
+ const payload = assertClosedRecord(input, [
580
+ 'bidDeadline',
581
+ 'budgetReservationUnits',
582
+ 'completionCriteria',
583
+ 'matchingAttributes',
584
+ 'objectiveDocumentId',
585
+ 'objectiveId',
586
+ 'objectiveRevision',
587
+ 'offerAttempt',
588
+ 'offerId',
589
+ 'ownerEpoch',
590
+ 'ownerPeerId',
591
+ 'requiredCapabilityKeys',
592
+ 'type',
593
+ 'workDeadline',
594
+ 'workItemId',
595
+ 'workItemRevision',
596
+ ], ['inputReference', 'inputSummary', 'previousOfferId'], '$["payload"]', 'invalid_payload');
597
+ assertPayloadType(payload.type, 'work.offer');
598
+ const hasInputSummary = payload.inputSummary !== undefined;
599
+ const hasInputReference = payload.inputReference !== undefined;
600
+ if (hasInputSummary === hasInputReference) {
601
+ fail('invalid_payload', '$["payload"]');
602
+ }
603
+ const inputSummary = hasInputSummary
604
+ ? assertBoundedString(payload.inputSummary, '$["payload"]["inputSummary"]', maximumWorkTextBytes)
605
+ : undefined;
606
+ const inputReference = hasInputReference
607
+ ? assertBoundedString(payload.inputReference, '$["payload"]["inputReference"]', maximumWorkTextBytes)
608
+ : undefined;
609
+ const offerId = assertIdentifier(payload.offerId, '$["payload"]["offerId"]', limits);
610
+ const offerAttempt = assertPositiveSafeInteger(payload.offerAttempt, '$["payload"]["offerAttempt"]', 'invalid_payload');
611
+ const previousOfferId = payload.previousOfferId === undefined
612
+ ? undefined
613
+ : assertIdentifier(payload.previousOfferId, '$["payload"]["previousOfferId"]', limits);
614
+ validateRevisionPredecessor(offerAttempt, previousOfferId, '$["payload"]["previousOfferId"]');
615
+ if (previousOfferId === offerId) {
616
+ fail('invalid_payload', '$["payload"]["previousOfferId"]');
617
+ }
618
+ const requiredCapabilityKeys = validateBoundedStringArray(payload.requiredCapabilityKeys, '$["payload"]["requiredCapabilityKeys"]', maximumWorkCapabilityKeys, maximumWorkTextBytes, undefined, true);
619
+ if (requiredCapabilityKeys.length === 0) {
620
+ fail('invalid_payload', '$["payload"]["requiredCapabilityKeys"]');
621
+ }
622
+ const completionCriteria = validateBoundedStringArray(payload.completionCriteria, '$["payload"]["completionCriteria"]', maximumWorkListItems, maximumWorkTextBytes, maximumWorkListBytes);
623
+ if (completionCriteria.length === 0) {
624
+ fail('invalid_payload', '$["payload"]["completionCriteria"]');
625
+ }
626
+ const ownerEpoch = assertPositiveSafeInteger(payload.ownerEpoch, '$["payload"]["ownerEpoch"]', 'invalid_payload');
627
+ if (ownerEpoch !== 1) {
628
+ fail('invalid_payload', '$["payload"]["ownerEpoch"]');
629
+ }
630
+ const bidDeadline = assertRfc3339PayloadTimestamp(payload.bidDeadline, '$["payload"]["bidDeadline"]').text;
631
+ const workDeadline = assertRfc3339PayloadTimestamp(payload.workDeadline, '$["payload"]["workDeadline"]').text;
632
+ const fields = {
633
+ offerId,
634
+ objectiveId: assertIdentifier(payload.objectiveId, '$["payload"]["objectiveId"]', limits),
635
+ objectiveDocumentId: assertIdentifier(payload.objectiveDocumentId, '$["payload"]["objectiveDocumentId"]', limits),
636
+ objectiveRevision: assertPositiveSafeInteger(payload.objectiveRevision, '$["payload"]["objectiveRevision"]', 'invalid_payload'),
637
+ workItemId: assertIdentifier(payload.workItemId, '$["payload"]["workItemId"]', limits),
638
+ workItemRevision: assertPositiveSafeInteger(payload.workItemRevision, '$["payload"]["workItemRevision"]', 'invalid_payload'),
639
+ ownerPeerId: assertIdentifier(payload.ownerPeerId, '$["payload"]["ownerPeerId"]', limits),
640
+ ownerEpoch,
641
+ offerAttempt,
642
+ ...(previousOfferId === undefined ? {} : { previousOfferId }),
643
+ requiredCapabilityKeys,
644
+ matchingAttributes: validateAttributes(payload.matchingAttributes, '$["payload"]["matchingAttributes"]'),
645
+ completionCriteria,
646
+ budgetReservationUnits: assertNonnegativeSafeInteger(payload.budgetReservationUnits, '$["payload"]["budgetReservationUnits"]'),
647
+ bidDeadline,
648
+ workDeadline,
323
649
  };
324
- return result;
650
+ if (inputSummary !== undefined) {
651
+ const offerInput = { inputSummary };
652
+ return { type: 'work.offer', ...fields, ...offerInput };
653
+ }
654
+ if (inputReference === undefined) {
655
+ return fail('invalid_payload', '$["payload"]');
656
+ }
657
+ const offerInput = { inputReference };
658
+ return { type: 'work.offer', ...fields, ...offerInput };
659
+ }
660
+ function validateWorkBid(input, limits) {
661
+ const payload = assertClosedRecord(input, [
662
+ 'advertisementId',
663
+ 'assumptions',
664
+ 'bidDeadline',
665
+ 'bidExpiresAt',
666
+ 'bidId',
667
+ 'bidRevision',
668
+ 'bidderPeerId',
669
+ 'budgetUnits',
670
+ 'capabilityId',
671
+ 'capabilityRevision',
672
+ 'capacityReservationUnits',
673
+ 'expectedCompletionAt',
674
+ 'objectiveDocumentId',
675
+ 'objectiveId',
676
+ 'objectiveRevision',
677
+ 'offerAttempt',
678
+ 'offerId',
679
+ 'ownerEpoch',
680
+ 'ownerPeerId',
681
+ 'type',
682
+ 'workDeadline',
683
+ 'workItemId',
684
+ 'workItemRevision',
685
+ ], ['previousBidId'], '$["payload"]', 'invalid_payload');
686
+ const bidId = assertIdentifier(payload.bidId, '$["payload"]["bidId"]', limits);
687
+ const bidRevision = assertPositiveSafeInteger(payload.bidRevision, '$["payload"]["bidRevision"]', 'invalid_payload');
688
+ const previousBidId = payload.previousBidId === undefined
689
+ ? undefined
690
+ : assertIdentifier(payload.previousBidId, '$["payload"]["previousBidId"]', limits);
691
+ validateRevisionPredecessor(bidRevision, previousBidId, '$["payload"]["previousBidId"]');
692
+ if (previousBidId === bidId) {
693
+ fail('invalid_payload', '$["payload"]["previousBidId"]');
694
+ }
695
+ const ownerEpoch = assertPositiveSafeInteger(payload.ownerEpoch, '$["payload"]["ownerEpoch"]', 'invalid_payload');
696
+ if (ownerEpoch !== 1) {
697
+ fail('invalid_payload', '$["payload"]["ownerEpoch"]');
698
+ }
699
+ return {
700
+ type: assertPayloadType(payload.type, 'work.bid'),
701
+ bidId,
702
+ bidRevision,
703
+ ...(previousBidId === undefined ? {} : { previousBidId }),
704
+ offerId: assertIdentifier(payload.offerId, '$["payload"]["offerId"]', limits),
705
+ objectiveId: assertIdentifier(payload.objectiveId, '$["payload"]["objectiveId"]', limits),
706
+ objectiveDocumentId: assertIdentifier(payload.objectiveDocumentId, '$["payload"]["objectiveDocumentId"]', limits),
707
+ objectiveRevision: assertPositiveSafeInteger(payload.objectiveRevision, '$["payload"]["objectiveRevision"]', 'invalid_payload'),
708
+ workItemId: assertIdentifier(payload.workItemId, '$["payload"]["workItemId"]', limits),
709
+ workItemRevision: assertPositiveSafeInteger(payload.workItemRevision, '$["payload"]["workItemRevision"]', 'invalid_payload'),
710
+ ownerPeerId: assertIdentifier(payload.ownerPeerId, '$["payload"]["ownerPeerId"]', limits),
711
+ ownerEpoch,
712
+ offerAttempt: assertPositiveSafeInteger(payload.offerAttempt, '$["payload"]["offerAttempt"]', 'invalid_payload'),
713
+ bidderPeerId: assertIdentifier(payload.bidderPeerId, '$["payload"]["bidderPeerId"]', limits),
714
+ advertisementId: assertIdentifier(payload.advertisementId, '$["payload"]["advertisementId"]', limits),
715
+ capabilityId: assertIdentifier(payload.capabilityId, '$["payload"]["capabilityId"]', limits),
716
+ capabilityRevision: assertPositiveSafeInteger(payload.capabilityRevision, '$["payload"]["capabilityRevision"]', 'invalid_payload'),
717
+ capacityReservationUnits: assertBoundedPositiveSafeInteger(payload.capacityReservationUnits, '$["payload"]["capacityReservationUnits"]', maximumCapacityReservationUnits),
718
+ budgetUnits: assertNonnegativeSafeInteger(payload.budgetUnits, '$["payload"]["budgetUnits"]'),
719
+ bidDeadline: assertRfc3339PayloadTimestamp(payload.bidDeadline, '$["payload"]["bidDeadline"]').text,
720
+ workDeadline: assertRfc3339PayloadTimestamp(payload.workDeadline, '$["payload"]["workDeadline"]').text,
721
+ expectedCompletionAt: assertRfc3339PayloadTimestamp(payload.expectedCompletionAt, '$["payload"]["expectedCompletionAt"]').text,
722
+ bidExpiresAt: assertRfc3339PayloadTimestamp(payload.bidExpiresAt, '$["payload"]["bidExpiresAt"]').text,
723
+ assumptions: validateBoundedStringArray(payload.assumptions, '$["payload"]["assumptions"]', maximumWorkListItems, maximumWorkTextBytes, maximumWorkListBytes),
724
+ };
725
+ }
726
+ function validateWorkAward(input, limits) {
727
+ const payload = assertClosedRecord(input, [
728
+ 'acceptanceDeadline',
729
+ 'assigneePeerId',
730
+ 'assignmentAuthorityId',
731
+ 'assignmentEpoch',
732
+ 'authorityKind',
733
+ 'awardId',
734
+ 'bidId',
735
+ 'bidRevision',
736
+ 'budgetReservationUnits',
737
+ 'fencingToken',
738
+ 'leaseExpiresAt',
739
+ 'leaseStartsAt',
740
+ 'objectiveDocumentId',
741
+ 'objectiveId',
742
+ 'objectiveRevision',
743
+ 'offerAttempt',
744
+ 'offerId',
745
+ 'ownerEpoch',
746
+ 'ownerPeerId',
747
+ 'type',
748
+ 'workDeadline',
749
+ 'workItemId',
750
+ 'workItemRevision',
751
+ ], ['recoveryCertificateId', 'resumeCheckpointId'], '$["payload"]', 'invalid_payload');
752
+ assertPayloadType(payload.type, 'work.award');
753
+ const authorityKind = assertString(payload.authorityKind, '$["payload"]["authorityKind"]', 'invalid_payload');
754
+ if (authorityKind !== 'award' && authorityKind !== 'recovery_certificate') {
755
+ fail('invalid_payload', '$["payload"]["authorityKind"]');
756
+ }
757
+ const awardId = assertIdentifier(payload.awardId, '$["payload"]["awardId"]', limits);
758
+ const assignmentEpoch = assertPositiveSafeInteger(payload.assignmentEpoch, '$["payload"]["assignmentEpoch"]', 'invalid_payload');
759
+ const assignmentAuthorityId = assertIdentifier(payload.assignmentAuthorityId, '$["payload"]["assignmentAuthorityId"]', limits);
760
+ const fencingToken = assertIdentifier(payload.fencingToken, '$["payload"]["fencingToken"]', limits);
761
+ if (assignmentAuthorityId !== fencingToken) {
762
+ fail('invalid_payload', '$["payload"]["fencingToken"]');
763
+ }
764
+ const ownerEpoch = assertPositiveSafeInteger(payload.ownerEpoch, '$["payload"]["ownerEpoch"]', 'invalid_payload');
765
+ if (ownerEpoch !== 1) {
766
+ fail('invalid_payload', '$["payload"]["ownerEpoch"]');
767
+ }
768
+ const fields = {
769
+ type: 'work.award',
770
+ awardId,
771
+ offerId: assertIdentifier(payload.offerId, '$["payload"]["offerId"]', limits),
772
+ bidId: assertIdentifier(payload.bidId, '$["payload"]["bidId"]', limits),
773
+ bidRevision: assertPositiveSafeInteger(payload.bidRevision, '$["payload"]["bidRevision"]', 'invalid_payload'),
774
+ objectiveId: assertIdentifier(payload.objectiveId, '$["payload"]["objectiveId"]', limits),
775
+ objectiveDocumentId: assertIdentifier(payload.objectiveDocumentId, '$["payload"]["objectiveDocumentId"]', limits),
776
+ objectiveRevision: assertPositiveSafeInteger(payload.objectiveRevision, '$["payload"]["objectiveRevision"]', 'invalid_payload'),
777
+ workItemId: assertIdentifier(payload.workItemId, '$["payload"]["workItemId"]', limits),
778
+ workItemRevision: assertPositiveSafeInteger(payload.workItemRevision, '$["payload"]["workItemRevision"]', 'invalid_payload'),
779
+ ownerPeerId: assertIdentifier(payload.ownerPeerId, '$["payload"]["ownerPeerId"]', limits),
780
+ ownerEpoch,
781
+ offerAttempt: assertPositiveSafeInteger(payload.offerAttempt, '$["payload"]["offerAttempt"]', 'invalid_payload'),
782
+ assigneePeerId: assertIdentifier(payload.assigneePeerId, '$["payload"]["assigneePeerId"]', limits),
783
+ assignmentEpoch,
784
+ assignmentAuthorityId,
785
+ fencingToken,
786
+ budgetReservationUnits: assertNonnegativeSafeInteger(payload.budgetReservationUnits, '$["payload"]["budgetReservationUnits"]'),
787
+ workDeadline: assertRfc3339PayloadTimestamp(payload.workDeadline, '$["payload"]["workDeadline"]').text,
788
+ leaseStartsAt: assertRfc3339PayloadTimestamp(payload.leaseStartsAt, '$["payload"]["leaseStartsAt"]').text,
789
+ leaseExpiresAt: assertRfc3339PayloadTimestamp(payload.leaseExpiresAt, '$["payload"]["leaseExpiresAt"]').text,
790
+ acceptanceDeadline: assertRfc3339PayloadTimestamp(payload.acceptanceDeadline, '$["payload"]["acceptanceDeadline"]').text,
791
+ };
792
+ if (authorityKind === 'award') {
793
+ if (payload.recoveryCertificateId !== undefined ||
794
+ payload.resumeCheckpointId !== undefined) {
795
+ fail('invalid_payload', '$["payload"]');
796
+ }
797
+ if (assignmentAuthorityId !== awardId) {
798
+ fail('invalid_payload', '$["payload"]["assignmentAuthorityId"]');
799
+ }
800
+ return { ...fields, authorityKind };
801
+ }
802
+ if (assignmentEpoch < 2) {
803
+ fail('invalid_payload', '$["payload"]["assignmentEpoch"]');
804
+ }
805
+ const recoveryCertificateId = assertIdentifier(payload.recoveryCertificateId, '$["payload"]["recoveryCertificateId"]', limits);
806
+ if (assignmentAuthorityId !== recoveryCertificateId) {
807
+ fail('invalid_payload', '$["payload"]["assignmentAuthorityId"]');
808
+ }
809
+ const resumeCheckpointId = payload.resumeCheckpointId === undefined
810
+ ? undefined
811
+ : assertIdentifier(payload.resumeCheckpointId, '$["payload"]["resumeCheckpointId"]', limits);
812
+ return {
813
+ ...fields,
814
+ authorityKind,
815
+ recoveryCertificateId,
816
+ ...(resumeCheckpointId === undefined ? {} : { resumeCheckpointId }),
817
+ };
818
+ }
819
+ function validateWorkAccept(input, limits) {
820
+ const payload = validateWorkAssignmentResponse(input, 'work.accept', 'acceptanceId', limits);
821
+ return {
822
+ type: 'work.accept',
823
+ acceptanceId: payload.responseId,
824
+ ...payload.fields,
825
+ };
826
+ }
827
+ function validateWorkDecline(input, limits) {
828
+ const payload = validateWorkAssignmentResponse(input, 'work.decline', 'declineId', limits);
829
+ return {
830
+ type: 'work.decline',
831
+ declineId: payload.responseId,
832
+ ...payload.fields,
833
+ };
834
+ }
835
+ function validateWorkProgress(input, limits) {
836
+ const payload = assertClosedRecord(input, [
837
+ 'acceptanceId',
838
+ 'assigneePeerId',
839
+ 'assignmentAuthorityId',
840
+ 'assignmentEpoch',
841
+ 'awardId',
842
+ 'fencingToken',
843
+ 'leaseExpiresAt',
844
+ 'objectiveDocumentId',
845
+ 'objectiveId',
846
+ 'objectiveRevision',
847
+ 'ownerEpoch',
848
+ 'ownerPeerId',
849
+ 'progressId',
850
+ 'progressSequence',
851
+ 'progressSummary',
852
+ 'type',
853
+ 'workItemId',
854
+ 'workItemRevision',
855
+ ], ['checkpointId'], '$["payload"]', 'invalid_payload');
856
+ assertPayloadType(payload.type, 'work.progress');
857
+ const checkpointId = payload.checkpointId === undefined
858
+ ? undefined
859
+ : assertIdentifier(payload.checkpointId, '$["payload"]["checkpointId"]', limits);
860
+ return {
861
+ type: 'work.progress',
862
+ ...validateWorkExecutionAuthorityFields(payload, limits),
863
+ progressId: assertIdentifier(payload.progressId, '$["payload"]["progressId"]', limits),
864
+ progressSequence: assertPositiveSafeInteger(payload.progressSequence, '$["payload"]["progressSequence"]', 'invalid_payload'),
865
+ progressSummary: assertBoundedString(payload.progressSummary, '$["payload"]["progressSummary"]', maximumWorkTextBytes),
866
+ ...(checkpointId === undefined ? {} : { checkpointId }),
867
+ };
868
+ }
869
+ function validateWorkCheckpoint(input, limits) {
870
+ const payload = assertClosedRecord(input, [
871
+ 'acceptanceId',
872
+ 'assigneePeerId',
873
+ 'assignmentAuthorityId',
874
+ 'assignmentEpoch',
875
+ 'awardId',
876
+ 'checkpointDigest',
877
+ 'checkpointId',
878
+ 'checkpointSequence',
879
+ 'fencingToken',
880
+ 'leaseExpiresAt',
881
+ 'objectiveDocumentId',
882
+ 'objectiveId',
883
+ 'objectiveRevision',
884
+ 'ownerEpoch',
885
+ 'ownerPeerId',
886
+ 'type',
887
+ 'workItemId',
888
+ 'workItemRevision',
889
+ ], ['checkpointReference', 'checkpointSummary', 'previousCheckpointId'], '$["payload"]', 'invalid_payload');
890
+ assertPayloadType(payload.type, 'work.checkpoint');
891
+ const checkpointId = assertIdentifier(payload.checkpointId, '$["payload"]["checkpointId"]', limits);
892
+ const checkpointSequence = assertPositiveSafeInteger(payload.checkpointSequence, '$["payload"]["checkpointSequence"]', 'invalid_payload');
893
+ const previousCheckpointId = payload.previousCheckpointId === undefined
894
+ ? undefined
895
+ : assertIdentifier(payload.previousCheckpointId, '$["payload"]["previousCheckpointId"]', limits);
896
+ validateRevisionPredecessor(checkpointSequence, previousCheckpointId, '$["payload"]["previousCheckpointId"]');
897
+ if (previousCheckpointId === checkpointId) {
898
+ fail('invalid_payload', '$["payload"]["previousCheckpointId"]');
899
+ }
900
+ return {
901
+ type: 'work.checkpoint',
902
+ ...validateWorkExecutionAuthorityFields(payload, limits),
903
+ ...validateWorkCheckpointContent(payload, limits),
904
+ checkpointId,
905
+ checkpointSequence,
906
+ ...(previousCheckpointId === undefined ? {} : { previousCheckpointId }),
907
+ checkpointDigest: assertContentDigest(payload.checkpointDigest, '$["payload"]["checkpointDigest"]'),
908
+ };
909
+ }
910
+ function validateWorkResult(input, limits) {
911
+ const payload = assertClosedRecord(input, [
912
+ 'acceptanceId',
913
+ 'assigneePeerId',
914
+ 'assignmentAuthorityId',
915
+ 'assignmentEpoch',
916
+ 'awardId',
917
+ 'fencingToken',
918
+ 'leaseExpiresAt',
919
+ 'objectiveDocumentId',
920
+ 'objectiveId',
921
+ 'objectiveRevision',
922
+ 'ownerEpoch',
923
+ 'ownerPeerId',
924
+ 'resultDigest',
925
+ 'resultId',
926
+ 'type',
927
+ 'workItemId',
928
+ 'workItemRevision',
929
+ ], ['checkpointId', 'resultReference', 'resultSummary'], '$["payload"]', 'invalid_payload');
930
+ assertPayloadType(payload.type, 'work.result');
931
+ const checkpointId = payload.checkpointId === undefined
932
+ ? undefined
933
+ : assertIdentifier(payload.checkpointId, '$["payload"]["checkpointId"]', limits);
934
+ return {
935
+ type: 'work.result',
936
+ ...validateWorkExecutionAuthorityFields(payload, limits),
937
+ ...validateWorkResultContent(payload, limits),
938
+ resultId: assertIdentifier(payload.resultId, '$["payload"]["resultId"]', limits),
939
+ resultDigest: assertContentDigest(payload.resultDigest, '$["payload"]["resultDigest"]'),
940
+ ...(checkpointId === undefined ? {} : { checkpointId }),
941
+ };
942
+ }
943
+ function validateWorkRelease(input, limits) {
944
+ const payload = assertClosedRecord(input, [
945
+ 'acceptanceId',
946
+ 'assigneePeerId',
947
+ 'assignmentAuthorityId',
948
+ 'assignmentEpoch',
949
+ 'awardId',
950
+ 'fencingToken',
951
+ 'leaseExpiresAt',
952
+ 'objectiveDocumentId',
953
+ 'objectiveId',
954
+ 'objectiveRevision',
955
+ 'ownerEpoch',
956
+ 'ownerPeerId',
957
+ 'releaseAuthority',
958
+ 'releaseDisposition',
959
+ 'releaseId',
960
+ 'type',
961
+ 'workItemId',
962
+ 'workItemRevision',
963
+ ], [], '$["payload"]', 'invalid_payload');
964
+ assertPayloadType(payload.type, 'work.release');
965
+ const releaseAuthority = assertString(payload.releaseAuthority, '$["payload"]["releaseAuthority"]', 'invalid_payload');
966
+ if (releaseAuthority !== 'owner' && releaseAuthority !== 'assignee') {
967
+ fail('invalid_payload', '$["payload"]["releaseAuthority"]');
968
+ }
969
+ const releaseDisposition = assertString(payload.releaseDisposition, '$["payload"]["releaseDisposition"]', 'invalid_payload');
970
+ if (releaseDisposition !== 'reoffer' && releaseDisposition !== 'close') {
971
+ fail('invalid_payload', '$["payload"]["releaseDisposition"]');
972
+ }
973
+ return {
974
+ type: 'work.release',
975
+ ...validateWorkExecutionAuthorityFields(payload, limits),
976
+ releaseId: assertIdentifier(payload.releaseId, '$["payload"]["releaseId"]', limits),
977
+ releaseAuthority,
978
+ releaseDisposition,
979
+ };
980
+ }
981
+ function validateWorkCancel(input, limits) {
982
+ const payload = assertClosedRecord(input, [
983
+ 'assigneePeerId',
984
+ 'assignmentAuthorityId',
985
+ 'assignmentEpoch',
986
+ 'assignmentState',
987
+ 'awardId',
988
+ 'cancellationId',
989
+ 'fencingToken',
990
+ 'leaseExpiresAt',
991
+ 'objectiveDocumentId',
992
+ 'objectiveId',
993
+ 'objectiveRevision',
994
+ 'ownerEpoch',
995
+ 'ownerPeerId',
996
+ 'type',
997
+ 'workItemId',
998
+ 'workItemRevision',
999
+ ], ['acceptanceId'], '$["payload"]', 'invalid_payload');
1000
+ assertPayloadType(payload.type, 'work.cancel');
1001
+ const fields = validateWorkAssignmentAuthorityFields(payload, limits);
1002
+ const cancellationId = assertIdentifier(payload.cancellationId, '$["payload"]["cancellationId"]', limits);
1003
+ const assignmentState = assertString(payload.assignmentState, '$["payload"]["assignmentState"]', 'invalid_payload');
1004
+ if (assignmentState === 'award_pending') {
1005
+ if (Object.hasOwn(payload, 'acceptanceId')) {
1006
+ fail('invalid_payload', '$["payload"]["acceptanceId"]');
1007
+ }
1008
+ return {
1009
+ type: 'work.cancel',
1010
+ ...fields,
1011
+ cancellationId,
1012
+ assignmentState,
1013
+ };
1014
+ }
1015
+ if (assignmentState === 'active') {
1016
+ return {
1017
+ type: 'work.cancel',
1018
+ ...fields,
1019
+ cancellationId,
1020
+ assignmentState,
1021
+ acceptanceId: assertIdentifier(payload.acceptanceId, '$["payload"]["acceptanceId"]', limits),
1022
+ };
1023
+ }
1024
+ return fail('invalid_payload', '$["payload"]["assignmentState"]');
1025
+ }
1026
+ function validateLeaseRenew(input, limits) {
1027
+ const payload = assertClosedRecord(input, [
1028
+ 'acceptanceId',
1029
+ 'assigneePeerId',
1030
+ 'assignmentAuthorityId',
1031
+ 'assignmentEpoch',
1032
+ 'awardId',
1033
+ 'fencingToken',
1034
+ 'leaseExpiresAt',
1035
+ 'leaseRenewalId',
1036
+ 'leaseRenewalSequence',
1037
+ 'objectiveDocumentId',
1038
+ 'objectiveId',
1039
+ 'objectiveRevision',
1040
+ 'ownerEpoch',
1041
+ 'ownerPeerId',
1042
+ 'renewedLeaseExpiresAt',
1043
+ 'type',
1044
+ 'workItemId',
1045
+ 'workItemRevision',
1046
+ ], ['previousLeaseRenewalId'], '$["payload"]', 'invalid_payload');
1047
+ assertPayloadType(payload.type, 'lease.renew');
1048
+ const fields = validateWorkExecutionAuthorityFields(payload, limits);
1049
+ const leaseRenewalId = assertIdentifier(payload.leaseRenewalId, '$["payload"]["leaseRenewalId"]', limits);
1050
+ const leaseRenewalSequence = assertPositiveSafeInteger(payload.leaseRenewalSequence, '$["payload"]["leaseRenewalSequence"]', 'invalid_payload');
1051
+ if (leaseRenewalSequence > maximumLeaseRenewals) {
1052
+ fail('invalid_payload', '$["payload"]["leaseRenewalSequence"]');
1053
+ }
1054
+ const previousLeaseRenewalId = payload.previousLeaseRenewalId === undefined
1055
+ ? undefined
1056
+ : assertIdentifier(payload.previousLeaseRenewalId, '$["payload"]["previousLeaseRenewalId"]', limits);
1057
+ validateRevisionPredecessor(leaseRenewalSequence, previousLeaseRenewalId, '$["payload"]["previousLeaseRenewalId"]');
1058
+ if (previousLeaseRenewalId === leaseRenewalId) {
1059
+ fail('invalid_payload', '$["payload"]["previousLeaseRenewalId"]');
1060
+ }
1061
+ const renewedLeaseExpiresAt = assertRfc3339PayloadTimestamp(payload.renewedLeaseExpiresAt, '$["payload"]["renewedLeaseExpiresAt"]');
1062
+ const currentLeaseExpiresAt = parseRfc3339(fields.leaseExpiresAt, '$["payload"]["leaseExpiresAt"]');
1063
+ if (renewedLeaseExpiresAt.instant <= currentLeaseExpiresAt) {
1064
+ fail('invalid_payload', '$["payload"]["renewedLeaseExpiresAt"]');
1065
+ }
1066
+ if (renewedLeaseExpiresAt.instant - currentLeaseExpiresAt >
1067
+ BigInt(maximumLeaseDurationMs) * 1000000n) {
1068
+ fail('invalid_payload', '$["payload"]["renewedLeaseExpiresAt"]');
1069
+ }
1070
+ return {
1071
+ type: 'lease.renew',
1072
+ ...fields,
1073
+ leaseRenewalId,
1074
+ leaseRenewalSequence,
1075
+ ...(previousLeaseRenewalId === undefined ? {} : { previousLeaseRenewalId }),
1076
+ renewedLeaseExpiresAt: renewedLeaseExpiresAt.text,
1077
+ };
1078
+ }
1079
+ function validateLeaseTakeoverProposal(input, limits) {
1080
+ const payload = assertClosedRecord(input, [
1081
+ 'acceptanceId',
1082
+ 'assigneePeerId',
1083
+ 'assignmentAuthorityId',
1084
+ 'assignmentEpoch',
1085
+ 'awardId',
1086
+ 'fencingToken',
1087
+ 'leaseExpiresAt',
1088
+ 'leaseRenewalSequence',
1089
+ 'objectiveDocumentId',
1090
+ 'objectiveId',
1091
+ 'objectiveRevision',
1092
+ 'ownerEpoch',
1093
+ 'ownerPeerId',
1094
+ 'proposalAuthority',
1095
+ 'proposedAssigneePeerId',
1096
+ 'proposedAssignmentEpoch',
1097
+ 'proposerPeerId',
1098
+ 'takeoverProposalId',
1099
+ 'type',
1100
+ 'workItemId',
1101
+ 'workItemRevision',
1102
+ ], ['candidateConsentProposalId', 'latestLeaseRenewalId'], '$["payload"]', 'invalid_payload');
1103
+ assertPayloadType(payload.type, 'lease.takeover_proposal');
1104
+ const fields = validateWorkExecutionAuthorityFields(payload, limits);
1105
+ const takeoverProposalId = assertIdentifier(payload.takeoverProposalId, '$["payload"]["takeoverProposalId"]', limits);
1106
+ const proposerPeerId = assertIdentifier(payload.proposerPeerId, '$["payload"]["proposerPeerId"]', limits);
1107
+ const proposedAssigneePeerId = assertIdentifier(payload.proposedAssigneePeerId, '$["payload"]["proposedAssigneePeerId"]', limits);
1108
+ if (proposedAssigneePeerId === fields.assigneePeerId) {
1109
+ fail('invalid_payload', '$["payload"]["proposedAssigneePeerId"]');
1110
+ }
1111
+ const proposalAuthority = assertString(payload.proposalAuthority, '$["payload"]["proposalAuthority"]', 'invalid_payload');
1112
+ if (proposalAuthority !== 'candidate' && proposalAuthority !== 'witness') {
1113
+ fail('invalid_payload', '$["payload"]["proposalAuthority"]');
1114
+ }
1115
+ if (proposalAuthority === 'candidate' &&
1116
+ proposerPeerId !== proposedAssigneePeerId) {
1117
+ fail('invalid_payload', '$["payload"]["proposedAssigneePeerId"]');
1118
+ }
1119
+ if (proposalAuthority === 'witness' &&
1120
+ proposerPeerId === proposedAssigneePeerId) {
1121
+ fail('invalid_payload', '$["payload"]["proposalAuthority"]');
1122
+ }
1123
+ if (proposalAuthority === 'candidate' &&
1124
+ Object.hasOwn(payload, 'candidateConsentProposalId')) {
1125
+ fail('invalid_payload', '$["payload"]["candidateConsentProposalId"]');
1126
+ }
1127
+ const proposedAssignmentEpoch = assertPositiveSafeInteger(payload.proposedAssignmentEpoch, '$["payload"]["proposedAssignmentEpoch"]', 'invalid_payload');
1128
+ if (proposedAssignmentEpoch !== fields.assignmentEpoch + 1) {
1129
+ fail('invalid_payload', '$["payload"]["proposedAssignmentEpoch"]');
1130
+ }
1131
+ const leaseRenewalSequence = assertNonnegativeSafeInteger(payload.leaseRenewalSequence, '$["payload"]["leaseRenewalSequence"]');
1132
+ if (leaseRenewalSequence > maximumLeaseRenewals) {
1133
+ fail('invalid_payload', '$["payload"]["leaseRenewalSequence"]');
1134
+ }
1135
+ const latestLeaseRenewalId = leaseRenewalSequence === 0
1136
+ ? undefined
1137
+ : assertIdentifier(payload.latestLeaseRenewalId, '$["payload"]["latestLeaseRenewalId"]', limits);
1138
+ if (leaseRenewalSequence === 0) {
1139
+ if (Object.hasOwn(payload, 'latestLeaseRenewalId')) {
1140
+ fail('invalid_payload', '$["payload"]["latestLeaseRenewalId"]');
1141
+ }
1142
+ }
1143
+ const proposalFields = {
1144
+ type: 'lease.takeover_proposal',
1145
+ ...fields,
1146
+ takeoverProposalId,
1147
+ proposerPeerId,
1148
+ proposedAssigneePeerId,
1149
+ proposedAssignmentEpoch,
1150
+ leaseRenewalSequence,
1151
+ ...(latestLeaseRenewalId === undefined ? {} : { latestLeaseRenewalId }),
1152
+ };
1153
+ if (proposalAuthority === 'candidate') {
1154
+ return {
1155
+ ...proposalFields,
1156
+ proposalAuthority,
1157
+ };
1158
+ }
1159
+ return {
1160
+ ...proposalFields,
1161
+ proposalAuthority,
1162
+ candidateConsentProposalId: assertIdentifier(payload.candidateConsentProposalId, '$["payload"]["candidateConsentProposalId"]', limits),
1163
+ };
1164
+ }
1165
+ function validateLeaseVote(input, limits) {
1166
+ const payload = assertClosedRecord(input, [
1167
+ 'leaseVoteId',
1168
+ 'objectiveId',
1169
+ 'takeoverProposalId',
1170
+ 'type',
1171
+ 'witnessPeerId',
1172
+ ], [], '$["payload"]', 'invalid_payload');
1173
+ return {
1174
+ type: assertPayloadType(payload.type, 'lease.vote'),
1175
+ leaseVoteId: assertIdentifier(payload.leaseVoteId, '$["payload"]["leaseVoteId"]', limits),
1176
+ takeoverProposalId: assertIdentifier(payload.takeoverProposalId, '$["payload"]["takeoverProposalId"]', limits),
1177
+ witnessPeerId: assertIdentifier(payload.witnessPeerId, '$["payload"]["witnessPeerId"]', limits),
1178
+ objectiveId: assertIdentifier(payload.objectiveId, '$["payload"]["objectiveId"]', limits),
1179
+ };
1180
+ }
1181
+ function validateLeaseCertificate(input, limits) {
1182
+ const payload = assertClosedRecord(input, [
1183
+ 'certificateAssemblerPeerId',
1184
+ 'certificateId',
1185
+ 'leaseVoteIds',
1186
+ 'objectiveId',
1187
+ 'takeoverProposalId',
1188
+ 'type',
1189
+ ], [], '$["payload"]', 'invalid_payload');
1190
+ const leaseVoteIds = validateIdentifierArray(payload.leaseVoteIds, '$["payload"]["leaseVoteIds"]', maximumRecoveryWitnesses, limits);
1191
+ if (leaseVoteIds.length < 2) {
1192
+ fail('invalid_payload', '$["payload"]["leaseVoteIds"]');
1193
+ }
1194
+ return {
1195
+ type: assertPayloadType(payload.type, 'lease.certificate'),
1196
+ certificateId: assertIdentifier(payload.certificateId, '$["payload"]["certificateId"]', limits),
1197
+ certificateAssemblerPeerId: assertIdentifier(payload.certificateAssemblerPeerId, '$["payload"]["certificateAssemblerPeerId"]', limits),
1198
+ takeoverProposalId: assertIdentifier(payload.takeoverProposalId, '$["payload"]["takeoverProposalId"]', limits),
1199
+ leaseVoteIds,
1200
+ objectiveId: assertIdentifier(payload.objectiveId, '$["payload"]["objectiveId"]', limits),
1201
+ };
1202
+ }
1203
+ function validateWorkExecutionAuthorityFields(payload, limits) {
1204
+ return {
1205
+ ...validateWorkAssignmentAuthorityFields(payload, limits),
1206
+ acceptanceId: assertIdentifier(payload.acceptanceId, '$["payload"]["acceptanceId"]', limits),
1207
+ };
1208
+ }
1209
+ function validateWorkAssignmentAuthorityFields(payload, limits) {
1210
+ const ownerEpoch = assertPositiveSafeInteger(payload.ownerEpoch, '$["payload"]["ownerEpoch"]', 'invalid_payload');
1211
+ if (ownerEpoch !== 1) {
1212
+ fail('invalid_payload', '$["payload"]["ownerEpoch"]');
1213
+ }
1214
+ const assignmentAuthorityId = assertIdentifier(payload.assignmentAuthorityId, '$["payload"]["assignmentAuthorityId"]', limits);
1215
+ const fencingToken = assertIdentifier(payload.fencingToken, '$["payload"]["fencingToken"]', limits);
1216
+ if (assignmentAuthorityId !== fencingToken) {
1217
+ fail('invalid_payload', '$["payload"]["fencingToken"]');
1218
+ }
1219
+ return {
1220
+ objectiveId: assertIdentifier(payload.objectiveId, '$["payload"]["objectiveId"]', limits),
1221
+ objectiveDocumentId: assertIdentifier(payload.objectiveDocumentId, '$["payload"]["objectiveDocumentId"]', limits),
1222
+ objectiveRevision: assertPositiveSafeInteger(payload.objectiveRevision, '$["payload"]["objectiveRevision"]', 'invalid_payload'),
1223
+ workItemId: assertIdentifier(payload.workItemId, '$["payload"]["workItemId"]', limits),
1224
+ workItemRevision: assertPositiveSafeInteger(payload.workItemRevision, '$["payload"]["workItemRevision"]', 'invalid_payload'),
1225
+ ownerPeerId: assertIdentifier(payload.ownerPeerId, '$["payload"]["ownerPeerId"]', limits),
1226
+ ownerEpoch,
1227
+ assigneePeerId: assertIdentifier(payload.assigneePeerId, '$["payload"]["assigneePeerId"]', limits),
1228
+ awardId: assertIdentifier(payload.awardId, '$["payload"]["awardId"]', limits),
1229
+ assignmentEpoch: assertPositiveSafeInteger(payload.assignmentEpoch, '$["payload"]["assignmentEpoch"]', 'invalid_payload'),
1230
+ assignmentAuthorityId,
1231
+ fencingToken,
1232
+ leaseExpiresAt: assertRfc3339PayloadTimestamp(payload.leaseExpiresAt, '$["payload"]["leaseExpiresAt"]').text,
1233
+ };
1234
+ }
1235
+ function validateWorkCheckpointContent(payload, limits) {
1236
+ const hasSummary = payload.checkpointSummary !== undefined;
1237
+ const hasReference = payload.checkpointReference !== undefined;
1238
+ if (hasSummary === hasReference) {
1239
+ fail('invalid_payload', '$["payload"]');
1240
+ }
1241
+ if (hasSummary) {
1242
+ return {
1243
+ checkpointSummary: assertBoundedString(payload.checkpointSummary, '$["payload"]["checkpointSummary"]', maximumWorkTextBytes),
1244
+ };
1245
+ }
1246
+ return {
1247
+ checkpointReference: assertBoundedString(payload.checkpointReference, '$["payload"]["checkpointReference"]', maximumWorkTextBytes),
1248
+ };
1249
+ }
1250
+ function validateWorkResultContent(payload, limits) {
1251
+ const hasSummary = payload.resultSummary !== undefined;
1252
+ const hasReference = payload.resultReference !== undefined;
1253
+ if (hasSummary === hasReference) {
1254
+ fail('invalid_payload', '$["payload"]');
1255
+ }
1256
+ if (hasSummary) {
1257
+ return {
1258
+ resultSummary: assertBoundedString(payload.resultSummary, '$["payload"]["resultSummary"]', maximumWorkTextBytes),
1259
+ };
1260
+ }
1261
+ return {
1262
+ resultReference: assertBoundedString(payload.resultReference, '$["payload"]["resultReference"]', maximumWorkTextBytes),
1263
+ };
1264
+ }
1265
+ function validateWorkAssignmentResponse(input, type, responseIdKey, limits) {
1266
+ const payload = assertClosedRecord(input, [
1267
+ 'acceptanceDeadline',
1268
+ 'assigneePeerId',
1269
+ 'assignmentAuthorityId',
1270
+ 'assignmentEpoch',
1271
+ 'awardId',
1272
+ 'fencingToken',
1273
+ 'objectiveDocumentId',
1274
+ 'objectiveId',
1275
+ 'objectiveRevision',
1276
+ 'ownerEpoch',
1277
+ 'ownerPeerId',
1278
+ responseIdKey,
1279
+ 'type',
1280
+ 'workItemId',
1281
+ 'workItemRevision',
1282
+ ], [], '$["payload"]', 'invalid_payload');
1283
+ assertPayloadType(payload.type, type);
1284
+ const assignmentAuthorityId = assertIdentifier(payload.assignmentAuthorityId, '$["payload"]["assignmentAuthorityId"]', limits);
1285
+ const fencingToken = assertIdentifier(payload.fencingToken, '$["payload"]["fencingToken"]', limits);
1286
+ if (assignmentAuthorityId !== fencingToken) {
1287
+ fail('invalid_payload', '$["payload"]["fencingToken"]');
1288
+ }
1289
+ const ownerEpoch = assertPositiveSafeInteger(payload.ownerEpoch, '$["payload"]["ownerEpoch"]', 'invalid_payload');
1290
+ if (ownerEpoch !== 1) {
1291
+ fail('invalid_payload', '$["payload"]["ownerEpoch"]');
1292
+ }
1293
+ return {
1294
+ responseId: assertIdentifier(payload[responseIdKey], `$["payload"]["${responseIdKey}"]`, limits),
1295
+ fields: {
1296
+ awardId: assertIdentifier(payload.awardId, '$["payload"]["awardId"]', limits),
1297
+ objectiveId: assertIdentifier(payload.objectiveId, '$["payload"]["objectiveId"]', limits),
1298
+ objectiveDocumentId: assertIdentifier(payload.objectiveDocumentId, '$["payload"]["objectiveDocumentId"]', limits),
1299
+ objectiveRevision: assertPositiveSafeInteger(payload.objectiveRevision, '$["payload"]["objectiveRevision"]', 'invalid_payload'),
1300
+ workItemId: assertIdentifier(payload.workItemId, '$["payload"]["workItemId"]', limits),
1301
+ workItemRevision: assertPositiveSafeInteger(payload.workItemRevision, '$["payload"]["workItemRevision"]', 'invalid_payload'),
1302
+ ownerPeerId: assertIdentifier(payload.ownerPeerId, '$["payload"]["ownerPeerId"]', limits),
1303
+ ownerEpoch,
1304
+ assigneePeerId: assertIdentifier(payload.assigneePeerId, '$["payload"]["assigneePeerId"]', limits),
1305
+ assignmentEpoch: assertPositiveSafeInteger(payload.assignmentEpoch, '$["payload"]["assignmentEpoch"]', 'invalid_payload'),
1306
+ assignmentAuthorityId,
1307
+ fencingToken,
1308
+ acceptanceDeadline: assertRfc3339PayloadTimestamp(payload.acceptanceDeadline, '$["payload"]["acceptanceDeadline"]').text,
1309
+ },
1310
+ };
1311
+ }
1312
+ function validateObjectiveDocument(input, type, limits) {
1313
+ const requiredKeys = [
1314
+ 'acceptanceWindowMs',
1315
+ 'bidWindowMs',
1316
+ 'issuerPeerId',
1317
+ 'maximumBudgetUnits',
1318
+ 'maximumConcurrentAssignments',
1319
+ 'maximumLeaseDurationMs',
1320
+ 'maximumLeaseRenewals',
1321
+ 'maximumWorkItems',
1322
+ 'objectiveDocumentId',
1323
+ 'objectiveId',
1324
+ 'objectiveRevision',
1325
+ 'permittedCapabilityKeys',
1326
+ 'recoveryGraceMs',
1327
+ 'recoveryWitnessPeerIds',
1328
+ 'recoveryWitnessThreshold',
1329
+ 'successCriteria',
1330
+ 'type',
1331
+ 'validFrom',
1332
+ 'validUntil',
1333
+ ];
1334
+ if (type === 'objective.revise') {
1335
+ requiredKeys.push('previousObjectiveDocumentId');
1336
+ }
1337
+ const payload = assertClosedRecord(input, requiredKeys, ['authorizedObserverPeerIds', 'contentReference', 'summary'], '$["payload"]', 'invalid_payload');
1338
+ assertPayloadType(payload.type, type);
1339
+ const hasSummary = payload.summary !== undefined;
1340
+ const hasContentReference = payload.contentReference !== undefined;
1341
+ if (hasSummary === hasContentReference) {
1342
+ fail('invalid_payload', '$["payload"]');
1343
+ }
1344
+ const summary = hasSummary
1345
+ ? assertBoundedString(payload.summary, '$["payload"]["summary"]', maximumObjectiveTextBytes)
1346
+ : undefined;
1347
+ const contentReference = hasContentReference
1348
+ ? assertBoundedString(payload.contentReference, '$["payload"]["contentReference"]', maximumObjectiveTextBytes)
1349
+ : undefined;
1350
+ const successCriteria = validateBoundedStringArray(payload.successCriteria, '$["payload"]["successCriteria"]', maximumSuccessCriteria, maximumObjectiveTextBytes, maximumSuccessCriteriaBytes);
1351
+ if (successCriteria.length === 0) {
1352
+ fail('invalid_payload', '$["payload"]["successCriteria"]');
1353
+ }
1354
+ const permittedCapabilityKeys = validateBoundedStringArray(payload.permittedCapabilityKeys, '$["payload"]["permittedCapabilityKeys"]', maximumPermittedCapabilityKeys, maximumObjectiveTextBytes, undefined, true);
1355
+ if (permittedCapabilityKeys.length === 0) {
1356
+ fail('invalid_payload', '$["payload"]["permittedCapabilityKeys"]');
1357
+ }
1358
+ const recoveryWitnessPeerIds = validateIdentifierArray(payload.recoveryWitnessPeerIds, '$["payload"]["recoveryWitnessPeerIds"]', maximumRecoveryWitnesses, limits);
1359
+ if (recoveryWitnessPeerIds.length < minimumRecoveryWitnesses) {
1360
+ fail('invalid_payload', '$["payload"]["recoveryWitnessPeerIds"]');
1361
+ }
1362
+ const recoveryWitnessThreshold = assertPositiveSafeInteger(payload.recoveryWitnessThreshold, '$["payload"]["recoveryWitnessThreshold"]', 'invalid_payload');
1363
+ if (recoveryWitnessThreshold > recoveryWitnessPeerIds.length ||
1364
+ recoveryWitnessThreshold <= recoveryWitnessPeerIds.length / 2) {
1365
+ fail('invalid_payload', '$["payload"]["recoveryWitnessThreshold"]');
1366
+ }
1367
+ const authorizedObserverPeerIds = payload.authorizedObserverPeerIds === undefined
1368
+ ? undefined
1369
+ : validateIdentifierArray(payload.authorizedObserverPeerIds, '$["payload"]["authorizedObserverPeerIds"]', maximumAuthorizedObservers, limits);
1370
+ const maximumWorkItems = assertPositiveSafeInteger(payload.maximumWorkItems, '$["payload"]["maximumWorkItems"]', 'invalid_payload');
1371
+ if (maximumWorkItems > maximumObjectiveWorkItems) {
1372
+ fail('invalid_payload', '$["payload"]["maximumWorkItems"]');
1373
+ }
1374
+ const maximumConcurrentAssignments = assertPositiveSafeInteger(payload.maximumConcurrentAssignments, '$["payload"]["maximumConcurrentAssignments"]', 'invalid_payload');
1375
+ if (maximumConcurrentAssignments > maximumWorkItems) {
1376
+ fail('invalid_payload', '$["payload"]["maximumConcurrentAssignments"]');
1377
+ }
1378
+ const maximumBudgetUnits = assertNonnegativeSafeInteger(payload.maximumBudgetUnits, '$["payload"]["maximumBudgetUnits"]');
1379
+ const bidWindowMs = assertBoundedPositiveSafeInteger(payload.bidWindowMs, '$["payload"]["bidWindowMs"]', maximumBidWindowMs);
1380
+ const acceptanceWindowMs = assertBoundedPositiveSafeInteger(payload.acceptanceWindowMs, '$["payload"]["acceptanceWindowMs"]', maximumAcceptanceWindowMs);
1381
+ const maximumLeaseDuration = assertBoundedPositiveSafeInteger(payload.maximumLeaseDurationMs, '$["payload"]["maximumLeaseDurationMs"]', maximumLeaseDurationMs);
1382
+ const recoveryGraceMs = assertBoundedPositiveSafeInteger(payload.recoveryGraceMs, '$["payload"]["recoveryGraceMs"]', maximumRecoveryGraceMs);
1383
+ const maximumLeaseRenewalsValue = assertNonnegativeSafeInteger(payload.maximumLeaseRenewals, '$["payload"]["maximumLeaseRenewals"]');
1384
+ if (maximumLeaseRenewalsValue > maximumLeaseRenewals) {
1385
+ fail('invalid_payload', '$["payload"]["maximumLeaseRenewals"]');
1386
+ }
1387
+ const validFrom = assertRfc3339PayloadTimestamp(payload.validFrom, '$["payload"]["validFrom"]');
1388
+ const validUntil = assertRfc3339PayloadTimestamp(payload.validUntil, '$["payload"]["validUntil"]');
1389
+ const validityDuration = assertObjectiveValidity(validFrom.instant, validUntil.instant);
1390
+ for (const [path, timer] of [
1391
+ ['$["payload"]["bidWindowMs"]', bidWindowMs],
1392
+ ['$["payload"]["acceptanceWindowMs"]', acceptanceWindowMs],
1393
+ ['$["payload"]["maximumLeaseDurationMs"]', maximumLeaseDuration],
1394
+ ['$["payload"]["recoveryGraceMs"]', recoveryGraceMs],
1395
+ ]) {
1396
+ if (BigInt(timer) * 1000000n > validityDuration) {
1397
+ fail('invalid_payload', path);
1398
+ }
1399
+ }
1400
+ const fields = {
1401
+ objectiveDocumentId: assertIdentifier(payload.objectiveDocumentId, '$["payload"]["objectiveDocumentId"]', limits),
1402
+ objectiveId: assertIdentifier(payload.objectiveId, '$["payload"]["objectiveId"]', limits),
1403
+ objectiveRevision: assertPositiveSafeInteger(payload.objectiveRevision, '$["payload"]["objectiveRevision"]', 'invalid_payload'),
1404
+ issuerPeerId: assertIdentifier(payload.issuerPeerId, '$["payload"]["issuerPeerId"]', limits),
1405
+ successCriteria,
1406
+ permittedCapabilityKeys,
1407
+ maximumWorkItems,
1408
+ maximumConcurrentAssignments,
1409
+ maximumBudgetUnits,
1410
+ bidWindowMs,
1411
+ acceptanceWindowMs,
1412
+ maximumLeaseDurationMs: maximumLeaseDuration,
1413
+ recoveryGraceMs,
1414
+ maximumLeaseRenewals: maximumLeaseRenewalsValue,
1415
+ recoveryWitnessPeerIds,
1416
+ recoveryWitnessThreshold,
1417
+ validFrom: validFrom.text,
1418
+ validUntil: validUntil.text,
1419
+ ...(authorizedObserverPeerIds === undefined
1420
+ ? {}
1421
+ : { authorizedObserverPeerIds }),
1422
+ };
1423
+ if (summary !== undefined) {
1424
+ return { ...fields, summary };
1425
+ }
1426
+ if (contentReference === undefined) {
1427
+ return fail('invalid_payload', '$["payload"]');
1428
+ }
1429
+ return { ...fields, contentReference };
325
1430
  }
326
1431
  function validateProof(input, limits) {
327
1432
  const proof = assertClosedRecord(input, ['algorithm', 'keyId', 'value'], [], '$["proof"]', 'invalid_proof');
@@ -371,28 +1476,517 @@ function validateCriticalExtensions(input, extensions, limits) {
371
1476
  }
372
1477
  return result;
373
1478
  }
374
- function validateMessageSpecificEnvelope(type, audience, objectiveId, causationId) {
375
- if (type === 'peer.hello') {
1479
+ function validateMessageSpecificEnvelope(type, sender, audience, objectiveId, causationId, payload, sentAt, expiresAt) {
1480
+ if (payload.type === 'peer.card') {
1481
+ if (payload.subjectPeerId !== sender.peerId) {
1482
+ fail('invalid_payload', '$["payload"]["subjectPeerId"]');
1483
+ }
1484
+ if (payload.instanceId !== sender.instanceId) {
1485
+ fail('invalid_payload', '$["payload"]["instanceId"]');
1486
+ }
1487
+ }
1488
+ else if (payload.type === 'peer.goodbye' &&
1489
+ payload.instanceId !== sender.instanceId) {
1490
+ fail('invalid_payload', '$["payload"]["instanceId"]');
1491
+ }
1492
+ else if (payload.type === 'capability.advertise' &&
1493
+ payload.ownerPeerId !== sender.peerId) {
1494
+ fail('invalid_payload', '$["payload"]["ownerPeerId"]');
1495
+ }
1496
+ else if ((payload.type === 'objective.announce' ||
1497
+ payload.type === 'objective.revise') &&
1498
+ payload.issuerPeerId !== sender.peerId) {
1499
+ fail('invalid_payload', '$["payload"]["issuerPeerId"]');
1500
+ }
1501
+ else if (payload.type === 'work.offer' &&
1502
+ payload.ownerPeerId !== sender.peerId) {
1503
+ fail('invalid_payload', '$["payload"]["ownerPeerId"]');
1504
+ }
1505
+ else if (payload.type === 'work.bid' &&
1506
+ payload.bidderPeerId !== sender.peerId) {
1507
+ fail('invalid_payload', '$["payload"]["bidderPeerId"]');
1508
+ }
1509
+ else if (payload.type === 'work.award' &&
1510
+ payload.ownerPeerId !== sender.peerId) {
1511
+ fail('invalid_payload', '$["payload"]["ownerPeerId"]');
1512
+ }
1513
+ else if ((payload.type === 'work.accept' ||
1514
+ payload.type === 'work.decline' ||
1515
+ payload.type === 'work.progress' ||
1516
+ payload.type === 'work.checkpoint' ||
1517
+ payload.type === 'work.result' ||
1518
+ payload.type === 'lease.renew') &&
1519
+ payload.assigneePeerId !== sender.peerId) {
1520
+ fail('invalid_payload', '$["payload"]["assigneePeerId"]');
1521
+ }
1522
+ else if (payload.type === 'work.release') {
1523
+ if (payload.releaseAuthority === 'owner' &&
1524
+ payload.ownerPeerId !== sender.peerId) {
1525
+ fail('invalid_payload', '$["payload"]["ownerPeerId"]');
1526
+ }
1527
+ if (payload.releaseAuthority === 'assignee' &&
1528
+ payload.assigneePeerId !== sender.peerId) {
1529
+ fail('invalid_payload', '$["payload"]["assigneePeerId"]');
1530
+ }
1531
+ }
1532
+ else if (payload.type === 'work.cancel' &&
1533
+ payload.ownerPeerId !== sender.peerId) {
1534
+ fail('invalid_payload', '$["payload"]["ownerPeerId"]');
1535
+ }
1536
+ else if (payload.type === 'lease.takeover_proposal' &&
1537
+ payload.proposerPeerId !== sender.peerId) {
1538
+ fail('invalid_payload', '$["payload"]["proposerPeerId"]');
1539
+ }
1540
+ else if (payload.type === 'lease.vote' &&
1541
+ payload.witnessPeerId !== sender.peerId) {
1542
+ fail('invalid_payload', '$["payload"]["witnessPeerId"]');
1543
+ }
1544
+ else if (payload.type === 'lease.certificate' &&
1545
+ payload.certificateAssemblerPeerId !== sender.peerId) {
1546
+ fail('invalid_payload', '$["payload"]["certificateAssemblerPeerId"]');
1547
+ }
1548
+ if (type === 'peer.hello' ||
1549
+ type === 'peer.card' ||
1550
+ type === 'peer.goodbye') {
376
1551
  if (audience.kind === 'mesh' && audience.topic !== 'membership') {
377
1552
  fail('invalid_audience', '$["audience"]["topic"]');
378
1553
  }
379
- return;
380
1554
  }
381
- if (audience.kind !== 'peer') {
1555
+ else if (type === 'capability.advertise' ||
1556
+ type === 'capability.withdraw') {
1557
+ if (audience.kind === 'mesh' && audience.topic !== 'capability') {
1558
+ fail('invalid_audience', '$["audience"]["topic"]');
1559
+ }
1560
+ }
1561
+ else if (type === 'objective.announce' ||
1562
+ type === 'objective.revise' ||
1563
+ type === 'objective.cancel') {
1564
+ if (audience.kind === 'mesh' && audience.topic !== 'objective') {
1565
+ fail('invalid_audience', '$["audience"]["topic"]');
1566
+ }
1567
+ }
1568
+ else if (type === 'work.offer') {
1569
+ if (audience.kind === 'mesh' && audience.topic !== 'work') {
1570
+ fail('invalid_audience', '$["audience"]["topic"]');
1571
+ }
1572
+ }
1573
+ else if (type === 'work.bid') {
1574
+ if (audience.kind !== 'peer') {
1575
+ fail('invalid_audience', '$["audience"]');
1576
+ }
1577
+ if (audience.peerId !== payload.ownerPeerId) {
1578
+ fail('invalid_audience', '$["audience"]["peerId"]');
1579
+ }
1580
+ }
1581
+ else if (type === 'work.award' ||
1582
+ type === 'work.accept' ||
1583
+ type === 'work.decline' ||
1584
+ type === 'work.progress' ||
1585
+ type === 'work.checkpoint' ||
1586
+ type === 'work.result' ||
1587
+ type === 'work.release' ||
1588
+ type === 'work.cancel' ||
1589
+ type === 'lease.renew' ||
1590
+ type === 'lease.takeover_proposal' ||
1591
+ type === 'lease.vote' ||
1592
+ type === 'lease.certificate') {
1593
+ if (audience.kind !== 'peer') {
1594
+ fail('invalid_audience', '$["audience"]');
1595
+ }
1596
+ if (type === 'work.decline' &&
1597
+ audience.peerId !== payload.ownerPeerId) {
1598
+ fail('invalid_audience', '$["audience"]["peerId"]');
1599
+ }
1600
+ }
1601
+ else if (audience.kind !== 'peer') {
382
1602
  fail('invalid_audience', '$["audience"]');
383
1603
  }
384
- if (objectiveId !== undefined) {
1604
+ if (type !== 'peer.hello' &&
1605
+ type.startsWith('peer.') &&
1606
+ objectiveId !== undefined) {
385
1607
  fail('invalid_payload', '$["objectiveId"]');
386
1608
  }
387
- if (type === 'peer.ping_ack' && causationId === undefined) {
1609
+ if (type === 'peer.ping_ack' ||
1610
+ type === 'peer.goodbye' ||
1611
+ type === 'capability.withdraw' ||
1612
+ type === 'objective.cancel') {
1613
+ if (causationId === undefined) {
1614
+ fail('invalid_payload', '$["causationId"]');
1615
+ }
1616
+ }
1617
+ else if (type === 'peer.card' || type === 'capability.advertise') {
1618
+ const revision = payload.type === 'peer.card'
1619
+ ? payload.cardRevision
1620
+ : payload.capabilityRevision;
1621
+ if (revision === 1 && causationId !== undefined) {
1622
+ fail('invalid_payload', '$["causationId"]');
1623
+ }
1624
+ if (revision > 1 && causationId === undefined) {
1625
+ fail('invalid_payload', '$["causationId"]');
1626
+ }
1627
+ }
1628
+ else if (type === 'objective.announce') {
1629
+ if (causationId !== undefined) {
1630
+ fail('invalid_payload', '$["causationId"]');
1631
+ }
1632
+ }
1633
+ else if (type === 'objective.revise' && causationId === undefined) {
1634
+ fail('invalid_payload', '$["causationId"]');
1635
+ }
1636
+ else if (type === 'work.offer') {
1637
+ const offer = payload;
1638
+ if (offer.offerAttempt === 1 && causationId !== undefined) {
1639
+ fail('invalid_payload', '$["causationId"]');
1640
+ }
1641
+ if (offer.offerAttempt > 1 && causationId === undefined) {
1642
+ fail('invalid_payload', '$["causationId"]');
1643
+ }
1644
+ }
1645
+ else if ((type === 'work.bid' ||
1646
+ type === 'work.award' ||
1647
+ type === 'work.accept' ||
1648
+ type === 'work.decline' ||
1649
+ type === 'work.progress' ||
1650
+ type === 'work.checkpoint' ||
1651
+ type === 'work.result' ||
1652
+ type === 'work.release' ||
1653
+ type === 'work.cancel' ||
1654
+ type === 'lease.renew' ||
1655
+ type === 'lease.takeover_proposal' ||
1656
+ type === 'lease.vote' ||
1657
+ type === 'lease.certificate') &&
1658
+ causationId === undefined) {
388
1659
  fail('invalid_payload', '$["causationId"]');
389
1660
  }
1661
+ if (type === 'objective.announce' ||
1662
+ type === 'objective.revise' ||
1663
+ type === 'objective.cancel' ||
1664
+ type === 'work.offer' ||
1665
+ type === 'work.bid' ||
1666
+ type === 'work.award' ||
1667
+ type === 'work.accept' ||
1668
+ type === 'work.decline' ||
1669
+ type === 'work.progress' ||
1670
+ type === 'work.checkpoint' ||
1671
+ type === 'work.result' ||
1672
+ type === 'work.release' ||
1673
+ type === 'work.cancel' ||
1674
+ type === 'lease.renew' ||
1675
+ type === 'lease.takeover_proposal' ||
1676
+ type === 'lease.vote' ||
1677
+ type === 'lease.certificate') {
1678
+ if (objectiveId === undefined ||
1679
+ objectiveId !==
1680
+ payload.objectiveId) {
1681
+ fail('invalid_payload', '$["objectiveId"]');
1682
+ }
1683
+ }
1684
+ if (payload.type === 'work.offer') {
1685
+ validateWorkOfferTimes(payload, sentAt, expiresAt);
1686
+ }
1687
+ else if (payload.type === 'work.bid') {
1688
+ validateWorkBidTimes(payload, sentAt, expiresAt);
1689
+ }
1690
+ else if (payload.type === 'work.award') {
1691
+ validateWorkAwardTimes(payload, sentAt, expiresAt);
1692
+ }
1693
+ else if (payload.type === 'work.accept' ||
1694
+ payload.type === 'work.decline') {
1695
+ validateWorkAssignmentResponseTimes(payload, sentAt, expiresAt);
1696
+ }
1697
+ else if (payload.type === 'work.progress' ||
1698
+ payload.type === 'work.checkpoint' ||
1699
+ payload.type === 'work.result' ||
1700
+ payload.type === 'lease.renew') {
1701
+ validateWorkExecutionTimes(payload, sentAt, expiresAt);
1702
+ }
1703
+ else if (payload.type === 'work.release' &&
1704
+ payload.releaseAuthority === 'assignee') {
1705
+ validateWorkExecutionTimes(payload, sentAt, expiresAt);
1706
+ }
1707
+ }
1708
+ function validateWorkOfferTimes(payload, sentAt, expiresAt) {
1709
+ const bidDeadline = parseRfc3339(payload.bidDeadline, '$["payload"]["bidDeadline"]');
1710
+ const workDeadline = parseRfc3339(payload.workDeadline, '$["payload"]["workDeadline"]');
1711
+ if (bidDeadline <= sentAt) {
1712
+ fail('invalid_payload', '$["payload"]["bidDeadline"]');
1713
+ }
1714
+ if (workDeadline <= bidDeadline) {
1715
+ fail('invalid_payload', '$["payload"]["workDeadline"]');
1716
+ }
1717
+ if (bidDeadline - sentAt > BigInt(maximumWorkBidWindowMs) * 1000000n) {
1718
+ fail('invalid_payload', '$["payload"]["bidDeadline"]');
1719
+ }
1720
+ if (workDeadline - sentAt > BigInt(maximumWorkDeadlineMs) * 1000000n) {
1721
+ fail('invalid_payload', '$["payload"]["workDeadline"]');
1722
+ }
1723
+ if (expiresAt > bidDeadline) {
1724
+ fail('invalid_lifetime', '$["expiresAt"]');
1725
+ }
1726
+ }
1727
+ function validateWorkBidTimes(payload, sentAt, expiresAt) {
1728
+ const bidExpiresAt = parseRfc3339(payload.bidExpiresAt, '$["payload"]["bidExpiresAt"]');
1729
+ const bidDeadline = parseRfc3339(payload.bidDeadline, '$["payload"]["bidDeadline"]');
1730
+ const expectedCompletionAt = parseRfc3339(payload.expectedCompletionAt, '$["payload"]["expectedCompletionAt"]');
1731
+ const workDeadline = parseRfc3339(payload.workDeadline, '$["payload"]["workDeadline"]');
1732
+ if (bidExpiresAt <= sentAt) {
1733
+ fail('invalid_payload', '$["payload"]["bidExpiresAt"]');
1734
+ }
1735
+ if (bidExpiresAt > bidDeadline) {
1736
+ fail('invalid_payload', '$["payload"]["bidExpiresAt"]');
1737
+ }
1738
+ if (bidDeadline >= expectedCompletionAt) {
1739
+ fail('invalid_payload', '$["payload"]["expectedCompletionAt"]');
1740
+ }
1741
+ if (expectedCompletionAt > workDeadline) {
1742
+ fail('invalid_payload', '$["payload"]["expectedCompletionAt"]');
1743
+ }
1744
+ if (bidDeadline - sentAt > BigInt(maximumWorkBidWindowMs) * 1000000n) {
1745
+ fail('invalid_payload', '$["payload"]["bidDeadline"]');
1746
+ }
1747
+ if (workDeadline - sentAt > BigInt(maximumWorkDeadlineMs) * 1000000n) {
1748
+ fail('invalid_payload', '$["payload"]["workDeadline"]');
1749
+ }
1750
+ if (expiresAt > bidExpiresAt) {
1751
+ fail('invalid_lifetime', '$["expiresAt"]');
1752
+ }
1753
+ }
1754
+ function validateWorkAwardTimes(payload, sentAt, expiresAt) {
1755
+ const leaseStartsAt = parseRfc3339(payload.leaseStartsAt, '$["payload"]["leaseStartsAt"]');
1756
+ const acceptanceDeadline = parseRfc3339(payload.acceptanceDeadline, '$["payload"]["acceptanceDeadline"]');
1757
+ const leaseExpiresAt = parseRfc3339(payload.leaseExpiresAt, '$["payload"]["leaseExpiresAt"]');
1758
+ const workDeadline = parseRfc3339(payload.workDeadline, '$["payload"]["workDeadline"]');
1759
+ if (leaseStartsAt < sentAt) {
1760
+ fail('invalid_payload', '$["payload"]["leaseStartsAt"]');
1761
+ }
1762
+ if (acceptanceDeadline <= leaseStartsAt) {
1763
+ fail('invalid_payload', '$["payload"]["acceptanceDeadline"]');
1764
+ }
1765
+ if (leaseExpiresAt < acceptanceDeadline) {
1766
+ fail('invalid_payload', '$["payload"]["leaseExpiresAt"]');
1767
+ }
1768
+ if (workDeadline < leaseExpiresAt) {
1769
+ fail('invalid_payload', '$["payload"]["workDeadline"]');
1770
+ }
1771
+ if (acceptanceDeadline - sentAt >
1772
+ BigInt(maximumAcceptanceWindowMs) * 1000000n) {
1773
+ fail('invalid_payload', '$["payload"]["acceptanceDeadline"]');
1774
+ }
1775
+ if (leaseExpiresAt - leaseStartsAt >
1776
+ BigInt(maximumLeaseDurationMs) * 1000000n) {
1777
+ fail('invalid_payload', '$["payload"]["leaseExpiresAt"]');
1778
+ }
1779
+ if (workDeadline - sentAt > BigInt(maximumWorkDeadlineMs) * 1000000n) {
1780
+ fail('invalid_payload', '$["payload"]["workDeadline"]');
1781
+ }
1782
+ if (expiresAt > acceptanceDeadline) {
1783
+ fail('invalid_lifetime', '$["expiresAt"]');
1784
+ }
1785
+ }
1786
+ function validateWorkAssignmentResponseTimes(payload, sentAt, expiresAt) {
1787
+ const acceptanceDeadline = parseRfc3339(payload.acceptanceDeadline, '$["payload"]["acceptanceDeadline"]');
1788
+ if (sentAt >= acceptanceDeadline) {
1789
+ fail('invalid_payload', '$["payload"]["acceptanceDeadline"]');
1790
+ }
1791
+ if (expiresAt > acceptanceDeadline) {
1792
+ fail('invalid_lifetime', '$["expiresAt"]');
1793
+ }
1794
+ }
1795
+ function validateWorkExecutionTimes(payload, sentAt, expiresAt) {
1796
+ const leaseExpiresAt = parseRfc3339(payload.leaseExpiresAt, '$["payload"]["leaseExpiresAt"]');
1797
+ if (sentAt >= leaseExpiresAt) {
1798
+ fail('invalid_payload', '$["payload"]["leaseExpiresAt"]');
1799
+ }
1800
+ if (expiresAt > leaseExpiresAt) {
1801
+ fail('invalid_lifetime', '$["expiresAt"]');
1802
+ }
1803
+ }
1804
+ function validateRevisionPredecessor(revision, predecessor, path) {
1805
+ if (revision === 1 && predecessor !== undefined) {
1806
+ fail('invalid_payload', path);
1807
+ }
1808
+ if (revision > 1 && predecessor === undefined) {
1809
+ fail('invalid_payload', path);
1810
+ }
1811
+ }
1812
+ function assertBoundedValidity(validFrom, validUntil) {
1813
+ if (validUntil <= validFrom) {
1814
+ fail('invalid_payload', '$["payload"]["validUntil"]');
1815
+ }
1816
+ if (validUntil - validFrom >
1817
+ BigInt(maximumAdvertisementValidityMs) * 1000000n) {
1818
+ fail('invalid_payload', '$["payload"]["validUntil"]');
1819
+ }
1820
+ }
1821
+ function assertObjectiveValidity(validFrom, validUntil) {
1822
+ if (validUntil <= validFrom) {
1823
+ fail('invalid_payload', '$["payload"]["validUntil"]');
1824
+ }
1825
+ const duration = validUntil - validFrom;
1826
+ if (duration > BigInt(maximumObjectiveValidityMs) * 1000000n) {
1827
+ fail('invalid_payload', '$["payload"]["validUntil"]');
1828
+ }
1829
+ return duration;
1830
+ }
1831
+ function assertRfc3339PayloadTimestamp(input, path) {
1832
+ const text = assertString(input, path, 'invalid_payload');
1833
+ try {
1834
+ return { text, instant: parseRfc3339(text, path) };
1835
+ }
1836
+ catch (error) {
1837
+ if (error instanceof ValidationFailure) {
1838
+ fail('invalid_payload', path);
1839
+ }
1840
+ throw error;
1841
+ }
1842
+ }
1843
+ function validateProtocolVersions(input) {
1844
+ const path = '$["payload"]["protocolVersions"]';
1845
+ if (!Array.isArray(input) ||
1846
+ input.length === 0 ||
1847
+ input.length > maximumProtocolVersions) {
1848
+ fail('invalid_payload', path);
1849
+ }
1850
+ let previous;
1851
+ let includesCurrentWireVersion = false;
1852
+ const result = [];
1853
+ for (const [index, value] of input.entries()) {
1854
+ if (typeof value !== 'number' ||
1855
+ !Number.isSafeInteger(value) ||
1856
+ value < 0 ||
1857
+ (previous !== undefined && value <= previous)) {
1858
+ fail('invalid_payload', `${path}[${index}]`);
1859
+ }
1860
+ if (value === MESH_WIRE_VERSION)
1861
+ includesCurrentWireVersion = true;
1862
+ previous = value;
1863
+ result.push(value);
1864
+ }
1865
+ if (!includesCurrentWireVersion) {
1866
+ fail('invalid_payload', path);
1867
+ }
1868
+ return result;
1869
+ }
1870
+ function validateIdentifierArray(input, path, maximumItems, limits) {
1871
+ if (!Array.isArray(input) || input.length > maximumItems) {
1872
+ fail('invalid_payload', path);
1873
+ }
1874
+ let previous;
1875
+ const result = [];
1876
+ for (const [index, value] of input.entries()) {
1877
+ const itemPath = `${path}[${index}]`;
1878
+ const identifier = assertIdentifier(value, itemPath, limits);
1879
+ if (previous !== undefined &&
1880
+ compareUtf16CodeUnits(identifier, previous) !== 1) {
1881
+ fail('invalid_payload', itemPath);
1882
+ }
1883
+ previous = identifier;
1884
+ result.push(identifier);
1885
+ }
1886
+ return result;
1887
+ }
1888
+ function validateBoundedStringArray(input, path, maximumItems, maximumItemBytes, maximumAggregateBytes, sortedUnique = false) {
1889
+ if (!Array.isArray(input) || input.length > maximumItems) {
1890
+ fail('invalid_payload', path);
1891
+ }
1892
+ let aggregateBytes = 0;
1893
+ let previous;
1894
+ const result = [];
1895
+ for (const [index, value] of input.entries()) {
1896
+ const itemPath = `${path}[${index}]`;
1897
+ const item = assertBoundedString(value, itemPath, maximumItemBytes);
1898
+ if (sortedUnique &&
1899
+ previous !== undefined &&
1900
+ compareUtf16CodeUnits(item, previous) !== 1) {
1901
+ fail('invalid_payload', itemPath);
1902
+ }
1903
+ aggregateBytes += utf8Encoder.encode(item).byteLength;
1904
+ if (maximumAggregateBytes !== undefined &&
1905
+ aggregateBytes > maximumAggregateBytes) {
1906
+ fail('invalid_payload', path);
1907
+ }
1908
+ previous = item;
1909
+ result.push(item);
1910
+ }
1911
+ return result;
1912
+ }
1913
+ /**
1914
+ * Compares raw UTF-16 code units lexicographically, matching JavaScript string
1915
+ * relational ordering and the property-name ordering used by JCS/RFC 8785.
1916
+ */
1917
+ function compareUtf16CodeUnits(left, right) {
1918
+ const sharedLength = Math.min(left.length, right.length);
1919
+ for (let index = 0; index < sharedLength; index += 1) {
1920
+ const leftCodeUnit = left.charCodeAt(index);
1921
+ const rightCodeUnit = right.charCodeAt(index);
1922
+ if (leftCodeUnit < rightCodeUnit)
1923
+ return -1;
1924
+ if (leftCodeUnit > rightCodeUnit)
1925
+ return 1;
1926
+ }
1927
+ if (left.length < right.length)
1928
+ return -1;
1929
+ if (left.length > right.length)
1930
+ return 1;
1931
+ return 0;
1932
+ }
1933
+ function validateAttributes(input, path = '$["payload"]["attributes"]') {
1934
+ const attributes = assertRecord(input, path, 'invalid_payload');
1935
+ const keys = Object.keys(attributes);
1936
+ if (keys.length > maximumAttributes) {
1937
+ fail('invalid_payload', path);
1938
+ }
1939
+ let aggregateBytes = 0;
1940
+ const result = {};
1941
+ for (const key of keys) {
1942
+ const keyPath = `${path}[${JSON.stringify(key)}]`;
1943
+ if (key.length === 0 ||
1944
+ utf8Encoder.encode(key).byteLength > maximumAttributeKeyBytes) {
1945
+ fail('invalid_payload', keyPath);
1946
+ }
1947
+ const value = assertBoundedString(attributes[key], keyPath, maximumAttributeValueBytes);
1948
+ aggregateBytes +=
1949
+ utf8Encoder.encode(key).byteLength + utf8Encoder.encode(value).byteLength;
1950
+ if (aggregateBytes > maximumAttributesBytes) {
1951
+ fail('invalid_payload', path);
1952
+ }
1953
+ Object.defineProperty(result, key, {
1954
+ value,
1955
+ enumerable: true,
1956
+ configurable: true,
1957
+ writable: true,
1958
+ });
1959
+ }
1960
+ return result;
1961
+ }
1962
+ function assertBoundedString(input, path, maximumBytes) {
1963
+ const value = assertString(input, path, 'invalid_payload');
1964
+ if (value.length === 0 ||
1965
+ utf8Encoder.encode(value).byteLength > maximumBytes) {
1966
+ fail('invalid_payload', path);
1967
+ }
1968
+ return value;
390
1969
  }
391
1970
  function validateLifetime(type, sentAt, expiresAt, limits) {
392
1971
  if (expiresAt <= sentAt) {
393
1972
  fail('invalid_lifetime', '$["expiresAt"]');
394
1973
  }
395
- const messageMaximum = type === 'peer.hello' ? 120_000 : 30_000;
1974
+ const messageMaximum = type === 'peer.ping' || type === 'peer.ping_ack'
1975
+ ? 30_000
1976
+ : type === 'peer.goodbye' ||
1977
+ type === 'lease.takeover_proposal' ||
1978
+ type === 'lease.vote' ||
1979
+ type === 'lease.certificate'
1980
+ ? 60_000
1981
+ : type === 'objective.announce' || type === 'objective.revise'
1982
+ ? 5 * 60_000
1983
+ : type === 'work.progress' ||
1984
+ type === 'work.checkpoint' ||
1985
+ type === 'work.result'
1986
+ ? maximumWorkExecutionLifetimeMs
1987
+ : type === 'lease.renew'
1988
+ ? 30_000
1989
+ : 120_000;
396
1990
  const maximum = Math.min(limits.maximumLifetimeMs, messageMaximum);
397
1991
  if (expiresAt - sentAt > BigInt(maximum) * 1000000n) {
398
1992
  fail('invalid_lifetime', '$["expiresAt"]');
@@ -415,6 +2009,14 @@ function assertPayloadHash(input, path) {
415
2009
  }
416
2010
  return value;
417
2011
  }
2012
+ function assertContentDigest(input, path) {
2013
+ const value = assertString(input, path, 'invalid_payload');
2014
+ if (!value.startsWith('sha256:') ||
2015
+ !isCanonicalBase64Url(value.slice('sha256:'.length), 32)) {
2016
+ fail('invalid_payload', path);
2017
+ }
2018
+ return value;
2019
+ }
418
2020
  function assertMessageId(input, path) {
419
2021
  const value = assertString(input, path, 'invalid_message_id');
420
2022
  if (!isCanonicalBase64Url(value, 16)) {
@@ -435,6 +2037,19 @@ function assertPositiveSafeInteger(input, path, code = 'invalid_sequence') {
435
2037
  }
436
2038
  return input;
437
2039
  }
2040
+ function assertNonnegativeSafeInteger(input, path) {
2041
+ if (typeof input !== 'number' || !Number.isSafeInteger(input) || input < 0) {
2042
+ fail('invalid_payload', path);
2043
+ }
2044
+ return input;
2045
+ }
2046
+ function assertBoundedPositiveSafeInteger(input, path, maximum) {
2047
+ const value = assertPositiveSafeInteger(input, path, 'invalid_payload');
2048
+ if (value > maximum) {
2049
+ fail('invalid_payload', path);
2050
+ }
2051
+ return value;
2052
+ }
438
2053
  function assertString(input, path, code = 'invalid_payload') {
439
2054
  if (typeof input !== 'string')
440
2055
  fail(code, path);
@@ -535,8 +2150,31 @@ function isCanonicalBase64Url(value, expectedBytes) {
535
2150
  const unusedBits = 6 - significantBits;
536
2151
  return (finalIndex & ((1 << unusedBits) - 1)) === 0;
537
2152
  }
538
- function isAlphaOneMessageType(value) {
539
- return (value === 'peer.hello' || value === 'peer.ping' || value === 'peer.ping_ack');
2153
+ function isImplementedMessageType(value) {
2154
+ return (value === 'peer.hello' ||
2155
+ value === 'peer.card' ||
2156
+ value === 'peer.ping' ||
2157
+ value === 'peer.ping_ack' ||
2158
+ value === 'peer.goodbye' ||
2159
+ value === 'capability.advertise' ||
2160
+ value === 'capability.withdraw' ||
2161
+ value === 'objective.announce' ||
2162
+ value === 'objective.revise' ||
2163
+ value === 'objective.cancel' ||
2164
+ value === 'work.offer' ||
2165
+ value === 'work.bid' ||
2166
+ value === 'work.award' ||
2167
+ value === 'work.accept' ||
2168
+ value === 'work.decline' ||
2169
+ value === 'work.progress' ||
2170
+ value === 'work.checkpoint' ||
2171
+ value === 'work.result' ||
2172
+ value === 'work.release' ||
2173
+ value === 'work.cancel' ||
2174
+ value === 'lease.renew' ||
2175
+ value === 'lease.takeover_proposal' ||
2176
+ value === 'lease.vote' ||
2177
+ value === 'lease.certificate');
540
2178
  }
541
2179
  function canonicalizeMeshJsonInternal(input, options) {
542
2180
  const limits = resolveLimits(options.limits);