@hyperscale0/udl 1.0.0-alpha.4 → 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -1
- package/README.md +22 -20
- package/dist/evolution.d.ts +17 -0
- package/dist/evolution.d.ts.map +1 -1
- package/dist/evolution.js +54 -0
- package/dist/evolution.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/schema.d.ts +207 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +205 -1
- package/dist/schema.js.map +1 -1
- package/dist/validation.d.ts +6 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +323 -14
- package/dist/validation.js.map +1 -1
- package/package.json +1 -1
- package/spec/README.md +10 -7
- package/spec/udl.schema.json +289 -0
- package/src/evolution.ts +99 -0
- package/src/index.ts +4 -0
- package/src/schema.ts +238 -1
- package/src/validation.ts +504 -19
package/spec/udl.schema.json
CHANGED
|
@@ -109,6 +109,14 @@
|
|
|
109
109
|
]
|
|
110
110
|
}
|
|
111
111
|
},
|
|
112
|
+
"computedMoneyRefs": {
|
|
113
|
+
"minItems": 1,
|
|
114
|
+
"type": "array",
|
|
115
|
+
"items": {
|
|
116
|
+
"type": "string",
|
|
117
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
112
120
|
"description": {
|
|
113
121
|
"type": "string"
|
|
114
122
|
},
|
|
@@ -116,6 +124,46 @@
|
|
|
116
124
|
"type": "boolean",
|
|
117
125
|
"const": true
|
|
118
126
|
},
|
|
127
|
+
"derivedAmounts": {
|
|
128
|
+
"minItems": 1,
|
|
129
|
+
"maxItems": 4,
|
|
130
|
+
"type": "array",
|
|
131
|
+
"items": {
|
|
132
|
+
"type": "object",
|
|
133
|
+
"properties": {
|
|
134
|
+
"field": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
137
|
+
},
|
|
138
|
+
"rounding": {
|
|
139
|
+
"type": "string",
|
|
140
|
+
"const": "floor"
|
|
141
|
+
},
|
|
142
|
+
"rule": {
|
|
143
|
+
"type": "object",
|
|
144
|
+
"properties": {
|
|
145
|
+
"bps": {
|
|
146
|
+
"type": "integer",
|
|
147
|
+
"minimum": 1,
|
|
148
|
+
"maximum": 9999
|
|
149
|
+
},
|
|
150
|
+
"kind": {
|
|
151
|
+
"type": "string",
|
|
152
|
+
"const": "percentage_of"
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"required": ["bps", "kind"],
|
|
156
|
+
"additionalProperties": false
|
|
157
|
+
},
|
|
158
|
+
"sourceField": {
|
|
159
|
+
"type": "string",
|
|
160
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
"required": ["field", "rounding", "rule", "sourceField"],
|
|
164
|
+
"additionalProperties": false
|
|
165
|
+
}
|
|
166
|
+
},
|
|
119
167
|
"fields": {
|
|
120
168
|
"type": "object",
|
|
121
169
|
"propertyNames": {
|
|
@@ -338,6 +386,17 @@
|
|
|
338
386
|
"additionalProperties": {
|
|
339
387
|
"type": "object",
|
|
340
388
|
"properties": {
|
|
389
|
+
"captureInput": {
|
|
390
|
+
"type": "object",
|
|
391
|
+
"propertyNames": {
|
|
392
|
+
"type": "string",
|
|
393
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
394
|
+
},
|
|
395
|
+
"additionalProperties": {
|
|
396
|
+
"type": "string",
|
|
397
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
398
|
+
}
|
|
399
|
+
},
|
|
341
400
|
"deadline": {
|
|
342
401
|
"type": "object",
|
|
343
402
|
"properties": {
|
|
@@ -372,6 +431,59 @@
|
|
|
372
431
|
"required": ["capability", "deadlineMs", "onTimeout"],
|
|
373
432
|
"additionalProperties": false
|
|
374
433
|
},
|
|
434
|
+
"distribute": {
|
|
435
|
+
"type": "object",
|
|
436
|
+
"properties": {
|
|
437
|
+
"amountRef": {
|
|
438
|
+
"type": "string",
|
|
439
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
440
|
+
},
|
|
441
|
+
"onZero": {
|
|
442
|
+
"type": "string",
|
|
443
|
+
"enum": ["refuse", "skip_steps"]
|
|
444
|
+
},
|
|
445
|
+
"pool": {
|
|
446
|
+
"type": "object",
|
|
447
|
+
"properties": {
|
|
448
|
+
"from": {
|
|
449
|
+
"type": "string",
|
|
450
|
+
"const": "parent"
|
|
451
|
+
},
|
|
452
|
+
"path": {
|
|
453
|
+
"type": "string",
|
|
454
|
+
"pattern": "^[a-z][A-Za-z0-9]*(?:\\.[a-z][A-Za-z0-9]*)*$"
|
|
455
|
+
}
|
|
456
|
+
},
|
|
457
|
+
"required": ["from", "path"],
|
|
458
|
+
"additionalProperties": false
|
|
459
|
+
},
|
|
460
|
+
"refField": {
|
|
461
|
+
"type": "string",
|
|
462
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
463
|
+
},
|
|
464
|
+
"statuses": {
|
|
465
|
+
"minItems": 1,
|
|
466
|
+
"type": "array",
|
|
467
|
+
"items": {
|
|
468
|
+
"type": "string",
|
|
469
|
+
"pattern": "^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$"
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
"weightField": {
|
|
473
|
+
"type": "string",
|
|
474
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
475
|
+
}
|
|
476
|
+
},
|
|
477
|
+
"required": [
|
|
478
|
+
"amountRef",
|
|
479
|
+
"onZero",
|
|
480
|
+
"pool",
|
|
481
|
+
"refField",
|
|
482
|
+
"statuses",
|
|
483
|
+
"weightField"
|
|
484
|
+
],
|
|
485
|
+
"additionalProperties": false
|
|
486
|
+
},
|
|
375
487
|
"description": {
|
|
376
488
|
"type": "string"
|
|
377
489
|
},
|
|
@@ -580,6 +692,49 @@
|
|
|
580
692
|
"additionalProperties": false
|
|
581
693
|
}
|
|
582
694
|
},
|
|
695
|
+
"payout": {
|
|
696
|
+
"type": "object",
|
|
697
|
+
"properties": {
|
|
698
|
+
"amount": {
|
|
699
|
+
"type": "string",
|
|
700
|
+
"pattern": "^(?:fields|refs)\\.[a-z][A-Za-z0-9]*$"
|
|
701
|
+
},
|
|
702
|
+
"beneficiaryField": {
|
|
703
|
+
"type": "string",
|
|
704
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
705
|
+
},
|
|
706
|
+
"beneficiaryPartyField": {
|
|
707
|
+
"type": "string",
|
|
708
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
709
|
+
},
|
|
710
|
+
"capture": {
|
|
711
|
+
"type": "string",
|
|
712
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
713
|
+
},
|
|
714
|
+
"currencyField": {
|
|
715
|
+
"type": "string",
|
|
716
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
717
|
+
},
|
|
718
|
+
"sourceAccountField": {
|
|
719
|
+
"type": "string",
|
|
720
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
721
|
+
},
|
|
722
|
+
"speed": {
|
|
723
|
+
"type": "string",
|
|
724
|
+
"const": "standard"
|
|
725
|
+
}
|
|
726
|
+
},
|
|
727
|
+
"required": [
|
|
728
|
+
"amount",
|
|
729
|
+
"beneficiaryField",
|
|
730
|
+
"beneficiaryPartyField",
|
|
731
|
+
"capture",
|
|
732
|
+
"currencyField",
|
|
733
|
+
"sourceAccountField",
|
|
734
|
+
"speed"
|
|
735
|
+
],
|
|
736
|
+
"additionalProperties": false
|
|
737
|
+
},
|
|
583
738
|
"port": {
|
|
584
739
|
"type": "object",
|
|
585
740
|
"properties": {
|
|
@@ -595,6 +750,11 @@
|
|
|
595
750
|
"required": ["allowedParties"],
|
|
596
751
|
"additionalProperties": false
|
|
597
752
|
},
|
|
753
|
+
"publicIntent": {
|
|
754
|
+
"description": "Author-approved public intent name; the containing verb key remains the lifecycle and execution identity",
|
|
755
|
+
"type": "string",
|
|
756
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
757
|
+
},
|
|
598
758
|
"requiresAggregate": {
|
|
599
759
|
"minItems": 1,
|
|
600
760
|
"type": "array",
|
|
@@ -758,6 +918,51 @@
|
|
|
758
918
|
"required": ["path"],
|
|
759
919
|
"additionalProperties": false
|
|
760
920
|
},
|
|
921
|
+
"requiresExposure": {
|
|
922
|
+
"minItems": 1,
|
|
923
|
+
"type": "array",
|
|
924
|
+
"items": {
|
|
925
|
+
"type": "object",
|
|
926
|
+
"properties": {
|
|
927
|
+
"amountField": {
|
|
928
|
+
"type": "string",
|
|
929
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
930
|
+
},
|
|
931
|
+
"anchorField": {
|
|
932
|
+
"type": "string",
|
|
933
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
934
|
+
},
|
|
935
|
+
"capField": {
|
|
936
|
+
"type": "string",
|
|
937
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
938
|
+
},
|
|
939
|
+
"capOnAnchor": {
|
|
940
|
+
"type": "boolean",
|
|
941
|
+
"const": true
|
|
942
|
+
},
|
|
943
|
+
"childNounId": {
|
|
944
|
+
"type": "string",
|
|
945
|
+
"pattern": "^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$"
|
|
946
|
+
},
|
|
947
|
+
"statuses": {
|
|
948
|
+
"minItems": 1,
|
|
949
|
+
"type": "array",
|
|
950
|
+
"items": {
|
|
951
|
+
"type": "string",
|
|
952
|
+
"pattern": "^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$"
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
},
|
|
956
|
+
"required": [
|
|
957
|
+
"amountField",
|
|
958
|
+
"anchorField",
|
|
959
|
+
"capField",
|
|
960
|
+
"childNounId",
|
|
961
|
+
"statuses"
|
|
962
|
+
],
|
|
963
|
+
"additionalProperties": false
|
|
964
|
+
}
|
|
965
|
+
},
|
|
761
966
|
"requiresRefs": {
|
|
762
967
|
"minItems": 1,
|
|
763
968
|
"type": "array",
|
|
@@ -811,6 +1016,21 @@
|
|
|
811
1016
|
"additionalProperties": false
|
|
812
1017
|
}
|
|
813
1018
|
},
|
|
1019
|
+
"requiresSettlement": {
|
|
1020
|
+
"type": "object",
|
|
1021
|
+
"properties": {
|
|
1022
|
+
"capture": {
|
|
1023
|
+
"type": "string",
|
|
1024
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
1025
|
+
},
|
|
1026
|
+
"payoutRef": {
|
|
1027
|
+
"type": "string",
|
|
1028
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
1029
|
+
}
|
|
1030
|
+
},
|
|
1031
|
+
"required": ["capture", "payoutRef"],
|
|
1032
|
+
"additionalProperties": false
|
|
1033
|
+
},
|
|
814
1034
|
"setsAt": {
|
|
815
1035
|
"type": "object",
|
|
816
1036
|
"properties": {
|
|
@@ -818,6 +1038,10 @@
|
|
|
818
1038
|
"type": "string",
|
|
819
1039
|
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
820
1040
|
},
|
|
1041
|
+
"marker": {
|
|
1042
|
+
"type": "boolean",
|
|
1043
|
+
"const": true
|
|
1044
|
+
},
|
|
821
1045
|
"offset": {
|
|
822
1046
|
"type": "string"
|
|
823
1047
|
}
|
|
@@ -825,6 +1049,71 @@
|
|
|
825
1049
|
"required": ["field", "offset"],
|
|
826
1050
|
"additionalProperties": false
|
|
827
1051
|
},
|
|
1052
|
+
"signedSum": {
|
|
1053
|
+
"type": "object",
|
|
1054
|
+
"properties": {
|
|
1055
|
+
"amountRef": {
|
|
1056
|
+
"type": "string",
|
|
1057
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
1058
|
+
},
|
|
1059
|
+
"onNegative": {
|
|
1060
|
+
"type": "string",
|
|
1061
|
+
"const": "refuse"
|
|
1062
|
+
},
|
|
1063
|
+
"onZero": {
|
|
1064
|
+
"type": "string",
|
|
1065
|
+
"enum": ["refuse", "skip_steps"]
|
|
1066
|
+
},
|
|
1067
|
+
"sources": {
|
|
1068
|
+
"minItems": 1,
|
|
1069
|
+
"type": "array",
|
|
1070
|
+
"items": {
|
|
1071
|
+
"type": "object",
|
|
1072
|
+
"properties": {
|
|
1073
|
+
"amountField": {
|
|
1074
|
+
"type": "string",
|
|
1075
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
1076
|
+
},
|
|
1077
|
+
"nounId": {
|
|
1078
|
+
"type": "string",
|
|
1079
|
+
"pattern": "^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$"
|
|
1080
|
+
},
|
|
1081
|
+
"refField": {
|
|
1082
|
+
"type": "string",
|
|
1083
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
1084
|
+
},
|
|
1085
|
+
"sign": {
|
|
1086
|
+
"type": "string",
|
|
1087
|
+
"enum": ["add", "subtract"]
|
|
1088
|
+
},
|
|
1089
|
+
"statuses": {
|
|
1090
|
+
"minItems": 1,
|
|
1091
|
+
"type": "array",
|
|
1092
|
+
"items": {
|
|
1093
|
+
"type": "string",
|
|
1094
|
+
"pattern": "^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$"
|
|
1095
|
+
}
|
|
1096
|
+
},
|
|
1097
|
+
"subtotalRef": {
|
|
1098
|
+
"type": "string",
|
|
1099
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
1100
|
+
}
|
|
1101
|
+
},
|
|
1102
|
+
"required": [
|
|
1103
|
+
"amountField",
|
|
1104
|
+
"nounId",
|
|
1105
|
+
"refField",
|
|
1106
|
+
"sign",
|
|
1107
|
+
"statuses",
|
|
1108
|
+
"subtotalRef"
|
|
1109
|
+
],
|
|
1110
|
+
"additionalProperties": false
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
},
|
|
1114
|
+
"required": ["amountRef", "onNegative", "onZero", "sources"],
|
|
1115
|
+
"additionalProperties": false
|
|
1116
|
+
},
|
|
828
1117
|
"steps": {
|
|
829
1118
|
"type": "array",
|
|
830
1119
|
"items": {
|
package/src/evolution.ts
CHANGED
|
@@ -18,8 +18,12 @@ export interface EvolutionMoveSnapshot extends EvolutionStepSnapshot {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface EvolutionVerbSnapshot {
|
|
21
|
+
/** Missing on snapshots written before receipt-input capture existed. */
|
|
22
|
+
readonly captureInput?: unknown;
|
|
21
23
|
readonly deadline: unknown;
|
|
22
24
|
readonly decision: unknown;
|
|
25
|
+
/** Missing on snapshots written before weighted distribution existed. */
|
|
26
|
+
readonly distribute?: unknown;
|
|
23
27
|
readonly due: unknown;
|
|
24
28
|
readonly earnable: boolean;
|
|
25
29
|
readonly eventName: string | null;
|
|
@@ -30,11 +34,21 @@ export interface EvolutionVerbSnapshot {
|
|
|
30
34
|
* friends change what callers may send, so they are frozen once live.
|
|
31
35
|
*/
|
|
32
36
|
readonly inputConstraints: unknown;
|
|
37
|
+
/** Missing on snapshots written before payout intents existed. */
|
|
38
|
+
readonly payout?: unknown;
|
|
33
39
|
readonly port: unknown;
|
|
40
|
+
/** Missing on snapshots written before public intent metadata existed. */
|
|
41
|
+
readonly publicIntent?: string | null;
|
|
34
42
|
readonly requiresAggregate: unknown;
|
|
35
43
|
readonly requiresDrainedAccount: unknown;
|
|
44
|
+
/** Missing on snapshots written before exposure gates entered open UDL. */
|
|
45
|
+
readonly requiresExposure?: unknown;
|
|
36
46
|
readonly requiresRefs: unknown;
|
|
47
|
+
/** Missing on snapshots written before settlement evidence gates existed. */
|
|
48
|
+
readonly requiresSettlement?: unknown;
|
|
37
49
|
readonly setsAt: unknown;
|
|
50
|
+
/** Missing on snapshots written before signed child sums existed. */
|
|
51
|
+
readonly signedSum?: unknown;
|
|
38
52
|
readonly moves: readonly EvolutionMoveSnapshot[];
|
|
39
53
|
readonly steps: readonly EvolutionStepSnapshot[];
|
|
40
54
|
}
|
|
@@ -47,6 +61,9 @@ export interface EvolutionTransitionSnapshot {
|
|
|
47
61
|
/** The complete serializable algebra protected by append-only evolution. */
|
|
48
62
|
export interface NounEvolutionSnapshot {
|
|
49
63
|
readonly aggregateInvariants: readonly string[];
|
|
64
|
+
/** Missing on snapshots written before typed computed refs entered UDL. */
|
|
65
|
+
readonly computedMoneyRefs?: readonly string[];
|
|
66
|
+
readonly derivedAmounts: readonly string[];
|
|
50
67
|
readonly distinctParties?: true;
|
|
51
68
|
readonly fields: Readonly<Record<string, EvolutionFieldSnapshot>>;
|
|
52
69
|
readonly id: string;
|
|
@@ -70,6 +87,11 @@ export function snapshotUdlNoun(noun: UdlNoun): NounEvolutionSnapshot {
|
|
|
70
87
|
aggregateInvariants: (noun.aggregateInvariants ?? []).map(
|
|
71
88
|
aggregateInvariantKey,
|
|
72
89
|
),
|
|
90
|
+
computedMoneyRefs: [...(noun.computedMoneyRefs ?? [])].sort(),
|
|
91
|
+
derivedAmounts: (noun.derivedAmounts ?? []).map(
|
|
92
|
+
(amount) =>
|
|
93
|
+
`${amount.field}=floor(${amount.sourceField}*${amount.rule.bps}/10000)`,
|
|
94
|
+
),
|
|
73
95
|
...(noun.distinctParties ? { distinctParties: true as const } : {}),
|
|
74
96
|
fields: Object.fromEntries(
|
|
75
97
|
Object.entries(noun.fields).map(([field, schema]) => [
|
|
@@ -235,6 +257,22 @@ export function diffNounEvolution(
|
|
|
235
257
|
violations.push(...diffVerbs(previous.verbs, next.verbs));
|
|
236
258
|
violations.push(...diffParties(previous.parties, next.parties));
|
|
237
259
|
violations.push(...diffAggregates(previous, next));
|
|
260
|
+
if (
|
|
261
|
+
stableStringify(previous.computedMoneyRefs ?? []) !==
|
|
262
|
+
stableStringify(next.computedMoneyRefs ?? [])
|
|
263
|
+
) {
|
|
264
|
+
violations.push(
|
|
265
|
+
"computed money refs changed; runtime-derived money surfaces are frozen once live",
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
if (
|
|
269
|
+
stableStringify(previous.derivedAmounts ?? []) !==
|
|
270
|
+
stableStringify(next.derivedAmounts ?? [])
|
|
271
|
+
) {
|
|
272
|
+
violations.push(
|
|
273
|
+
"derived amount rules changed; derived money arithmetic is frozen once live",
|
|
274
|
+
);
|
|
275
|
+
}
|
|
238
276
|
violations.push(
|
|
239
277
|
...removedSetEntries(
|
|
240
278
|
previous.partitions,
|
|
@@ -271,8 +309,10 @@ export function diffNounEvolution(
|
|
|
271
309
|
|
|
272
310
|
function snapshotUdlVerb(definition: UdlVerb): EvolutionVerbSnapshot {
|
|
273
311
|
return {
|
|
312
|
+
captureInput: definition.captureInput ?? null,
|
|
274
313
|
deadline: definition.deadline ?? null,
|
|
275
314
|
decision: definition.decision ?? null,
|
|
315
|
+
distribute: definition.distribute ?? null,
|
|
276
316
|
due: definition.due ?? null,
|
|
277
317
|
earnable: definition.earnable ?? false,
|
|
278
318
|
eventName: definition.eventName ?? null,
|
|
@@ -280,8 +320,11 @@ function snapshotUdlVerb(definition: UdlVerb): EvolutionVerbSnapshot {
|
|
|
280
320
|
inputConstraints: definition.input
|
|
281
321
|
? snapshotJsonSchemaConstraints(definition.input)
|
|
282
322
|
: null,
|
|
323
|
+
payout: definition.payout ?? null,
|
|
283
324
|
port: definition.port ?? null,
|
|
325
|
+
publicIntent: definition.publicIntent ?? null,
|
|
284
326
|
setsAt: definition.setsAt ?? null,
|
|
327
|
+
signedSum: definition.signedSum ?? null,
|
|
285
328
|
moves: definition.moves.map((move) => ({
|
|
286
329
|
bind: move.bind,
|
|
287
330
|
capture: move.capture ?? {},
|
|
@@ -290,7 +333,9 @@ function snapshotUdlVerb(definition: UdlVerb): EvolutionVerbSnapshot {
|
|
|
290
333
|
})),
|
|
291
334
|
requiresAggregate: definition.requiresAggregate ?? [],
|
|
292
335
|
requiresDrainedAccount: definition.requiresDrainedAccount ?? null,
|
|
336
|
+
requiresExposure: definition.requiresExposure ?? [],
|
|
293
337
|
requiresRefs: definition.requiresRefs ?? [],
|
|
338
|
+
requiresSettlement: definition.requiresSettlement ?? null,
|
|
294
339
|
steps: definition.steps.map((step) => ({
|
|
295
340
|
bind: step.bind,
|
|
296
341
|
capture: step.capture ?? {},
|
|
@@ -431,6 +476,26 @@ function diffVerbs(
|
|
|
431
476
|
) {
|
|
432
477
|
violations.push(`verb ${verb} changed its drained-account gate`);
|
|
433
478
|
}
|
|
479
|
+
if (
|
|
480
|
+
descriptor.requiresExposure !== undefined &&
|
|
481
|
+
stableStringify(descriptor.requiresExposure) !==
|
|
482
|
+
stableStringify(current.requiresExposure)
|
|
483
|
+
) {
|
|
484
|
+
violations.push(`verb ${verb} changed its exposure admission gates`);
|
|
485
|
+
}
|
|
486
|
+
if (
|
|
487
|
+
descriptor.requiresSettlement !== undefined &&
|
|
488
|
+
stableStringify(descriptor.requiresSettlement) !==
|
|
489
|
+
stableStringify(current.requiresSettlement)
|
|
490
|
+
) {
|
|
491
|
+
violations.push(`verb ${verb} changed its settlement evidence gate`);
|
|
492
|
+
}
|
|
493
|
+
if (
|
|
494
|
+
stableStringify(descriptor.payout ?? null) !==
|
|
495
|
+
stableStringify(current.payout ?? null)
|
|
496
|
+
) {
|
|
497
|
+
violations.push(`verb ${verb} changed its payout intent`);
|
|
498
|
+
}
|
|
434
499
|
if (descriptor.earnable !== current.earnable) {
|
|
435
500
|
violations.push(`verb ${verb} changed its earnable flag`);
|
|
436
501
|
}
|
|
@@ -450,14 +515,48 @@ function diffVerbs(
|
|
|
450
515
|
) {
|
|
451
516
|
violations.push(`verb ${verb} changed its provider decision`);
|
|
452
517
|
}
|
|
518
|
+
if (
|
|
519
|
+
stableStringify(descriptor.distribute) !==
|
|
520
|
+
stableStringify(current.distribute)
|
|
521
|
+
) {
|
|
522
|
+
violations.push(
|
|
523
|
+
`verb ${verb} changed its distribution rule; money distribution is frozen once live`,
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
if (
|
|
527
|
+
descriptor.captureInput !== undefined &&
|
|
528
|
+
stableStringify(descriptor.captureInput) !==
|
|
529
|
+
stableStringify(current.captureInput)
|
|
530
|
+
) {
|
|
531
|
+
violations.push(`verb ${verb} changed its captured receipt input`);
|
|
532
|
+
}
|
|
453
533
|
if (stableStringify(descriptor.port) !== stableStringify(current.port)) {
|
|
454
534
|
violations.push(`verb ${verb} changed its decision port`);
|
|
455
535
|
}
|
|
536
|
+
if (
|
|
537
|
+
descriptor.publicIntent != null &&
|
|
538
|
+
descriptor.publicIntent !== current.publicIntent
|
|
539
|
+
) {
|
|
540
|
+
violations.push(`verb ${verb} changed its public intent`);
|
|
541
|
+
}
|
|
456
542
|
if (
|
|
457
543
|
stableStringify(descriptor.setsAt) !== stableStringify(current.setsAt)
|
|
458
544
|
) {
|
|
459
545
|
violations.push(`verb ${verb} changed its computed timestamp`);
|
|
460
546
|
}
|
|
547
|
+
if (
|
|
548
|
+
descriptor.signedSum !== undefined &&
|
|
549
|
+
stableStringify(descriptor.signedSum) !==
|
|
550
|
+
stableStringify(current.signedSum)
|
|
551
|
+
) {
|
|
552
|
+
violations.push(`verb ${verb} changed its signed child sum`);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
for (const [verb, descriptor] of Object.entries(next)) {
|
|
556
|
+
if (previous[verb] || descriptor.payout == null) continue;
|
|
557
|
+
violations.push(
|
|
558
|
+
`verb ${verb} added a payout intent; external money movement is frozen once live`,
|
|
559
|
+
);
|
|
461
560
|
}
|
|
462
561
|
return violations;
|
|
463
562
|
}
|
package/src/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ export {
|
|
|
23
23
|
UDL_FORMAT_VERSION,
|
|
24
24
|
udlDocumentSchema,
|
|
25
25
|
udlKernelOperationSchema,
|
|
26
|
+
udlPublicIntentSchema,
|
|
26
27
|
} from "./schema.js";
|
|
27
28
|
export type {
|
|
28
29
|
UdlAggregate,
|
|
@@ -39,6 +40,8 @@ export type {
|
|
|
39
40
|
UdlLifecycleTransition,
|
|
40
41
|
UdlNoun,
|
|
41
42
|
UdlNounSubject,
|
|
43
|
+
UdlPayout,
|
|
44
|
+
UdlRequiresSettlement,
|
|
42
45
|
UdlStep,
|
|
43
46
|
UdlSubject,
|
|
44
47
|
UdlUnwind,
|
|
@@ -49,6 +52,7 @@ export {
|
|
|
49
52
|
openReferenceShapeBudget,
|
|
50
53
|
UdlError,
|
|
51
54
|
validateUdl,
|
|
55
|
+
validateUdlJsonSchema,
|
|
52
56
|
validateUdlSchemaValue,
|
|
53
57
|
} from "./validation.js";
|
|
54
58
|
export type {
|