@hyperscale0/udl 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +5 -1
  3. package/conformance/invalid/invalid-journeys.expected.json +3 -19
  4. package/conformance/invalid/invalid-journeys.udl +47 -49
  5. package/conformance/valid/attested.expected.json +6 -0
  6. package/conformance/valid/attested.udl +251 -0
  7. package/conformance/valid/hand-edited.expected.json +1 -1
  8. package/conformance/valid/hand-edited.udl +1 -1
  9. package/conformance/valid/minimal.expected.json +1 -1
  10. package/conformance/valid/minimal.udl +0 -15
  11. package/conformance/valid/vocabulary.expected.json +6 -0
  12. package/conformance/valid/vocabulary.udl +1999 -0
  13. package/dist/allocation.d.ts +60 -0
  14. package/dist/allocation.d.ts.map +1 -0
  15. package/dist/allocation.js +177 -0
  16. package/dist/allocation.js.map +1 -0
  17. package/dist/diagnostics.d.ts +1 -31
  18. package/dist/diagnostics.d.ts.map +1 -1
  19. package/dist/diagnostics.js +0 -30
  20. package/dist/diagnostics.js.map +1 -1
  21. package/dist/distribution.d.ts +15 -0
  22. package/dist/distribution.d.ts.map +1 -0
  23. package/dist/distribution.js +49 -0
  24. package/dist/distribution.js.map +1 -0
  25. package/dist/effects.d.ts.map +1 -1
  26. package/dist/effects.js +23 -1
  27. package/dist/effects.js.map +1 -1
  28. package/dist/evolution.d.ts +12 -0
  29. package/dist/evolution.d.ts.map +1 -1
  30. package/dist/evolution.js +42 -1
  31. package/dist/evolution.js.map +1 -1
  32. package/dist/finance.d.ts +18 -1
  33. package/dist/finance.d.ts.map +1 -1
  34. package/dist/finance.js +158 -27
  35. package/dist/finance.js.map +1 -1
  36. package/dist/index.d.ts +8 -2
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +5 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/instrument-references.d.ts +5 -0
  41. package/dist/instrument-references.d.ts.map +1 -0
  42. package/dist/instrument-references.js +69 -0
  43. package/dist/instrument-references.js.map +1 -0
  44. package/dist/limits.d.ts +3 -3
  45. package/dist/limits.d.ts.map +1 -1
  46. package/dist/limits.js +3 -7
  47. package/dist/limits.js.map +1 -1
  48. package/dist/reference.d.ts +3 -0
  49. package/dist/reference.d.ts.map +1 -0
  50. package/dist/reference.js +28 -0
  51. package/dist/reference.js.map +1 -0
  52. package/dist/schema.d.ts +1232 -83
  53. package/dist/schema.d.ts.map +1 -1
  54. package/dist/schema.js +398 -60
  55. package/dist/schema.js.map +1 -1
  56. package/dist/validation.d.ts +14 -0
  57. package/dist/validation.d.ts.map +1 -1
  58. package/dist/validation.js +75 -131
  59. package/dist/validation.js.map +1 -1
  60. package/dist/vocabulary.d.ts +23 -0
  61. package/dist/vocabulary.d.ts.map +1 -0
  62. package/dist/vocabulary.js +965 -0
  63. package/dist/vocabulary.js.map +1 -0
  64. package/docs/README.md +2 -1
  65. package/docs/funding-custody.md +165 -0
  66. package/docs/guide/09-schedules-and-allocation.md +130 -0
  67. package/docs/llms-full.txt +620 -101
  68. package/docs/llms.txt +1 -1
  69. package/docs/reference/clauses.md +451 -63
  70. package/docs/reference/cli.md +3 -1
  71. package/docs/reference/diagnostics.md +33 -38
  72. package/package.json +5 -6
  73. package/spec/udl.schema.json +1095 -118
  74. package/src/allocation.ts +259 -0
  75. package/src/diagnostics.ts +0 -32
  76. package/src/distribution.ts +61 -0
  77. package/src/effects.ts +27 -1
  78. package/src/evolution.ts +63 -3
  79. package/src/finance.ts +218 -24
  80. package/src/index.ts +30 -3
  81. package/src/instrument-references.ts +98 -0
  82. package/src/limits.ts +3 -7
  83. package/src/reference.ts +31 -0
  84. package/src/schema.ts +417 -66
  85. package/src/validation.ts +112 -182
  86. package/src/vocabulary.ts +1508 -0
package/src/schema.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { referencePatternPrefix } from "./reference.js";
1
2
  import { z } from "zod";
2
3
 
3
4
  import { udlCheckEvidenceProfiles } from "./check-profiles.js";
@@ -24,6 +25,9 @@ const eventNamePattern = /^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+$/;
24
25
  const udlSnakeCaseSchema = z
25
26
  .string()
26
27
  .regex(snakeCasePattern, "must be a snake_case identifier");
28
+ const udlInstrumentIdSchema = udlSnakeCaseSchema.meta({
29
+ "x-udl-reference": "instrument",
30
+ });
27
31
  const udlActionNameSchema = z
28
32
  .string()
29
33
  .regex(snakeCasePattern, "must be a snake_case action identifier");
@@ -43,14 +47,6 @@ export const udlInstrumentActionIdSchema = z
43
47
  "must name an instrument action as instrument_id.action_key",
44
48
  );
45
49
 
46
- const udlJourneyOperationNameSchema = z
47
- .string()
48
- .max(160)
49
- .regex(
50
- /^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+$/,
51
- "must name a dotted operation",
52
- );
53
-
54
50
  const nonEmptyTextSchema = z
55
51
  .string()
56
52
  .refine((value) => value.trim().length > 0, "must not be blank");
@@ -111,20 +107,6 @@ const udlExampleSchema = z.strictObject({
111
107
  output: z.json().optional(),
112
108
  });
113
109
 
114
- const udlJourneyStepSchema = z.strictObject({
115
- bind: z.record(fieldPathSchema, udlSnakeCaseSchema),
116
- example: udlSnakeCaseSchema,
117
- id: udlSnakeCaseSchema.optional(),
118
- operation: udlJourneyOperationNameSchema,
119
- });
120
-
121
- export const udlJourneySchema = z.strictObject({
122
- id: udlSnakeCaseSchema,
123
- label: nonEmptyTextSchema,
124
- steps: z.array(udlJourneyStepSchema).min(1),
125
- summary: nonEmptyTextSchema,
126
- });
127
-
128
110
  const udlLifecycleTransitionSchema = z.strictObject({
129
111
  from: z.array(udlSnakeCaseSchema).min(1),
130
112
  to: udlSnakeCaseSchema,
@@ -150,10 +132,28 @@ const udlDateComparisonSchema = z.strictObject({
150
132
  referencedPath: fieldPathSchema,
151
133
  });
152
134
 
135
+ const udlStoredFieldSchema = z.strictObject({ field: udlFieldNameSchema });
136
+ const udlOffsetSchema = z.union([nonEmptyTextSchema, udlStoredFieldSchema]);
137
+
138
+ const udlAttestationSchema = z.strictObject({
139
+ forAction: udlActionNameSchema.optional(),
140
+ action: instanceValuePathSchema,
141
+ digest: instanceValuePathSchema,
142
+ role: instanceValuePathSchema,
143
+ expiresAt: instanceValuePathSchema,
144
+ instrument: instanceValuePathSchema,
145
+ party: z.string().regex(/^[a-z][A-Za-z0-9_]*$/),
146
+ consume: udlActionNameSchema,
147
+ });
148
+
153
149
  const udlGateSchema = z.strictObject({
150
+ attests: udlAttestationSchema.optional(),
154
151
  /** Local field key <- referenced instance path; create actions only. */
155
152
  bind: z.record(udlFieldNameSchema, fieldPathSchema).optional(),
156
153
  dateComparison: udlDateComparisonSchema.optional(),
154
+ dueBefore: z
155
+ .strictObject({ field: udlFieldNameSchema, offset: nonEmptyTextSchema })
156
+ .optional(),
157
157
  field: udlFieldNameSchema,
158
158
  /** Local instance path === referenced instance path at admission. */
159
159
  match: z.record(fieldPathSchema, fieldPathSchema).optional(),
@@ -161,7 +161,15 @@ const udlGateSchema = z.strictObject({
161
161
  optional: z.literal(true).optional(),
162
162
  statuses: z.array(udlSnakeCaseSchema).min(1),
163
163
  /** One dependent ever per referenced instance; create actions only. */
164
- unique: z.literal(true).optional(),
164
+ unique: z
165
+ .union([
166
+ z.literal(true),
167
+ z.strictObject({
168
+ namespace: udlSnakeCaseSchema,
169
+ byFields: z.array(udlFieldNameSchema).min(1).max(8),
170
+ }),
171
+ ])
172
+ .optional(),
165
173
  });
166
174
 
167
175
  const udlBindingSchema = z.discriminatedUnion("from", [
@@ -219,7 +227,7 @@ const udlDueRecurrenceSchema = z.strictObject({
219
227
  });
220
228
 
221
229
  const udlDueParentStatusSchema = z.strictObject({
222
- instrumentId: udlSnakeCaseSchema,
230
+ instrumentId: udlInstrumentIdSchema,
223
231
  refField: udlFieldNameSchema,
224
232
  statuses: z.array(udlSnakeCaseSchema).min(1),
225
233
  });
@@ -227,13 +235,13 @@ const udlDueParentStatusSchema = z.strictObject({
227
235
  const udlDueSchema = z.strictObject({
228
236
  every: udlDueRecurrenceSchema.optional(),
229
237
  field: udlFieldNameSchema,
230
- offset: nonEmptyTextSchema.optional(),
238
+ offset: udlOffsetSchema.optional(),
231
239
  whenParentStatus: udlDueParentStatusSchema.optional(),
232
240
  });
233
241
 
234
242
  const udlDeadlineSchema = z.strictObject({
235
243
  field: udlFieldNameSchema,
236
- offset: nonEmptyTextSchema.optional(),
244
+ offset: udlOffsetSchema.optional(),
237
245
  });
238
246
 
239
247
  const udlSetsAtSchema = z.strictObject({
@@ -352,6 +360,31 @@ const udlAggregateCheckSchema = z.discriminatedUnion("kind", [
352
360
  kind: z.literal("count_at_least"),
353
361
  targetField: udlFieldNameSchema,
354
362
  }),
363
+ z.strictObject({
364
+ kind: z.literal("count_exactly"),
365
+ value: z.number().int().min(0),
366
+ }),
367
+ z.strictObject({
368
+ kind: z.literal("ordered"),
369
+ field: udlFieldNameSchema,
370
+ positionField: udlFieldNameSchema,
371
+ }),
372
+ z.strictObject({
373
+ kind: z.literal("schedule"),
374
+ positionField: udlFieldNameSchema,
375
+ dateField: udlFieldNameSchema,
376
+ datesField: udlFieldNameSchema,
377
+ amounts: z
378
+ .array(
379
+ z.strictObject({
380
+ amountField: udlFieldNameSchema,
381
+ totalField: udlFieldNameSchema,
382
+ }),
383
+ )
384
+ .min(1)
385
+ .max(8),
386
+ remainder: z.literal("first"),
387
+ }),
355
388
  z.strictObject({ kind: z.literal("all_in") }),
356
389
  z.strictObject({
357
390
  field: udlFieldNameSchema,
@@ -360,19 +393,29 @@ const udlAggregateCheckSchema = z.discriminatedUnion("kind", [
360
393
  ]);
361
394
 
362
395
  const udlAggregateConditionSchema = z.strictObject({
396
+ anchorField: udlFieldNameSchema.optional(),
397
+ dueBefore: z
398
+ .strictObject({
399
+ field: udlFieldNameSchema,
400
+ offset: udlOffsetSchema.optional(),
401
+ })
402
+ .optional(),
363
403
  check: udlAggregateCheckSchema,
364
- instrumentId: udlSnakeCaseSchema.optional(),
404
+ instrumentId: udlInstrumentIdSchema.optional(),
365
405
  over: z.enum(["children", "siblings"]),
366
406
  refField: udlFieldNameSchema,
367
407
  statuses: z.array(udlSnakeCaseSchema).min(1),
368
408
  });
369
409
 
370
410
  const udlExposureRequirementSchema = z.strictObject({
411
+ groupField: udlFieldNameSchema.optional(),
412
+ minimumField: udlFieldNameSchema.optional(),
413
+ measure: z.strictObject({ allocation: udlSnakeCaseSchema }).optional(),
371
414
  amountField: udlFieldNameSchema,
372
415
  anchorField: udlFieldNameSchema,
373
416
  capField: udlFieldNameSchema,
374
417
  capOnAnchor: z.literal(true).optional(),
375
- childInstrumentId: udlSnakeCaseSchema,
418
+ childInstrumentId: udlInstrumentIdSchema,
376
419
  statuses: z.array(udlSnakeCaseSchema).min(1),
377
420
  });
378
421
 
@@ -383,6 +426,7 @@ const udlPartyRoleSchema = z.string().regex(/^[a-z][A-Za-z0-9_]*$/);
383
426
 
384
427
  const udlPortSchema = z.strictObject({
385
428
  allowedParties: z.array(udlPartyRoleSchema).min(1),
429
+ capture: udlFieldNameSchema.optional(),
386
430
  });
387
431
 
388
432
  const udlPayoutSchema = z.strictObject({
@@ -421,7 +465,7 @@ const udlReconcileSchema = z.strictObject({
421
465
  */
422
466
  exception: z.strictObject({
423
467
  amountField: udlFieldNameSchema,
424
- childInstrumentId: udlSnakeCaseSchema,
468
+ childInstrumentId: udlInstrumentIdSchema,
425
469
  maxOpen: z.number().int().min(1).max(1_000),
426
470
  reasonField: udlFieldNameSchema,
427
471
  refField: udlFieldNameSchema,
@@ -449,7 +493,7 @@ const udlReconcileSchema = z.strictObject({
449
493
 
450
494
  const udlSignedSumSourceSchema = z.strictObject({
451
495
  amountField: udlFieldNameSchema,
452
- instrumentId: udlSnakeCaseSchema,
496
+ instrumentId: udlInstrumentIdSchema,
453
497
  refField: udlFieldNameSchema,
454
498
  sign: z.enum(["add", "subtract"]),
455
499
  statuses: z.array(udlSnakeCaseSchema).min(1),
@@ -477,7 +521,7 @@ const udlDistributeSchema = z.strictObject({
477
521
 
478
522
  const udlRemainderCollectedSchema = z.strictObject({
479
523
  amountField: udlFieldNameSchema,
480
- instrumentId: udlSnakeCaseSchema,
524
+ instrumentId: udlInstrumentIdSchema,
481
525
  path: z.literal("refs").optional(),
482
526
  refField: udlFieldNameSchema,
483
527
  statuses: z.array(udlSnakeCaseSchema).min(1),
@@ -490,6 +534,7 @@ const udlRemainderSchema = z.strictObject({
490
534
  inputKey: udlFieldNameSchema.optional(),
491
535
  onZero: z.enum(["refuse", "skip_steps"]),
492
536
  totalPath: instanceValuePathSchema,
537
+ subtractPaths: z.array(instanceValuePathSchema).min(1).max(16).optional(),
493
538
  });
494
539
 
495
540
  type UdlCheckRequirementShape = {
@@ -575,10 +620,16 @@ const udlPartitionSchema = z.strictObject({
575
620
  const udlDerivedAmountSchema = z.strictObject({
576
621
  field: udlFieldNameSchema,
577
622
  rounding: z.literal("floor"),
578
- rule: z.strictObject({
579
- bps: z.number().int().min(1).max(9_999),
580
- kind: z.literal("percentage_of"),
581
- }),
623
+ rule: z.discriminatedUnion("kind", [
624
+ z.strictObject({
625
+ bps: z.union([z.number().int().min(1).max(9_999), udlStoredFieldSchema]),
626
+ kind: z.literal("percentage_of"),
627
+ }),
628
+ z.strictObject({
629
+ kind: z.literal("minimum"),
630
+ capField: udlFieldNameSchema,
631
+ }),
632
+ ]),
582
633
  sourceField: udlFieldNameSchema,
583
634
  });
584
635
 
@@ -738,7 +789,171 @@ export const udlActionLibrarySchema = z.record(
738
789
  udlActionLibraryModuleSchema,
739
790
  );
740
791
 
792
+ const templateParametersSchema = z.record(
793
+ udlFieldNameSchema,
794
+ z.union([z.string(), z.number().int(), z.boolean()]),
795
+ );
796
+
797
+ const udlAllocationBucketSchema = z.strictObject({
798
+ key: z.enum(["principal", "profit", "cost", "fine"]),
799
+ source: z.union([
800
+ z.strictObject({
801
+ from: z.literal("slice"),
802
+ amountField: udlFieldNameSchema,
803
+ destinationField: udlFieldNameSchema,
804
+ }),
805
+ z.strictObject({
806
+ from: z.literal("children"),
807
+ instrumentId: udlInstrumentIdSchema,
808
+ refField: udlFieldNameSchema,
809
+ statuses: z.array(udlSnakeCaseSchema).min(1),
810
+ amountField: udlFieldNameSchema,
811
+ destinationField: udlFieldNameSchema,
812
+ }),
813
+ z.strictObject({
814
+ from: z.literal("children"),
815
+ template: udlSnakeCaseSchema,
816
+ parameters: templateParametersSchema,
817
+ refField: udlFieldNameSchema,
818
+ statuses: z.array(udlSnakeCaseSchema).min(1),
819
+ amountField: udlFieldNameSchema,
820
+ destinationField: udlFieldNameSchema,
821
+ }),
822
+ ]),
823
+ });
824
+ const udlAllocationSchema = z.strictObject({
825
+ sliceInstrumentId: udlInstrumentIdSchema,
826
+ sliceRefField: udlFieldNameSchema,
827
+ sliceStatuses: z.array(udlSnakeCaseSchema).min(1),
828
+ dueField: udlFieldNameSchema,
829
+ positionField: udlFieldNameSchema,
830
+ earningRuleField: udlFieldNameSchema,
831
+ buckets: z.array(udlAllocationBucketSchema).min(2).max(4),
832
+ });
833
+ const udlAllocateSchema = z.union([
834
+ z.strictObject({
835
+ refField: udlFieldNameSchema.optional(),
836
+ mode: z.literal("refund"),
837
+ action: udlActionNameSchema.optional(),
838
+ assessmentField: udlFieldNameSchema.optional(),
839
+ capture: udlFieldNameSchema,
840
+ }),
841
+ z.strictObject({
842
+ refField: udlFieldNameSchema,
843
+ mode: z.literal("payment"),
844
+ assessment: z.literal("self").optional(),
845
+ amountField: udlFieldNameSchema.optional(),
846
+ sourceAccountField: udlFieldNameSchema,
847
+ paymentIdentityField: udlFieldNameSchema,
848
+ capture: udlFieldNameSchema,
849
+ }),
850
+ z.strictObject({
851
+ refField: udlFieldNameSchema.optional(),
852
+ mode: z.literal("payoff"),
853
+ amountField: udlFieldNameSchema.optional(),
854
+ sourceAccountField: udlFieldNameSchema,
855
+ paymentIdentityField: udlFieldNameSchema,
856
+ capture: udlFieldNameSchema,
857
+ }),
858
+ z.strictObject({
859
+ refField: udlFieldNameSchema.optional(),
860
+ mode: z.literal("write_off"),
861
+ capture: udlFieldNameSchema,
862
+ }),
863
+ ]);
864
+ const udlContributionsSchema = z.strictObject({
865
+ field: udlFieldNameSchema,
866
+ amountKey: udlFieldNameSchema,
867
+ accountKey: udlFieldNameSchema,
868
+ totalField: udlFieldNameSchema,
869
+ });
870
+
871
+ // These clauses are opt-in. Absent clauses never add defaults to older documents.
872
+ const udlFundingSchema = z.strictObject({
873
+ obligationField: udlFieldNameSchema,
874
+ ticketInstrumentId: udlInstrumentIdSchema,
875
+ ticketRefField: udlFieldNameSchema,
876
+ ticketAmountField: udlFieldNameSchema,
877
+ ticketInvestorField: udlFieldNameSchema,
878
+ ticketAccountField: udlFieldNameSchema,
879
+ ticketStatus: udlSnakeCaseSchema,
880
+ collectAction: udlActionNameSchema,
881
+ principalField: udlFieldNameSchema,
882
+ sourceAccountPath: instanceValuePathSchema,
883
+ destinationAccountField: udlFieldNameSchema,
884
+ terms: z.record(udlFieldNameSchema, udlFieldNameSchema),
885
+ capture: udlFieldNameSchema,
886
+ });
887
+ const udlReceiptDistributionSchema = z.strictObject({
888
+ roundField: udlFieldNameSchema,
889
+ snapshotRef: udlFieldNameSchema,
890
+ receiptField: udlFieldNameSchema,
891
+ receiptPath: instanceValuePathSchema,
892
+ mode: z.enum(["cash", "loss"]),
893
+ feeBps: z.number().int().min(0).max(10000),
894
+ vatBps: z.number().int().min(0).max(10000),
895
+ feeAccountField: udlFieldNameSchema,
896
+ taxAccountField: udlFieldNameSchema,
897
+ residualAccountField: udlFieldNameSchema,
898
+ capture: udlFieldNameSchema,
899
+ });
900
+
901
+ const udlRequestAuthoritySchema = z.strictObject({
902
+ instrumentField: udlFieldNameSchema,
903
+ instanceField: udlFieldNameSchema,
904
+ actionField: udlFieldNameSchema,
905
+ inputField: udlFieldNameSchema,
906
+ digestField: udlFieldNameSchema,
907
+ roleField: udlFieldNameSchema,
908
+ party: udlPartyRoleSchema,
909
+ expiresField: udlFieldNameSchema,
910
+ });
911
+
741
912
  const udlActionShape = {
913
+ requestAuthority: udlRequestAuthoritySchema.optional(),
914
+ funding: udlFundingSchema.optional(),
915
+ receiptDistribution: udlReceiptDistributionSchema.optional(),
916
+ requiresAllocation: z
917
+ .strictObject({
918
+ refField: udlFieldNameSchema.optional(),
919
+ slice: z.union([z.literal("self"), udlStoredFieldSchema]),
920
+ buckets: z
921
+ .array(z.enum(["principal", "profit", "cost", "fine"]))
922
+ .min(1)
923
+ .max(4),
924
+ check: z.enum(["settled", "outstanding"]),
925
+ })
926
+ .optional(),
927
+ unique: z
928
+ .strictObject({
929
+ namespace: udlSnakeCaseSchema,
930
+ byFields: z.array(udlFieldNameSchema).min(1).max(8),
931
+ })
932
+ .optional(),
933
+ requiresInput: z
934
+ .record(udlFieldNameSchema, instanceValuePathSchema)
935
+ .optional(),
936
+ engineOwned: z.literal(true).optional(),
937
+ captureEngine: z
938
+ .record(udlFieldNameSchema, z.enum(["operationId"]))
939
+ .optional(),
940
+ allocate: udlAllocateSchema.optional(),
941
+ contributionStage: z
942
+ .strictObject({
943
+ stage: z.enum(["fund", "refund"]),
944
+ accountPath: instanceValuePathSchema,
945
+ })
946
+ .optional(),
947
+ transitionsRefs: z
948
+ .array(
949
+ z.strictObject({
950
+ field: udlFieldNameSchema,
951
+ action: udlActionNameSchema,
952
+ }),
953
+ )
954
+ .min(1)
955
+ .max(16)
956
+ .optional(),
742
957
  agentDescription: udlAgentDescriptionSchema.optional(),
743
958
  calls: z.array(udlCallSchema).min(1).optional(),
744
959
  captureInput: z.record(udlFieldNameSchema, udlFieldNameSchema).optional(),
@@ -752,7 +967,11 @@ const udlActionShape = {
752
967
  due: udlDueSchema.optional(),
753
968
  earnable: z.boolean().optional(),
754
969
  effects: udlEffectsSchema.optional(),
755
- eventName: z.string().regex(eventNamePattern).optional(),
970
+ eventName: z
971
+ .string()
972
+ .regex(eventNamePattern)
973
+ .meta({ "x-udl-reference": "instrument_event" })
974
+ .optional(),
756
975
  examples: z.array(udlExampleSchema).min(1).optional(),
757
976
  input: jsonObjectSchema.optional(),
758
977
  moves: z.array(udlMoveSchema).default([]),
@@ -783,7 +1002,7 @@ const udlActionShape = {
783
1002
  const udlActionSchema = z.strictObject(udlActionShape);
784
1003
 
785
1004
  const udlAggregateBaseShape = {
786
- childInstrumentId: udlSnakeCaseSchema,
1005
+ childInstrumentId: udlInstrumentIdSchema,
787
1006
  childRefField: udlFieldNameSchema,
788
1007
  childStatuses: z.array(udlSnakeCaseSchema).min(1),
789
1008
  parentField: udlFieldNameSchema,
@@ -810,6 +1029,25 @@ const udlAggregateSchema = z.union([
810
1029
  ]);
811
1030
 
812
1031
  const udlInstrumentShape = {
1032
+ templateBinding: z
1033
+ .strictObject({
1034
+ id: udlSnakeCaseSchema,
1035
+ parameters: templateParametersSchema,
1036
+ })
1037
+ .optional(),
1038
+ allocation: udlAllocationSchema.optional(),
1039
+ contributions: udlContributionsSchema.optional(),
1040
+ dateOrder: z
1041
+ .array(
1042
+ z.strictObject({
1043
+ beforeField: udlFieldNameSchema,
1044
+ afterField: udlFieldNameSchema,
1045
+ operator: z.enum(["<", "<="]),
1046
+ }),
1047
+ )
1048
+ .min(1)
1049
+ .max(16)
1050
+ .optional(),
813
1051
  actionLibrary: udlActionLibrarySchema.optional(),
814
1052
  actionOrder: z.array(udlActionNameSchema).min(1),
815
1053
  agentDescription: udlAgentDescriptionSchema.optional(),
@@ -820,15 +1058,14 @@ const udlInstrumentShape = {
820
1058
  description: nonEmptyTextSchema.optional(),
821
1059
  dials: z.array(udlDialSchema).optional(),
822
1060
  distinctParties: z.literal(true).optional(),
823
- derivedAmounts: z.array(udlDerivedAmountSchema).min(1).max(4).optional(),
1061
+ derivedAmounts: z.array(udlDerivedAmountSchema).min(1).max(64).optional(),
824
1062
  feeRules: z.array(udlFeeRuleSchema).min(1).max(4).optional(),
825
1063
  fields: z.record(udlFieldNameSchema, jsonObjectSchema),
826
- id: udlSnakeCaseSchema,
1064
+ id: udlInstrumentIdSchema,
827
1065
  idPrefix: z
828
1066
  .string()
829
1067
  .regex(idPrefixPattern, "must contain 2 to 8 lowercase letters"),
830
1068
  lifecycle: udlLifecycleSchema,
831
- journeys: z.array(udlJourneySchema).min(1).optional(),
832
1069
  nav: z.array(nonEmptyTextSchema).min(1).optional(),
833
1070
  parties: z.record(udlPartyRoleSchema, udlFieldNameSchema).optional(),
834
1071
  partitions: z.array(udlPartitionSchema).min(1).optional(),
@@ -881,6 +1118,105 @@ export type UdlClauseVocabularyEntry = UdlClauseVocabularyMetadata &
881
1118
  );
882
1119
 
883
1120
  export const udlClauseVocabulary = [
1121
+ {
1122
+ scope: "action",
1123
+ spelling: "funding",
1124
+ target: "funding",
1125
+ cardinality: "one",
1126
+ effects: [
1127
+ {
1128
+ kind: "moves",
1129
+ per: "clause",
1130
+ signature: { fixed: "transfer.internal" },
1131
+ },
1132
+ ],
1133
+ },
1134
+ {
1135
+ scope: "action",
1136
+ spelling: "receipt distribution",
1137
+ target: "receiptDistribution",
1138
+ cardinality: "one",
1139
+ effects: [
1140
+ { kind: "decides", per: "clause", signature: { fixed: "allocation" } },
1141
+ { kind: "moves", per: "clause", signature: { fixed: "allocation" } },
1142
+ ],
1143
+ },
1144
+ {
1145
+ cardinality: "one",
1146
+ scope: "action",
1147
+ spelling: "requires allocation",
1148
+ target: "requiresAllocation",
1149
+ effects: [
1150
+ { kind: "decides", per: "clause", signature: { fixed: "allocation" } },
1151
+ ],
1152
+ },
1153
+ {
1154
+ cardinality: "one",
1155
+ scope: "instrument",
1156
+ spelling: "allocation",
1157
+ target: "allocation",
1158
+ },
1159
+ {
1160
+ cardinality: "one",
1161
+ scope: "instrument",
1162
+ spelling: "contributions",
1163
+ target: "contributions",
1164
+ },
1165
+ {
1166
+ cardinality: "one",
1167
+ scope: "action",
1168
+ spelling: "allocate",
1169
+ target: "allocate",
1170
+ effects: [
1171
+ { kind: "decides", per: "clause", signature: { fixed: "allocation" } },
1172
+ { kind: "moves", per: "clause", signature: { fixed: "allocation" } },
1173
+ ],
1174
+ },
1175
+ {
1176
+ cardinality: "one",
1177
+ scope: "action",
1178
+ spelling: "contribution stage",
1179
+ target: "contributionStage",
1180
+ effects: [
1181
+ {
1182
+ kind: "moves",
1183
+ per: "clause",
1184
+ signature: { fixed: "transfer.internal" },
1185
+ },
1186
+ ],
1187
+ },
1188
+ {
1189
+ cardinality: "many",
1190
+ scope: "instrument",
1191
+ spelling: "date order",
1192
+ target: "dateOrder",
1193
+ },
1194
+ {
1195
+ cardinality: "one",
1196
+ scope: "action",
1197
+ spelling: "unique",
1198
+ target: "unique",
1199
+ effects: [
1200
+ {
1201
+ kind: "decides",
1202
+ per: "clause",
1203
+ signature: { fixed: "subject_unique" },
1204
+ },
1205
+ ],
1206
+ },
1207
+ {
1208
+ cardinality: "many",
1209
+ scope: "action",
1210
+ spelling: "transitions refs",
1211
+ target: "transitionsRefs",
1212
+ effects: [
1213
+ {
1214
+ kind: "decides",
1215
+ per: "element",
1216
+ signature: { fixed: "referenced_transition" },
1217
+ },
1218
+ ],
1219
+ },
884
1220
  {
885
1221
  cardinality: "one",
886
1222
  literalKeys: true,
@@ -901,6 +1237,26 @@ export const udlClauseVocabulary = [
901
1237
  spelling: "calls",
902
1238
  target: "calls",
903
1239
  },
1240
+ {
1241
+ cardinality: "one",
1242
+ scope: "action",
1243
+ spelling: "requires input",
1244
+ target: "requiresInput",
1245
+ literalKeys: true,
1246
+ },
1247
+ {
1248
+ cardinality: "one",
1249
+ scope: "action",
1250
+ spelling: "engine owned",
1251
+ target: "engineOwned",
1252
+ },
1253
+ {
1254
+ cardinality: "one",
1255
+ scope: "action",
1256
+ spelling: "capture engine",
1257
+ target: "captureEngine",
1258
+ literalKeys: true,
1259
+ },
904
1260
  {
905
1261
  cardinality: "one",
906
1262
  scope: "action",
@@ -1266,12 +1622,6 @@ export const udlClauseVocabulary = [
1266
1622
  spelling: "id prefix",
1267
1623
  target: "idPrefix",
1268
1624
  },
1269
- {
1270
- cardinality: "many",
1271
- scope: "instrument",
1272
- spelling: "journeys",
1273
- target: "journeys",
1274
- },
1275
1625
  {
1276
1626
  cardinality: "many",
1277
1627
  scope: "instrument",
@@ -1302,6 +1652,12 @@ export const udlClauseVocabulary = [
1302
1652
  spelling: "surface visibility",
1303
1653
  target: "surfaceVisibility",
1304
1654
  },
1655
+ {
1656
+ cardinality: "one",
1657
+ scope: "instrument",
1658
+ spelling: "template binding",
1659
+ target: "templateBinding",
1660
+ },
1305
1661
  {
1306
1662
  cardinality: "one",
1307
1663
  scope: "instrument",
@@ -1320,6 +1676,13 @@ export const udlClauseVocabulary = [
1320
1676
  spelling: "update",
1321
1677
  target: "update",
1322
1678
  },
1679
+ {
1680
+ cardinality: "one",
1681
+ effects: [],
1682
+ scope: "action",
1683
+ spelling: "request authority",
1684
+ target: "requestAuthority",
1685
+ },
1323
1686
  ] as const satisfies readonly UdlClauseVocabularyEntry[];
1324
1687
 
1325
1688
  const udlDocumentShapeSchema = z.strictObject({
@@ -1348,24 +1711,10 @@ function referenceTargets(
1348
1711
  schema: Readonly<Record<string, unknown>>,
1349
1712
  instruments: readonly ParsedInstrument[],
1350
1713
  ): readonly ParsedInstrument[] {
1351
- if (schema.type !== "string" || typeof schema.pattern !== "string") return [];
1352
- // Parse the scoped-ID pattern. Executing an author regex here would bypass
1353
- // the semantic validator's branch and quantifier budgets.
1354
- const match = /^\^([a-z]{2,8})_\(sandbox\|live\)_\[a-z0-9\]\{8,64\}\$$/.exec(
1355
- schema.pattern,
1356
- );
1357
- if (!match) return [];
1358
- const prefix = match[1] as string;
1359
- const probe = `${prefix}_sandbox_0123456789abcdef`;
1360
- if (typeof schema.const === "string" && schema.const !== probe) return [];
1361
- if (Array.isArray(schema.enum) && !schema.enum.includes(probe)) return [];
1362
- if (typeof schema.minLength === "number" && probe.length < schema.minLength) {
1363
- return [];
1364
- }
1365
- if (typeof schema.maxLength === "number" && probe.length > schema.maxLength) {
1366
- return [];
1367
- }
1368
- return instruments.filter((instrument) => instrument.idPrefix === prefix);
1714
+ const prefix = referencePatternPrefix(schema);
1715
+ return prefix
1716
+ ? instruments.filter((instrument) => instrument.idPrefix === prefix)
1717
+ : [];
1369
1718
  }
1370
1719
 
1371
1720
  function declaredMoneyRefKeys(
@@ -1490,6 +1839,10 @@ export const udlDocumentSchema = udlDocumentShapeSchema.superRefine(
1490
1839
  },
1491
1840
  );
1492
1841
 
1842
+ export type UdlAllocation = z.infer<typeof udlAllocationSchema>;
1843
+ export type UdlAllocate = z.infer<typeof udlAllocateSchema>;
1844
+ export type UdlContributions = z.infer<typeof udlContributionsSchema>;
1845
+
1493
1846
  export type UdlAggregate = z.infer<typeof udlAggregateSchema>;
1494
1847
  export type UdlAggregateCondition = z.infer<typeof udlAggregateConditionSchema>;
1495
1848
  export type UdlBinding = z.infer<typeof udlBindingSchema>;
@@ -1515,8 +1868,6 @@ export type UdlLifecycleTransition = z.infer<
1515
1868
  >;
1516
1869
  export type UdlInstrument = z.infer<typeof udlInstrumentSchema>;
1517
1870
  export type UdlInstrumentSubject = z.infer<typeof udlInstrumentSubjectSchema>;
1518
- export type UdlJourney = z.infer<typeof udlJourneySchema>;
1519
- export type UdlJourneyStep = z.infer<typeof udlJourneyStepSchema>;
1520
1871
  export type UdlMove = z.infer<typeof udlMoveSchema>;
1521
1872
  export type UdlPayout = z.infer<typeof udlPayoutSchema>;
1522
1873
  export type UdlQuote = z.infer<typeof udlQuoteSchema>;