@hyperscale0/udl 2.6.1 → 3.0.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.
- package/CHANGELOG.md +2 -330
- package/LICENSING.md +1 -2
- package/README.md +3 -114
- package/TRADEMARKS.md +2 -2
- package/dist/diagnostics.d.ts +21 -201
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +29 -193
- package/dist/diagnostics.js.map +1 -1
- package/dist/evolution.d.ts +3 -132
- package/dist/evolution.d.ts.map +1 -1
- package/dist/evolution.js +29 -633
- package/dist/evolution.js.map +1 -1
- package/dist/finance.d.ts +5 -72
- package/dist/finance.d.ts.map +1 -1
- package/dist/finance.js +233 -737
- package/dist/finance.js.map +1 -1
- package/dist/index.d.ts +7 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -12
- package/dist/index.js.map +1 -1
- package/dist/instrument-references.d.ts.map +1 -1
- package/dist/instrument-references.js +3 -2
- package/dist/instrument-references.js.map +1 -1
- package/dist/schema.d.ts +2079 -4564
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +270 -1609
- package/dist/schema.js.map +1 -1
- package/dist/validation.d.ts +8 -104
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +653 -3271
- package/dist/validation.js.map +1 -1
- package/docs/README.md +147 -14
- package/package.json +7 -11
- package/spec/README.md +151 -164
- package/spec/darb.udl.json +249 -0
- package/spec/udl.schema.json +4104 -3202
- package/src/diagnostics.ts +51 -246
- package/src/evolution.ts +39 -1045
- package/src/finance.ts +287 -1127
- package/src/index.ts +18 -142
- package/src/instrument-references.ts +3 -2
- package/src/schema.ts +285 -1843
- package/src/validation.ts +870 -5611
- package/conformance/README.md +0 -82
- package/conformance/evolution/action-contract.expected.json +0 -10
- package/conformance/evolution/action-contract.live.udl +0 -44
- package/conformance/evolution/action-contract.next.udl +0 -45
- package/conformance/evolution/product-identity.expected.json +0 -10
- package/conformance/evolution/product-identity.live.udl +0 -55
- package/conformance/evolution/product-identity.next.udl +0 -55
- package/conformance/evolution/version-required.expected.json +0 -10
- package/conformance/evolution/version-required.live.udl +0 -55
- package/conformance/evolution/version-required.next.udl +0 -58
- package/conformance/invalid/action-without-transition.expected.json +0 -10
- package/conformance/invalid/action-without-transition.udl +0 -60
- package/conformance/invalid/agent-description-too-long.expected.json +0 -10
- package/conformance/invalid/agent-description-too-long.udl +0 -57
- package/conformance/invalid/blank-title.expected.json +0 -10
- package/conformance/invalid/blank-title.udl +0 -54
- package/conformance/invalid/call-binds-results.expected.json +0 -10
- package/conformance/invalid/call-binds-results.udl +0 -314
- package/conformance/invalid/call-unknown-action.expected.json +0 -10
- package/conformance/invalid/call-unknown-action.udl +0 -314
- package/conformance/invalid/composition-dial-duplicate-key.expected.json +0 -10
- package/conformance/invalid/composition-dial-duplicate-key.udl +0 -73
- package/conformance/invalid/depth-budget.expected.json +0 -10
- package/conformance/invalid/depth-budget.udl +0 -49
- package/conformance/invalid/duplicate-subject.expected.json +0 -10
- package/conformance/invalid/duplicate-subject.udl +0 -230
- package/conformance/invalid/forged-effects.expected.json +0 -10
- package/conformance/invalid/forged-effects.udl +0 -76
- package/conformance/invalid/format-version.expected.json +0 -10
- package/conformance/invalid/format-version.udl +0 -54
- package/conformance/invalid/instrument-id-not-snake-case.expected.json +0 -10
- package/conformance/invalid/instrument-id-not-snake-case.udl +0 -54
- package/conformance/invalid/invalid-aggregate-gate-shape.expected.json +0 -10
- package/conformance/invalid/invalid-aggregate-gate-shape.udl +0 -1819
- package/conformance/invalid/invalid-check-duration.expected.json +0 -10
- package/conformance/invalid/invalid-check-duration.udl +0 -219
- package/conformance/invalid/invalid-dial-anchor.expected.json +0 -10
- package/conformance/invalid/invalid-dial-anchor.udl +0 -219
- package/conformance/invalid/invalid-exception-parent-ref.expected.json +0 -10
- package/conformance/invalid/invalid-exception-parent-ref.udl +0 -2487
- package/conformance/invalid/invalid-exposure-shape.expected.json +0 -10
- package/conformance/invalid/invalid-exposure-shape.udl +0 -1819
- package/conformance/invalid/invalid-journeys.expected.json +0 -10
- package/conformance/invalid/invalid-journeys.udl +0 -77
- package/conformance/invalid/invalid-remainder.expected.json +0 -10
- package/conformance/invalid/invalid-remainder.udl +0 -220
- package/conformance/invalid/invalid-schema-keyword.expected.json +0 -10
- package/conformance/invalid/invalid-schema-keyword.udl +0 -220
- package/conformance/invalid/invalid-utf8.expected.json +0 -10
- package/conformance/invalid/invalid-utf8.udl +0 -1
- package/conformance/invalid/leaf-effect-mismatch.expected.json +0 -10
- package/conformance/invalid/leaf-effect-mismatch.udl +0 -314
- package/conformance/invalid/malformed-json.expected.json +0 -10
- package/conformance/invalid/malformed-json.udl +0 -1
- package/conformance/invalid/missing-create-action.expected.json +0 -10
- package/conformance/invalid/missing-create-action.udl +0 -48
- package/conformance/invalid/missing-exception-amount-field.expected.json +0 -10
- package/conformance/invalid/missing-exception-amount-field.udl +0 -2487
- package/conformance/invalid/missing-exception-contract.expected.json +0 -14
- package/conformance/invalid/missing-exception-contract.udl +0 -2523
- package/conformance/invalid/missing-exception-reason-field.expected.json +0 -10
- package/conformance/invalid/missing-exception-reason-field.udl +0 -2487
- package/conformance/invalid/not-an-object.expected.json +0 -10
- package/conformance/invalid/not-an-object.udl +0 -1
- package/conformance/invalid/payout-reconcile-not-a-bank-debit.expected.json +0 -10
- package/conformance/invalid/payout-reconcile-not-a-bank-debit.udl +0 -259
- package/conformance/invalid/piece-plan-without-partition.expected.json +0 -10
- package/conformance/invalid/piece-plan-without-partition.udl +0 -305
- package/conformance/invalid/private-action-independent-approval.expected.json +0 -10
- package/conformance/invalid/private-action-independent-approval.udl +0 -314
- package/conformance/invalid/quote-freeze-set-incomplete.expected.json +0 -10
- package/conformance/invalid/quote-freeze-set-incomplete.udl +0 -261
- package/conformance/invalid/quote-named-reference-gate.expected.json +0 -10
- package/conformance/invalid/quote-named-reference-gate.udl +0 -50
- package/conformance/invalid/reconcile-named-reference-gate.expected.json +0 -10
- package/conformance/invalid/reconcile-named-reference-gate.udl +0 -50
- package/conformance/invalid/unfund-order-not-reversed.expected.json +0 -10
- package/conformance/invalid/unfund-order-not-reversed.udl +0 -314
- package/conformance/invalid/unknown-key.expected.json +0 -10
- package/conformance/invalid/unknown-key.udl +0 -55
- package/conformance/invalid/unknown-reference-gate-field.expected.json +0 -10
- package/conformance/invalid/unknown-reference-gate-field.udl +0 -1819
- package/conformance/invalid/unknown-required-field.expected.json +0 -10
- package/conformance/invalid/unknown-required-field.udl +0 -220
- package/conformance/invalid/unreachable-state.expected.json +0 -10
- package/conformance/invalid/unreachable-state.udl +0 -55
- package/conformance/invalid/wrong-exception-amount-field.expected.json +0 -10
- package/conformance/invalid/wrong-exception-amount-field.udl +0 -2487
- package/conformance/invalid/wrong-exception-reason-field.expected.json +0 -10
- package/conformance/invalid/wrong-exception-reason-field.udl +0 -2487
- package/conformance/valid/agent-description.expected.json +0 -6
- package/conformance/valid/agent-description.udl +0 -66
- package/conformance/valid/attested.expected.json +0 -6
- package/conformance/valid/attested.udl +0 -251
- package/conformance/valid/cards.expected.json +0 -6
- package/conformance/valid/cards.udl +0 -1579
- package/conformance/valid/commerce-escrow.expected.json +0 -6
- package/conformance/valid/commerce-escrow.udl +0 -1512
- package/conformance/valid/compiled-crowdfunding.expected.json +0 -6
- package/conformance/valid/compiled-crowdfunding.udl +0 -1843
- package/conformance/valid/compiled-watch-club.expected.json +0 -6
- package/conformance/valid/compiled-watch-club.udl +0 -2486
- package/conformance/valid/complete-contract.expected.json +0 -6
- package/conformance/valid/complete-contract.udl +0 -218
- package/conformance/valid/effect-signatures.expected.json +0 -6
- package/conformance/valid/effect-signatures.udl +0 -75
- package/conformance/valid/hand-edited.expected.json +0 -6
- package/conformance/valid/hand-edited.udl +0 -1
- package/conformance/valid/insured-car-marketplace.expected.json +0 -6
- package/conformance/valid/insured-car-marketplace.udl +0 -1050
- package/conformance/valid/insured-travel.expected.json +0 -6
- package/conformance/valid/insured-travel.udl +0 -3469
- package/conformance/valid/minimal.expected.json +0 -6
- package/conformance/valid/minimal.udl +0 -62
- package/conformance/valid/piece-plan-calls.expected.json +0 -6
- package/conformance/valid/piece-plan-calls.udl +0 -314
- package/conformance/valid/protection.expected.json +0 -6
- package/conformance/valid/protection.udl +0 -1551
- package/conformance/valid/string-escaping.expected.json +0 -6
- package/conformance/valid/string-escaping.udl +0 -54
- package/conformance/valid/vocabulary.expected.json +0 -6
- package/conformance/valid/vocabulary.udl +0 -2012
- package/dist/allocation.d.ts +0 -60
- package/dist/allocation.d.ts.map +0 -1
- package/dist/allocation.js +0 -177
- package/dist/allocation.js.map +0 -1
- package/dist/check-profiles.d.ts +0 -57
- package/dist/check-profiles.d.ts.map +0 -1
- package/dist/check-profiles.js +0 -62
- package/dist/check-profiles.js.map +0 -1
- package/dist/distribution.d.ts +0 -15
- package/dist/distribution.d.ts.map +0 -1
- package/dist/distribution.js +0 -49
- package/dist/distribution.js.map +0 -1
- package/dist/effects.d.ts +0 -58
- package/dist/effects.d.ts.map +0 -1
- package/dist/effects.js +0 -1126
- package/dist/effects.js.map +0 -1
- package/dist/reference.d.ts +0 -3
- package/dist/reference.d.ts.map +0 -1
- package/dist/reference.js +0 -28
- package/dist/reference.js.map +0 -1
- package/dist/vocabulary.d.ts +0 -23
- package/dist/vocabulary.d.ts.map +0 -1
- package/dist/vocabulary.js +0 -1052
- package/dist/vocabulary.js.map +0 -1
- package/docs/funding-custody.md +0 -165
- package/docs/guide/01-a-document.md +0 -37
- package/docs/guide/02-money-steps.md +0 -23
- package/docs/guide/03-laws.md +0 -18
- package/docs/guide/04-fees-and-remainder.md +0 -36
- package/docs/guide/05-checks-updates-dials.md +0 -7
- package/docs/guide/06-effects.md +0 -11
- package/docs/guide/07-evolution.md +0 -11
- package/docs/guide/08-implementing.md +0 -13
- package/docs/guide/09-schedules-and-allocation.md +0 -132
- package/docs/llms-full.txt +0 -2008
- package/docs/llms.txt +0 -14
- package/docs/piece-plans.md +0 -148
- package/docs/reference/canonical.md +0 -16
- package/docs/reference/clauses.md +0 -1585
- package/docs/reference/cli.md +0 -24
- package/docs/reference/diagnostics.md +0 -38
- package/skills/udl/SKILL.md +0 -28
- package/src/allocation.ts +0 -259
- package/src/check-profiles.ts +0 -80
- package/src/distribution.ts +0 -61
- package/src/effects.ts +0 -1920
- package/src/reference.ts +0 -31
- package/src/vocabulary.ts +0 -1635
package/dist/schema.js
CHANGED
|
@@ -1,1676 +1,337 @@
|
|
|
1
|
-
import { referencePatternPrefix } from "./reference.js";
|
|
2
1
|
import { z } from "zod";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
"decides",
|
|
6
|
-
"holds",
|
|
7
|
-
"moves",
|
|
8
|
-
"notifies",
|
|
9
|
-
"reads",
|
|
10
|
-
"schedules",
|
|
11
|
-
];
|
|
12
|
-
export const UDL_FORMAT_VERSION = 1;
|
|
13
|
-
const snakeCasePattern = /^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/;
|
|
14
|
-
const camelCasePattern = /^[a-z][A-Za-z0-9]*$/;
|
|
15
|
-
const fieldPathPattern = /^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*)*$/;
|
|
16
|
-
const idPrefixPattern = /^[a-z]{2,8}$/;
|
|
17
|
-
const eventNamePattern = /^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+$/;
|
|
18
|
-
const udlSnakeCaseSchema = z
|
|
2
|
+
export const UDL_FORMAT_VERSION = 3;
|
|
3
|
+
const name = z
|
|
19
4
|
.string()
|
|
20
|
-
.regex(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
});
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const udlFieldNameSchema = z
|
|
28
|
-
.string()
|
|
29
|
-
.regex(camelCasePattern, "must be a camelCase field name");
|
|
30
|
-
export const udlPublicActionSchema = z
|
|
31
|
-
.string()
|
|
32
|
-
.regex(camelCasePattern, "must be a camelCase public action name");
|
|
33
|
-
export const udlInstrumentActionIdSchema = z
|
|
34
|
-
.string()
|
|
35
|
-
.max(160)
|
|
36
|
-
.regex(/^[a-z][a-z0-9_]*\.[a-z][a-z0-9_]*$/, "must name an instrument action as instrument_id.action_key");
|
|
37
|
-
const nonEmptyTextSchema = z
|
|
5
|
+
.regex(/^[a-z][a-zA-Z0-9_]*$/)
|
|
6
|
+
.max(80);
|
|
7
|
+
const text = z.string().min(1).max(2048);
|
|
8
|
+
const amount = z.string().regex(/^(0|[1-9][0-9]{0,17})$/);
|
|
9
|
+
const integer = z.number().int().safe();
|
|
10
|
+
const scalar = z.union([z.string(), integer, z.boolean()]);
|
|
11
|
+
const path = z
|
|
38
12
|
.string()
|
|
39
|
-
.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
.
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
.regex(/^(?:fields|refs)\.[a-z][A-Za-z0-9]*$/, "must name one declared fields.* or refs.* value");
|
|
50
|
-
const jsonObjectSchema = z.record(z.string(), z.json());
|
|
51
|
-
const stringMapSchema = z.record(nonEmptyTextSchema, nonEmptyTextSchema);
|
|
52
|
-
const providerFamilyIds = [
|
|
53
|
-
"accounts_ledger_first_party",
|
|
54
|
-
"identity_verification",
|
|
55
|
-
"national_identity",
|
|
56
|
-
"credit_bureau",
|
|
57
|
-
"sanctions_screening",
|
|
58
|
-
"enforcement_instrument",
|
|
59
|
-
"credit_servicing",
|
|
60
|
-
"collections_agency",
|
|
61
|
-
"settlement_ingestion",
|
|
62
|
-
"payouts",
|
|
63
|
-
"banking_or_card_issuing",
|
|
64
|
-
"insurance_carrier",
|
|
65
|
-
"insurance_claims_adjuster",
|
|
66
|
-
"air_carrier",
|
|
67
|
-
"lodging_supplier",
|
|
68
|
-
"email_or_notification",
|
|
69
|
-
];
|
|
70
|
-
export const udlProviderFamilyIdSchema = z.enum(providerFamilyIds);
|
|
71
|
-
const udlDeclaredValuePolicySchema = z.enum(["required", "optional", "none"]);
|
|
72
|
-
const udlSubjectSchema = z.strictObject({
|
|
73
|
-
declaredValue: udlDeclaredValuePolicySchema,
|
|
74
|
-
kind: udlSnakeCaseSchema,
|
|
75
|
-
schema: jsonObjectSchema,
|
|
76
|
-
title: nonEmptyTextSchema,
|
|
77
|
-
version: z.number().int().positive(),
|
|
78
|
-
});
|
|
79
|
-
const udlInstrumentSubjectSchema = z.strictObject({
|
|
80
|
-
extensible: z.boolean().optional(),
|
|
81
|
-
kinds: z.array(udlSnakeCaseSchema).min(1),
|
|
82
|
-
});
|
|
83
|
-
const udlExampleSchema = z.strictObject({
|
|
84
|
-
input: jsonObjectSchema,
|
|
85
|
-
name: nonEmptyTextSchema,
|
|
86
|
-
output: z.json().optional(),
|
|
87
|
-
});
|
|
88
|
-
const udlLifecycleTransitionSchema = z.strictObject({
|
|
89
|
-
from: z.array(udlSnakeCaseSchema).min(1),
|
|
90
|
-
to: udlSnakeCaseSchema,
|
|
91
|
-
});
|
|
92
|
-
const udlLifecycleSchema = z.strictObject({
|
|
93
|
-
initial: udlSnakeCaseSchema,
|
|
94
|
-
states: z.array(udlSnakeCaseSchema).min(1),
|
|
95
|
-
transitions: z.record(udlActionNameSchema, udlLifecycleTransitionSchema),
|
|
96
|
-
});
|
|
97
|
-
const udlUpdatePolicySchema = z.strictObject({
|
|
98
|
-
examples: z.array(udlExampleSchema).optional(),
|
|
99
|
-
fields: z.array(udlFieldNameSchema).min(1),
|
|
100
|
-
states: z.array(udlSnakeCaseSchema).min(1),
|
|
101
|
-
});
|
|
102
|
-
const udlDateComparisonOperatorSchema = z.enum([">=", ">", "<=", "<", "=="]);
|
|
103
|
-
const udlDateComparisonSchema = z.strictObject({
|
|
104
|
-
localPath: fieldPathSchema,
|
|
105
|
-
operator: udlDateComparisonOperatorSchema,
|
|
106
|
-
referencedPath: fieldPathSchema,
|
|
107
|
-
});
|
|
108
|
-
const udlStoredFieldSchema = z.strictObject({ field: udlFieldNameSchema });
|
|
109
|
-
const udlOffsetSchema = z.union([nonEmptyTextSchema, udlStoredFieldSchema]);
|
|
110
|
-
const udlAttestationSchema = z.strictObject({
|
|
111
|
-
forAction: udlActionNameSchema.optional(),
|
|
112
|
-
action: instanceValuePathSchema,
|
|
113
|
-
digest: instanceValuePathSchema,
|
|
114
|
-
role: instanceValuePathSchema,
|
|
115
|
-
expiresAt: instanceValuePathSchema,
|
|
116
|
-
instrument: instanceValuePathSchema,
|
|
117
|
-
party: z.string().regex(/^[a-z][A-Za-z0-9_]*$/),
|
|
118
|
-
consume: udlActionNameSchema,
|
|
119
|
-
});
|
|
120
|
-
const udlGateSchema = z.strictObject({
|
|
121
|
-
attests: udlAttestationSchema.optional(),
|
|
122
|
-
/** Local field key <- referenced instance path; create actions only. */
|
|
123
|
-
bind: z.record(udlFieldNameSchema, fieldPathSchema).optional(),
|
|
124
|
-
dateComparison: udlDateComparisonSchema.optional(),
|
|
125
|
-
dueBefore: z
|
|
126
|
-
.strictObject({ field: udlFieldNameSchema, offset: nonEmptyTextSchema })
|
|
127
|
-
.optional(),
|
|
128
|
-
field: udlFieldNameSchema,
|
|
129
|
-
/** Local instance path === referenced instance path at admission. */
|
|
130
|
-
match: z.record(fieldPathSchema, fieldPathSchema).optional(),
|
|
131
|
-
/** Opt-in over an optional reference field: absent passes, set is held to the clause. */
|
|
13
|
+
.regex(/^[a-z][a-zA-Z0-9_]*(?:\.[a-z][a-zA-Z0-9_]*)*$/)
|
|
14
|
+
.max(240);
|
|
15
|
+
const instrumentId = name.meta({ "x-udl-reference": "instrument" });
|
|
16
|
+
/** Currency belongs to the document. Accounts and amounts cannot override it. */
|
|
17
|
+
export const udlPartySchema = z.strictObject({
|
|
18
|
+
kind: z.enum(["person", "business", "staff"]),
|
|
19
|
+
role: name.optional(),
|
|
20
|
+
});
|
|
21
|
+
const fieldBase = {
|
|
22
|
+
name,
|
|
132
23
|
optional: z.literal(true).optional(),
|
|
133
|
-
|
|
134
|
-
/** One dependent ever per referenced instance; create actions only. */
|
|
135
|
-
unique: z
|
|
136
|
-
.union([
|
|
137
|
-
z.literal(true),
|
|
138
|
-
z.strictObject({
|
|
139
|
-
namespace: udlSnakeCaseSchema,
|
|
140
|
-
byFields: z.array(udlFieldNameSchema).min(1).max(8),
|
|
141
|
-
}),
|
|
142
|
-
])
|
|
143
|
-
.optional(),
|
|
144
|
-
});
|
|
145
|
-
const udlBindingSchema = z.discriminatedUnion("from", [
|
|
146
|
-
z.strictObject({ from: z.literal("const"), value: z.string() }),
|
|
147
|
-
z.strictObject({ from: z.literal("instance"), path: fieldPathSchema }),
|
|
148
|
-
z.strictObject({ from: z.literal("input"), path: fieldPathSchema }),
|
|
149
|
-
]);
|
|
150
|
-
const udlStepOperationSchema = z.enum([
|
|
151
|
-
"account.escrow.provision",
|
|
152
|
-
"account.freeze",
|
|
153
|
-
"account.unfreeze",
|
|
154
|
-
]);
|
|
155
|
-
const udlMoveOperationSchema = z.enum([
|
|
156
|
-
"internal_transfer.create",
|
|
157
|
-
"internal_transfer.reserve",
|
|
158
|
-
"internal_transfer.post",
|
|
159
|
-
"internal_transfer.void",
|
|
160
|
-
]);
|
|
161
|
-
export const udlKernelOperationSchema = z.enum([
|
|
162
|
-
...udlStepOperationSchema.options,
|
|
163
|
-
...udlMoveOperationSchema.options,
|
|
164
|
-
]);
|
|
165
|
-
const udlStepSchema = z.strictObject({
|
|
166
|
-
bind: z.record(fieldPathSchema, udlBindingSchema),
|
|
167
|
-
capture: stringMapSchema.optional(),
|
|
168
|
-
operation: udlStepOperationSchema,
|
|
169
|
-
});
|
|
170
|
-
const udlMoveSchema = z.strictObject({
|
|
171
|
-
bind: z.record(fieldPathSchema, udlBindingSchema),
|
|
172
|
-
capture: stringMapSchema.optional(),
|
|
173
|
-
key: udlSnakeCaseSchema,
|
|
174
|
-
operation: udlMoveOperationSchema,
|
|
175
|
-
});
|
|
176
|
-
const udlDueRecurrenceSchema = z.strictObject({
|
|
177
|
-
countField: udlFieldNameSchema.optional(),
|
|
178
|
-
delinquency: z.literal("parent_policy").optional(),
|
|
179
|
-
drainAction: udlActionNameSchema.optional(),
|
|
180
|
-
period: z.union([
|
|
181
|
-
nonEmptyTextSchema,
|
|
182
|
-
z.strictObject({
|
|
183
|
-
calendar: z.enum(["gregorian", "hijri"]),
|
|
184
|
-
monthEnd: z.literal("clamp_to_last_day"),
|
|
185
|
-
months: z.number().int().positive(),
|
|
186
|
-
}),
|
|
187
|
-
]),
|
|
188
|
-
liability: z.literal("one_open").optional(),
|
|
189
|
-
untilAction: udlActionNameSchema.optional(),
|
|
190
|
-
untilField: udlFieldNameSchema.optional(),
|
|
191
|
-
});
|
|
192
|
-
const udlDueParentStatusSchema = z.strictObject({
|
|
193
|
-
instrumentId: udlInstrumentIdSchema,
|
|
194
|
-
refField: udlFieldNameSchema,
|
|
195
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
196
|
-
});
|
|
197
|
-
const udlDueSchema = z.strictObject({
|
|
198
|
-
every: udlDueRecurrenceSchema.optional(),
|
|
199
|
-
field: udlFieldNameSchema,
|
|
200
|
-
offset: udlOffsetSchema.optional(),
|
|
201
|
-
whenParentStatus: udlDueParentStatusSchema.optional(),
|
|
202
|
-
});
|
|
203
|
-
const udlDeadlineSchema = z.strictObject({
|
|
204
|
-
field: udlFieldNameSchema,
|
|
205
|
-
offset: udlOffsetSchema.optional(),
|
|
206
|
-
});
|
|
207
|
-
const udlSetsAtSchema = z.strictObject({
|
|
208
|
-
field: udlFieldNameSchema,
|
|
209
|
-
marker: z.literal(true).optional(),
|
|
210
|
-
offset: nonEmptyTextSchema,
|
|
211
|
-
});
|
|
212
|
-
const udlQuoteChargeSchema = z.strictObject({
|
|
213
|
-
bps: z.number().int().min(0).max(9_999),
|
|
214
|
-
withinOffset: nonEmptyTextSchema.optional(),
|
|
215
|
-
});
|
|
216
|
-
export const udlQuoteRetainedRoleSchema = z.enum([
|
|
217
|
-
"payer",
|
|
218
|
-
"beneficiary",
|
|
219
|
-
"subjectHolder",
|
|
220
|
-
]);
|
|
221
|
-
// A priced, expiring offer. The quoting action splits `baseField` into a charge
|
|
222
|
-
// and a net at its own clock, freezes the fields the price was read from, and
|
|
223
|
-
// stamps an expiry. Only the paired `commit` action may spend the offer, and
|
|
224
|
-
// only while it is unexpired and its frozen fields still hold.
|
|
225
|
-
const udlQuoteShape = {
|
|
226
|
-
/** Date-time whose remaining time picks the charge tier; omit for elapsed age. */
|
|
227
|
-
anchorField: udlFieldNameSchema.optional(),
|
|
228
|
-
baseField: udlFieldNameSchema,
|
|
229
|
-
chargeRef: udlFieldNameSchema,
|
|
230
|
-
/** Party role that keeps the quoted charge instead of moving it through an escrow payout action. */
|
|
231
|
-
chargeRetainedBy: udlQuoteRetainedRoleSchema.optional(),
|
|
232
|
-
charges: z.array(udlQuoteChargeSchema).min(1),
|
|
233
|
-
/** Fixed ISO-8601 duration from the quoting action, or a stored deadline. */
|
|
234
|
-
expires: z.union([
|
|
235
|
-
z.strictObject({ field: udlFieldNameSchema }),
|
|
236
|
-
z.strictObject({ offset: nonEmptyTextSchema }),
|
|
237
|
-
]),
|
|
238
|
-
fixes: z.array(udlFieldNameSchema).min(1),
|
|
239
|
-
netDestinationField: udlFieldNameSchema,
|
|
240
|
-
netRef: udlFieldNameSchema,
|
|
24
|
+
description: text.optional(),
|
|
241
25
|
};
|
|
242
|
-
const
|
|
243
|
-
/**
|
|
244
|
-
* Where a quoting action stamps the instant its offer stops being committable.
|
|
245
|
-
* Derived from the author's net ref rather than a fixed name, so two offers on
|
|
246
|
-
* one instrument never share the slot.
|
|
247
|
-
*/
|
|
248
|
-
export function quoteExpiresAtRefKey(quote) {
|
|
249
|
-
return `${quote.netRef}ExpiresAt`;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Where a quoting action stamps the fingerprint of the field values it froze.
|
|
253
|
-
* The committing action recomputes it against the live fields, which is how an
|
|
254
|
-
* offer priced on one set of terms refuses to pay out against another.
|
|
255
|
-
*/
|
|
256
|
-
export function quoteFrozenRefKey(quote) {
|
|
257
|
-
return `${quote.netRef}Frozen`;
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Every ref key one quote seeds: the charge and the net the author named, plus
|
|
261
|
-
* the two the machinery derives to hold the offer itself. One derivation, read
|
|
262
|
-
* by the validator, the compiler, and the runtime alike.
|
|
263
|
-
*/
|
|
264
|
-
export function quoteSeededRefKeys(quote) {
|
|
265
|
-
return [
|
|
266
|
-
quote.chargeRef,
|
|
267
|
-
quote.netRef,
|
|
268
|
-
quoteExpiresAtRefKey(quote),
|
|
269
|
-
quoteFrozenRefKey(quote),
|
|
270
|
-
];
|
|
271
|
-
}
|
|
272
|
-
const udlDecisionSchema = z.strictObject({
|
|
273
|
-
capability: udlProviderFamilyIdSchema,
|
|
274
|
-
deadlineMs: z.number().int().positive().max(15_000),
|
|
275
|
-
// A decision that never came back is not an approval. `approve` would let a
|
|
276
|
-
// document release money because a counterparty went quiet, so the grammar
|
|
277
|
-
// admits only the fail-closed answer. Every published document already
|
|
278
|
-
// writes `decline`; widening later is additive, narrowing later would not
|
|
279
|
-
// be.
|
|
280
|
-
onTimeout: z.literal("decline"),
|
|
281
|
-
});
|
|
282
|
-
const udlAggregateCheckSchema = z.discriminatedUnion("kind", [
|
|
26
|
+
export const udlFieldSchema = z.discriminatedUnion("type", [
|
|
283
27
|
z.strictObject({
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
28
|
+
...fieldBase,
|
|
29
|
+
type: z.literal("money"),
|
|
30
|
+
value: amount.optional(),
|
|
31
|
+
minimum: amount.optional(),
|
|
32
|
+
maximum: amount.optional(),
|
|
287
33
|
}),
|
|
288
34
|
z.strictObject({
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
35
|
+
...fieldBase,
|
|
36
|
+
type: z.literal("account"),
|
|
37
|
+
owner: name,
|
|
38
|
+
key: name.optional(),
|
|
39
|
+
book: z.enum(["cash", "claim"]).default("cash"),
|
|
40
|
+
contra: z.literal(true).optional(),
|
|
41
|
+
external: z.literal(true).optional(),
|
|
292
42
|
}),
|
|
293
43
|
z.strictObject({
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
44
|
+
...fieldBase,
|
|
45
|
+
type: z.literal("ref"),
|
|
46
|
+
target: z.union([instrumentId, z.array(instrumentId).min(1).max(16)]),
|
|
297
47
|
}),
|
|
298
|
-
// Siblings summed against a cap read from the LOCKED anchor row's
|
|
299
|
-
// machinery-seeded ref (never a stored field on the counted rows).
|
|
300
48
|
z.strictObject({
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
49
|
+
...fieldBase,
|
|
50
|
+
type: z.literal("date"),
|
|
51
|
+
value: z.iso.datetime({ offset: true }).optional(),
|
|
304
52
|
}),
|
|
305
53
|
z.strictObject({
|
|
306
|
-
|
|
307
|
-
|
|
54
|
+
...fieldBase,
|
|
55
|
+
type: z.literal("duration"),
|
|
56
|
+
value: integer.positive().optional(),
|
|
308
57
|
}),
|
|
309
58
|
z.strictObject({
|
|
310
|
-
|
|
311
|
-
|
|
59
|
+
...fieldBase,
|
|
60
|
+
type: z.literal("text"),
|
|
61
|
+
value: text.optional(),
|
|
62
|
+
maxLength: integer.positive().max(2048).optional(),
|
|
312
63
|
}),
|
|
313
64
|
z.strictObject({
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
65
|
+
...fieldBase,
|
|
66
|
+
type: z.literal("integer"),
|
|
67
|
+
value: integer.optional(),
|
|
68
|
+
minimum: integer.optional(),
|
|
69
|
+
maximum: integer.optional(),
|
|
317
70
|
}),
|
|
318
71
|
z.strictObject({
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
datesField: udlFieldNameSchema,
|
|
323
|
-
amounts: z
|
|
324
|
-
.array(z.strictObject({
|
|
325
|
-
amountField: udlFieldNameSchema,
|
|
326
|
-
totalField: udlFieldNameSchema,
|
|
327
|
-
}))
|
|
328
|
-
.min(1)
|
|
329
|
-
.max(8),
|
|
330
|
-
remainder: z.literal("first"),
|
|
72
|
+
...fieldBase,
|
|
73
|
+
type: z.literal("percent"),
|
|
74
|
+
value: integer.min(0).max(10000).optional(),
|
|
331
75
|
}),
|
|
332
|
-
z.strictObject({ kind: z.literal("all_in") }),
|
|
333
76
|
z.strictObject({
|
|
334
|
-
|
|
335
|
-
|
|
77
|
+
...fieldBase,
|
|
78
|
+
type: z.literal("boolean"),
|
|
79
|
+
value: z.boolean().optional(),
|
|
80
|
+
}),
|
|
81
|
+
z.strictObject({
|
|
82
|
+
...fieldBase,
|
|
83
|
+
type: z.literal("enum"),
|
|
84
|
+
values: z.array(name).min(1).max(64),
|
|
85
|
+
value: name.optional(),
|
|
86
|
+
}),
|
|
87
|
+
z.strictObject({
|
|
88
|
+
...fieldBase,
|
|
89
|
+
type: z.literal("list"),
|
|
90
|
+
item: z.enum(["money", "date", "text", "integer", "ref"]),
|
|
91
|
+
target: instrumentId.optional(),
|
|
92
|
+
maxItems: integer.min(1).max(366),
|
|
336
93
|
}),
|
|
337
94
|
]);
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
95
|
+
/** Values are constants or resolved typed paths, never executable strings. */
|
|
96
|
+
export const udlValueSchema = z.union([
|
|
97
|
+
z.strictObject({ literal: scalar }),
|
|
98
|
+
z.strictObject({ field: path }),
|
|
99
|
+
]);
|
|
100
|
+
const value = udlValueSchema;
|
|
101
|
+
const values = z.array(value).min(1).max(256);
|
|
102
|
+
const selection = z.strictObject({
|
|
103
|
+
instrument: z.union([instrumentId, z.array(instrumentId).min(1).max(16)]),
|
|
104
|
+
reference: name,
|
|
105
|
+
anchor: path,
|
|
106
|
+
states: z.array(name).min(1).max(64),
|
|
107
|
+
limit: integer.min(1).max(366),
|
|
108
|
+
order: z.array(path).min(1).max(4).optional(),
|
|
109
|
+
window: z
|
|
110
|
+
.strictObject({ field: name, milliseconds: integer.positive() })
|
|
111
|
+
.optional(),
|
|
112
|
+
where: z
|
|
113
|
+
.record(path, value)
|
|
114
|
+
.refine((filters) => Object.keys(filters).length <= 8, "at most eight selection filters")
|
|
115
|
+
.meta({ maxProperties: 8 })
|
|
345
116
|
.optional(),
|
|
346
|
-
check: udlAggregateCheckSchema,
|
|
347
|
-
instrumentId: udlInstrumentIdSchema.optional(),
|
|
348
|
-
over: z.enum(["children", "siblings"]),
|
|
349
|
-
refField: udlFieldNameSchema,
|
|
350
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
351
|
-
});
|
|
352
|
-
const udlExposureRequirementSchema = z.strictObject({
|
|
353
|
-
groupField: udlFieldNameSchema.optional(),
|
|
354
|
-
minimumField: udlFieldNameSchema.optional(),
|
|
355
|
-
measure: z.strictObject({ allocation: udlSnakeCaseSchema }).optional(),
|
|
356
|
-
amountField: udlFieldNameSchema,
|
|
357
|
-
anchorField: udlFieldNameSchema,
|
|
358
|
-
capField: udlFieldNameSchema,
|
|
359
|
-
capOnAnchor: z.literal(true).optional(),
|
|
360
|
-
childInstrumentId: udlInstrumentIdSchema,
|
|
361
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
362
|
-
});
|
|
363
|
-
// The tenant-backend decision port: the action's caller asserts the acting
|
|
364
|
-
// party, checked at admission against the instrument's party bindings for the
|
|
365
|
-
// allowed roles.
|
|
366
|
-
const udlPartyRoleSchema = z.string().regex(/^[a-z][A-Za-z0-9_]*$/);
|
|
367
|
-
const udlPortSchema = z.strictObject({
|
|
368
|
-
allowedParties: z.array(udlPartyRoleSchema).min(1),
|
|
369
|
-
capture: udlFieldNameSchema.optional(),
|
|
370
|
-
});
|
|
371
|
-
const udlPayoutSchema = z.strictObject({
|
|
372
|
-
amount: instanceValuePathSchema,
|
|
373
|
-
beneficiaryField: udlFieldNameSchema,
|
|
374
|
-
beneficiaryPartyField: udlFieldNameSchema,
|
|
375
|
-
capture: udlFieldNameSchema,
|
|
376
|
-
currencyField: udlFieldNameSchema,
|
|
377
|
-
sourceAccountField: udlFieldNameSchema,
|
|
378
|
-
speed: z.literal("standard"),
|
|
379
117
|
});
|
|
380
|
-
/**
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
*/
|
|
388
|
-
const udlReconcileSchema = z.strictObject({
|
|
389
|
-
/** `fields.<name>` or `refs.<name>`: the money this action says will land. */
|
|
390
|
-
amount: instanceValuePathSchema,
|
|
391
|
-
/** Where the matched evidence id lands in refs. */
|
|
392
|
-
capture: udlFieldNameSchema,
|
|
393
|
-
/** The ref naming the provider-side row the evidence must cite. */
|
|
394
|
-
counterpartyRef: udlFieldNameSchema,
|
|
395
|
-
currencyField: udlFieldNameSchema,
|
|
396
|
-
direction: z.enum(["credit", "debit"]),
|
|
397
|
-
/** Exactly one source. A reconcile never reads two ledgers at once. */
|
|
398
|
-
evidence: z.enum(["movement", "provider_confirmation", "statement_line"]),
|
|
399
|
-
/**
|
|
400
|
-
* Where an expectation that never matched lands. The named child instrument
|
|
401
|
-
* carries the break, and `maxOpen` caps how many of them one instance may
|
|
402
|
-
* hold open at once, the same count measure the aggregate invariants use.
|
|
403
|
-
*/
|
|
404
|
-
exception: z.strictObject({
|
|
405
|
-
amountField: udlFieldNameSchema,
|
|
406
|
-
childInstrumentId: udlInstrumentIdSchema,
|
|
407
|
-
maxOpen: z.number().int().min(1).max(1_000),
|
|
408
|
-
reasonField: udlFieldNameSchema,
|
|
409
|
-
refField: udlFieldNameSchema,
|
|
118
|
+
/** A finite, ordered calculation graph. Every result is a declared field. */
|
|
119
|
+
export const udlCalculationSchema = z.discriminatedUnion("op", [
|
|
120
|
+
z.strictObject({
|
|
121
|
+
target: name,
|
|
122
|
+
op: z.literal("at"),
|
|
123
|
+
list: path,
|
|
124
|
+
position: value,
|
|
410
125
|
}),
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
match: z.discriminatedUnion("law", [
|
|
417
|
-
z.strictObject({ law: z.literal("exact") }),
|
|
418
|
-
z.strictObject({
|
|
419
|
-
dial: udlSnakeCaseSchema,
|
|
420
|
-
law: z.literal("tolerance"),
|
|
421
|
-
minorUnits: z.number().int().positive(),
|
|
422
|
-
}),
|
|
423
|
-
z.strictObject({ law: z.literal("window") }),
|
|
424
|
-
]),
|
|
425
|
-
/** Fixed ISO-8601 duration from the expecting action, or a stored deadline. */
|
|
426
|
-
within: z.union([
|
|
427
|
-
z.strictObject({ field: udlFieldNameSchema }),
|
|
428
|
-
z.strictObject({ offset: nonEmptyTextSchema }),
|
|
429
|
-
]),
|
|
430
|
-
});
|
|
431
|
-
const udlSignedSumSourceSchema = z.strictObject({
|
|
432
|
-
amountField: udlFieldNameSchema,
|
|
433
|
-
instrumentId: udlInstrumentIdSchema,
|
|
434
|
-
refField: udlFieldNameSchema,
|
|
435
|
-
sign: z.enum(["add", "subtract"]),
|
|
436
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
437
|
-
subtotalRef: udlFieldNameSchema,
|
|
438
|
-
});
|
|
439
|
-
const udlSignedSumSchema = z.strictObject({
|
|
440
|
-
amountRef: udlFieldNameSchema,
|
|
441
|
-
onNegative: z.literal("refuse"),
|
|
442
|
-
onZero: z.enum(["refuse", "skip_steps"]),
|
|
443
|
-
sources: z.array(udlSignedSumSourceSchema).min(1),
|
|
444
|
-
});
|
|
445
|
-
const udlDistributeSchema = z.strictObject({
|
|
446
|
-
amountRef: udlFieldNameSchema,
|
|
447
|
-
onZero: z.enum(["refuse", "skip_steps"]),
|
|
448
|
-
pool: z.strictObject({
|
|
449
|
-
from: z.literal("parent"),
|
|
450
|
-
path: fieldPathSchema,
|
|
126
|
+
z.strictObject({
|
|
127
|
+
target: name,
|
|
128
|
+
op: z.literal("aggregate"),
|
|
129
|
+
selection,
|
|
130
|
+
measure: z.union([z.literal("count"), z.strictObject({ sum: path })]),
|
|
451
131
|
}),
|
|
452
|
-
refField: udlFieldNameSchema,
|
|
453
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
454
|
-
weightField: udlFieldNameSchema,
|
|
455
|
-
});
|
|
456
|
-
const udlRemainderCollectedSchema = z.strictObject({
|
|
457
|
-
amountField: udlFieldNameSchema,
|
|
458
|
-
instrumentId: udlInstrumentIdSchema,
|
|
459
|
-
path: z.literal("refs").optional(),
|
|
460
|
-
refField: udlFieldNameSchema,
|
|
461
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
462
|
-
});
|
|
463
|
-
const udlRemainderSchema = z.strictObject({
|
|
464
|
-
accumulateRef: udlFieldNameSchema.optional(),
|
|
465
|
-
amountRef: udlFieldNameSchema,
|
|
466
|
-
collected: z.array(udlRemainderCollectedSchema).optional(),
|
|
467
|
-
inputKey: udlFieldNameSchema.optional(),
|
|
468
|
-
onZero: z.enum(["refuse", "skip_steps"]),
|
|
469
|
-
totalPath: instanceValuePathSchema,
|
|
470
|
-
subtractPaths: z.array(instanceValuePathSchema).min(1).max(16).optional(),
|
|
471
|
-
});
|
|
472
|
-
const udlCheckRequirementVariants = udlCheckEvidenceProfiles.map((profile) => z.strictObject({
|
|
473
|
-
checkKind: z.literal(profile.checkKind),
|
|
474
|
-
family: z.literal(profile.family),
|
|
475
|
-
maxAge: nonEmptyTextSchema.optional(),
|
|
476
|
-
statuses: z.array(z.enum(profile.statuses)).min(1),
|
|
477
|
-
subjectField: udlFieldNameSchema,
|
|
478
|
-
}));
|
|
479
|
-
const udlCheckRequirementSchema = z.union(udlCheckRequirementVariants);
|
|
480
|
-
const udlDialSchema = z.discriminatedUnion("kind", [
|
|
481
132
|
z.strictObject({
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
title: nonEmptyTextSchema,
|
|
133
|
+
target: name,
|
|
134
|
+
op: z.literal("ratio"),
|
|
135
|
+
amount: value,
|
|
136
|
+
numerator: value,
|
|
137
|
+
denominator: value,
|
|
138
|
+
rounding: z.literal("floor"),
|
|
489
139
|
}),
|
|
140
|
+
z.strictObject({ target: name, op: z.literal("sum"), values }),
|
|
490
141
|
z.strictObject({
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
minMs: z.number().int().positive().max(15_000).optional(),
|
|
496
|
-
summary: nonEmptyTextSchema,
|
|
497
|
-
title: nonEmptyTextSchema,
|
|
142
|
+
target: name,
|
|
143
|
+
op: z.literal("subtract"),
|
|
144
|
+
base: value,
|
|
145
|
+
subtract: values,
|
|
498
146
|
}),
|
|
499
147
|
z.strictObject({
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
title: nonEmptyTextSchema,
|
|
148
|
+
target: name,
|
|
149
|
+
op: z.literal("rate"),
|
|
150
|
+
base: value,
|
|
151
|
+
bps: value,
|
|
152
|
+
rounding: z.literal("floor"),
|
|
506
153
|
}),
|
|
154
|
+
z.strictObject({ target: name, op: z.literal("minimum"), values }),
|
|
507
155
|
z.strictObject({
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
156
|
+
target: name,
|
|
157
|
+
op: z.literal("multiply"),
|
|
158
|
+
amount: value,
|
|
159
|
+
units: value,
|
|
512
160
|
}),
|
|
513
|
-
]);
|
|
514
|
-
// A same-instance conservation law: the piece fields (money, minor units)
|
|
515
|
-
// must sum exactly to the total field; admission refuses a create whose
|
|
516
|
-
// pieces diverge.
|
|
517
|
-
// A composition-level dial. Instrument dials tune one instrument's frozen slots;
|
|
518
|
-
// this one is a property of the whole product, so it hangs off the document.
|
|
519
|
-
// `confirmation_threshold` carries minor units of the kernel currency: a
|
|
520
|
-
// money-moving tool call whose declared money inputs sum below the configured
|
|
521
|
-
// value skips the explicit confirmation argument.
|
|
522
|
-
const udlCompositionDialSchema = z.strictObject({
|
|
523
|
-
key: udlSnakeCaseSchema,
|
|
524
|
-
kind: z.literal("confirmation_threshold"),
|
|
525
|
-
maxMinor: z.number().int().positive().max(1_000_000_000_000).optional(),
|
|
526
|
-
summary: nonEmptyTextSchema,
|
|
527
|
-
title: nonEmptyTextSchema,
|
|
528
|
-
});
|
|
529
|
-
const udlPartitionSchema = z.strictObject({
|
|
530
|
-
pieceFields: z.array(udlFieldNameSchema).min(2),
|
|
531
|
-
totalField: udlFieldNameSchema,
|
|
532
|
-
});
|
|
533
|
-
const udlDerivedAmountSchema = z.strictObject({
|
|
534
|
-
field: udlFieldNameSchema,
|
|
535
|
-
rounding: z.literal("floor"),
|
|
536
|
-
rule: z.discriminatedUnion("kind", [
|
|
537
|
-
z.strictObject({
|
|
538
|
-
bps: z.union([z.number().int().min(1).max(9_999), udlStoredFieldSchema]),
|
|
539
|
-
kind: z.literal("percentage_of"),
|
|
540
|
-
}),
|
|
541
|
-
z.strictObject({
|
|
542
|
-
kind: z.literal("minimum"),
|
|
543
|
-
capField: udlFieldNameSchema,
|
|
544
|
-
}),
|
|
545
|
-
]),
|
|
546
|
-
sourceField: udlFieldNameSchema,
|
|
547
|
-
});
|
|
548
|
-
const udlFeeLeafRuleSchema = z.discriminatedUnion("kind", [
|
|
549
161
|
z.strictObject({
|
|
550
|
-
|
|
551
|
-
|
|
162
|
+
target: name,
|
|
163
|
+
op: z.literal("divide"),
|
|
164
|
+
amount: value,
|
|
165
|
+
divisor: value,
|
|
166
|
+
rounding: z.literal("floor"),
|
|
552
167
|
}),
|
|
553
168
|
z.strictObject({
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
169
|
+
target: name,
|
|
170
|
+
op: z.literal("shift"),
|
|
171
|
+
date: value,
|
|
172
|
+
milliseconds: value,
|
|
173
|
+
direction: z.enum(["before", "after"]),
|
|
557
174
|
}),
|
|
558
175
|
]);
|
|
559
|
-
const
|
|
560
|
-
.string()
|
|
561
|
-
.regex(/^(0|[1-9][0-9]*)$/, "must be a nonnegative decimal integer");
|
|
562
|
-
const udlFeeRuleSchema = z.strictObject({
|
|
563
|
-
amountField: udlFieldNameSchema,
|
|
564
|
-
baseField: udlFieldNameSchema,
|
|
565
|
-
bearerField: udlFieldNameSchema,
|
|
566
|
-
position: z.enum(["carved", "on_top"]),
|
|
567
|
-
rule: z.discriminatedUnion("kind", [
|
|
568
|
-
...udlFeeLeafRuleSchema.options,
|
|
569
|
-
z.strictObject({
|
|
570
|
-
kind: z.literal("tiered"),
|
|
571
|
-
tiers: z
|
|
572
|
-
.array(z.strictObject({
|
|
573
|
-
fromInclusive: nonNegativeDecimalIntegerSchema,
|
|
574
|
-
rule: udlFeeLeafRuleSchema,
|
|
575
|
-
toExclusive: nonNegativeDecimalIntegerSchema.optional(),
|
|
576
|
-
}))
|
|
577
|
-
.min(1)
|
|
578
|
-
.max(16),
|
|
579
|
-
}),
|
|
580
|
-
]),
|
|
581
|
-
});
|
|
582
|
-
const udlDecidedAmountSchema = z.strictObject({
|
|
583
|
-
boundField: udlFieldNameSchema,
|
|
584
|
-
field: udlFieldNameSchema,
|
|
585
|
-
remainderAction: udlActionNameSchema,
|
|
586
|
-
});
|
|
587
|
-
const udlEffectRowSchema = z.strictObject({
|
|
588
|
-
signature: nonEmptyTextSchema,
|
|
589
|
-
source: nonEmptyTextSchema,
|
|
590
|
-
});
|
|
591
|
-
const udlNotifyEffectSchema = z.strictObject({
|
|
592
|
-
channel: udlSnakeCaseSchema,
|
|
593
|
-
role: udlSnakeCaseSchema,
|
|
594
|
-
signature: nonEmptyTextSchema,
|
|
595
|
-
source: nonEmptyTextSchema,
|
|
596
|
-
});
|
|
597
|
-
const udlEffectsShape = {
|
|
598
|
-
decides: z.array(udlEffectRowSchema).min(1).optional(),
|
|
599
|
-
holds: z.array(udlEffectRowSchema).min(1).optional(),
|
|
600
|
-
moves: z.array(udlEffectRowSchema).min(1).optional(),
|
|
601
|
-
notifies: z.array(udlNotifyEffectSchema).min(1).optional(),
|
|
602
|
-
reads: z.array(udlEffectRowSchema).min(1).optional(),
|
|
603
|
-
schedules: z.array(udlEffectRowSchema).min(1).optional(),
|
|
604
|
-
};
|
|
605
|
-
const udlEffectsSchema = z.strictObject(udlEffectsShape);
|
|
606
|
-
export const udlPieceSchema = z.strictObject({
|
|
607
|
-
amount: udlFieldNameSchema,
|
|
608
|
-
id: udlSnakeCaseSchema,
|
|
609
|
-
refund_to: udlFieldNameSchema,
|
|
610
|
-
release_to: udlFieldNameSchema,
|
|
611
|
-
});
|
|
612
|
-
export const udlPiecePlanSchema = z.strictObject({
|
|
613
|
-
fund_order: z.array(udlSnakeCaseSchema),
|
|
614
|
-
id: udlSnakeCaseSchema,
|
|
615
|
-
pieces: z.array(udlPieceSchema).min(1).max(256),
|
|
616
|
-
refund_order: z.array(udlSnakeCaseSchema),
|
|
617
|
-
release_order: z.array(udlSnakeCaseSchema),
|
|
618
|
-
total: udlFieldNameSchema,
|
|
619
|
-
unfund_order: z.array(udlSnakeCaseSchema),
|
|
620
|
-
});
|
|
621
|
-
export const udlPieceStageStageSchema = z.enum([
|
|
622
|
-
"fund",
|
|
623
|
-
"release",
|
|
624
|
-
"refund",
|
|
625
|
-
"unfund",
|
|
626
|
-
]);
|
|
627
|
-
export const udlPieceStageSchema = z.strictObject({
|
|
628
|
-
plan: udlSnakeCaseSchema,
|
|
629
|
-
stage: udlPieceStageStageSchema,
|
|
630
|
-
});
|
|
631
|
-
export const udlCallSchema = z.strictObject({
|
|
632
|
-
action: z
|
|
633
|
-
.string()
|
|
634
|
-
.regex(/^[a-z][a-z0-9_]*\.[a-z][a-z0-9_]*$/, "must name an action as library_id.action_id"),
|
|
635
|
-
bind: z.record(udlFieldNameSchema, z.string()),
|
|
636
|
-
id: udlSnakeCaseSchema,
|
|
637
|
-
});
|
|
638
|
-
export const udlPrivateParameterKindSchema = z.enum([
|
|
639
|
-
"account",
|
|
640
|
-
"instance",
|
|
641
|
-
"money",
|
|
642
|
-
"piece",
|
|
643
|
-
"text",
|
|
644
|
-
]);
|
|
645
|
-
export const udlPrivateParameterSchema = z.strictObject({
|
|
646
|
-
currency: z.string().optional(),
|
|
647
|
-
kind: udlPrivateParameterKindSchema,
|
|
648
|
-
});
|
|
649
|
-
export const udlPrivateLeafSchema = z.strictObject({
|
|
650
|
-
bind: z.record(fieldPathSchema, z.string()),
|
|
651
|
-
capture: stringMapSchema.optional(),
|
|
652
|
-
effects: z
|
|
653
|
-
.array(z.strictObject({
|
|
654
|
-
kind: z.enum(udlEffectKinds),
|
|
655
|
-
signature: nonEmptyTextSchema,
|
|
656
|
-
}))
|
|
657
|
-
.min(1, "must declare at least one effect"),
|
|
658
|
-
evidence: nonEmptyTextSchema,
|
|
659
|
-
id: udlSnakeCaseSchema,
|
|
660
|
-
operation: udlKernelOperationSchema,
|
|
661
|
-
});
|
|
662
|
-
export const udlPrivateActionSchema = z.strictObject({
|
|
663
|
-
approval: z.enum(["inherit", "independent"]),
|
|
664
|
-
calls: z.array(udlCallSchema),
|
|
665
|
-
leaves: z.array(udlPrivateLeafSchema),
|
|
666
|
-
order: z.array(udlSnakeCaseSchema),
|
|
667
|
-
parameters: z.record(udlFieldNameSchema, udlPrivateParameterSchema),
|
|
668
|
-
principal: z.enum(["api_key", "user_session"]),
|
|
669
|
-
recovery: z.enum(["local", "external"]),
|
|
670
|
-
});
|
|
671
|
-
export const udlActionLibraryModuleSchema = z.strictObject({
|
|
672
|
-
actionOrder: z.array(udlSnakeCaseSchema),
|
|
673
|
-
actions: z.record(udlSnakeCaseSchema, udlPrivateActionSchema),
|
|
674
|
-
});
|
|
675
|
-
export const udlActionLibrarySchema = z.record(udlSnakeCaseSchema, udlActionLibraryModuleSchema);
|
|
676
|
-
const templateParametersSchema = z.record(udlFieldNameSchema, z.union([z.string(), z.number().int(), z.boolean()]));
|
|
677
|
-
const udlAllocationBucketSchema = z.strictObject({
|
|
678
|
-
key: z.enum(["principal", "profit", "cost", "fine"]),
|
|
679
|
-
source: z.union([
|
|
680
|
-
z.strictObject({
|
|
681
|
-
from: z.literal("slice"),
|
|
682
|
-
amountField: udlFieldNameSchema,
|
|
683
|
-
destinationField: udlFieldNameSchema,
|
|
684
|
-
}),
|
|
685
|
-
z.strictObject({
|
|
686
|
-
from: z.literal("children"),
|
|
687
|
-
instrumentId: udlInstrumentIdSchema,
|
|
688
|
-
refField: udlFieldNameSchema,
|
|
689
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
690
|
-
amountField: udlFieldNameSchema,
|
|
691
|
-
destinationField: udlFieldNameSchema,
|
|
692
|
-
}),
|
|
693
|
-
z.strictObject({
|
|
694
|
-
from: z.literal("children"),
|
|
695
|
-
template: udlSnakeCaseSchema,
|
|
696
|
-
parameters: templateParametersSchema,
|
|
697
|
-
refField: udlFieldNameSchema,
|
|
698
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
699
|
-
amountField: udlFieldNameSchema,
|
|
700
|
-
destinationField: udlFieldNameSchema,
|
|
701
|
-
}),
|
|
702
|
-
]),
|
|
703
|
-
});
|
|
704
|
-
const udlAllocationSchema = z.strictObject({
|
|
705
|
-
sliceInstrumentId: udlInstrumentIdSchema,
|
|
706
|
-
sliceRefField: udlFieldNameSchema,
|
|
707
|
-
sliceStatuses: z.array(udlSnakeCaseSchema).min(1),
|
|
708
|
-
dueField: udlFieldNameSchema,
|
|
709
|
-
positionField: udlFieldNameSchema,
|
|
710
|
-
earningRuleField: udlFieldNameSchema,
|
|
711
|
-
buckets: z.array(udlAllocationBucketSchema).min(2).max(4),
|
|
712
|
-
});
|
|
713
|
-
const udlAllocateSchema = z.union([
|
|
176
|
+
export const udlRequirementSchema = z.discriminatedUnion("kind", [
|
|
714
177
|
z.strictObject({
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
178
|
+
kind: z.literal("hours"),
|
|
179
|
+
at: path,
|
|
180
|
+
start: integer.min(0).max(23),
|
|
181
|
+
end: integer.min(0).max(23),
|
|
182
|
+
timezone: text,
|
|
720
183
|
}),
|
|
721
184
|
z.strictObject({
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
sourceAccountField: udlFieldNameSchema,
|
|
727
|
-
paymentIdentityField: udlFieldNameSchema,
|
|
728
|
-
capture: udlFieldNameSchema,
|
|
185
|
+
kind: z.literal("compare"),
|
|
186
|
+
left: value,
|
|
187
|
+
operator: z.enum(["==", "!=", "<", "<=", ">", ">="]),
|
|
188
|
+
right: value,
|
|
729
189
|
}),
|
|
730
190
|
z.strictObject({
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
sourceAccountField: udlFieldNameSchema,
|
|
735
|
-
paymentIdentityField: udlFieldNameSchema,
|
|
736
|
-
capture: udlFieldNameSchema,
|
|
191
|
+
kind: z.literal("state"),
|
|
192
|
+
reference: path,
|
|
193
|
+
states: z.array(name).min(1).max(64),
|
|
737
194
|
}),
|
|
738
195
|
z.strictObject({
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
196
|
+
kind: z.literal("unique"),
|
|
197
|
+
namespace: name,
|
|
198
|
+
fields: z.array(path).min(1).max(8),
|
|
199
|
+
}),
|
|
200
|
+
z.strictObject({
|
|
201
|
+
kind: z.literal("aggregate"),
|
|
202
|
+
selection,
|
|
203
|
+
measure: z.union([z.literal("count"), z.strictObject({ sum: path })]),
|
|
204
|
+
operator: z.enum(["==", "<=", ">=", "<", ">"]),
|
|
205
|
+
value,
|
|
742
206
|
}),
|
|
743
|
-
]);
|
|
744
|
-
const udlContributionsSchema = z.strictObject({
|
|
745
|
-
field: udlFieldNameSchema,
|
|
746
|
-
amountKey: udlFieldNameSchema,
|
|
747
|
-
accountKey: udlFieldNameSchema,
|
|
748
|
-
totalField: udlFieldNameSchema,
|
|
749
|
-
});
|
|
750
|
-
// These clauses are opt-in. Absent clauses never add defaults to older documents.
|
|
751
|
-
const udlFundingSchema = z.strictObject({
|
|
752
|
-
obligationField: udlFieldNameSchema,
|
|
753
|
-
ticketInstrumentId: udlInstrumentIdSchema,
|
|
754
|
-
ticketRefField: udlFieldNameSchema,
|
|
755
|
-
ticketAmountField: udlFieldNameSchema,
|
|
756
|
-
ticketInvestorField: udlFieldNameSchema,
|
|
757
|
-
ticketAccountField: udlFieldNameSchema,
|
|
758
|
-
ticketStatus: udlSnakeCaseSchema,
|
|
759
|
-
collectAction: udlActionNameSchema,
|
|
760
|
-
principalField: udlFieldNameSchema,
|
|
761
|
-
sourceAccountPath: instanceValuePathSchema,
|
|
762
|
-
destinationAccountField: udlFieldNameSchema,
|
|
763
|
-
terms: z.record(udlFieldNameSchema, udlFieldNameSchema),
|
|
764
|
-
capture: udlFieldNameSchema,
|
|
765
|
-
});
|
|
766
|
-
const udlReceiptDistributionSchema = z.strictObject({
|
|
767
|
-
roundField: udlFieldNameSchema,
|
|
768
|
-
snapshotRef: udlFieldNameSchema,
|
|
769
|
-
receiptField: udlFieldNameSchema,
|
|
770
|
-
receiptPath: instanceValuePathSchema,
|
|
771
|
-
mode: z.enum(["cash", "loss"]),
|
|
772
|
-
feeBps: z.number().int().min(0).max(10000),
|
|
773
|
-
vatBps: z.number().int().min(0).max(10000),
|
|
774
|
-
feeAccountField: udlFieldNameSchema,
|
|
775
|
-
taxAccountField: udlFieldNameSchema,
|
|
776
|
-
residualAccountField: udlFieldNameSchema,
|
|
777
|
-
capture: udlFieldNameSchema,
|
|
778
|
-
});
|
|
779
|
-
const udlRequestAuthoritySchema = z.strictObject({
|
|
780
|
-
instrumentField: udlFieldNameSchema,
|
|
781
|
-
instanceField: udlFieldNameSchema,
|
|
782
|
-
actionField: udlFieldNameSchema,
|
|
783
|
-
inputField: udlFieldNameSchema,
|
|
784
|
-
digestField: udlFieldNameSchema,
|
|
785
|
-
roleField: udlFieldNameSchema,
|
|
786
|
-
party: udlPartyRoleSchema,
|
|
787
|
-
expiresField: udlFieldNameSchema,
|
|
788
|
-
});
|
|
789
|
-
const udlCascadeEntrySchema = z.union([
|
|
790
207
|
z.strictObject({
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
208
|
+
kind: z.literal("approval"),
|
|
209
|
+
target: path.default("self"),
|
|
210
|
+
party: name,
|
|
211
|
+
action: name.optional(),
|
|
212
|
+
decision: z.enum(["approved", "declined"]),
|
|
794
213
|
}),
|
|
795
214
|
z.strictObject({
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
215
|
+
kind: z.literal("evidence"),
|
|
216
|
+
subject: path,
|
|
217
|
+
family: name,
|
|
218
|
+
check: name,
|
|
219
|
+
result: name,
|
|
220
|
+
maxAge: integer.positive(),
|
|
800
221
|
}),
|
|
801
222
|
]);
|
|
802
|
-
const
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
.optional(),
|
|
826
|
-
engineOwned: z.literal(true).optional(),
|
|
827
|
-
captureEngine: z
|
|
828
|
-
.record(udlFieldNameSchema, z.enum(["operationId"]))
|
|
829
|
-
.optional(),
|
|
830
|
-
allocate: udlAllocateSchema.optional(),
|
|
831
|
-
contributionStage: z
|
|
832
|
-
.strictObject({
|
|
833
|
-
stage: z.enum(["fund", "refund"]),
|
|
834
|
-
accountPath: instanceValuePathSchema,
|
|
835
|
-
})
|
|
836
|
-
.optional(),
|
|
837
|
-
transitionsRefs: z
|
|
838
|
-
.array(z.strictObject({
|
|
839
|
-
field: udlFieldNameSchema,
|
|
840
|
-
action: udlActionNameSchema,
|
|
841
|
-
}))
|
|
842
|
-
.min(1)
|
|
843
|
-
.max(16)
|
|
844
|
-
.optional(),
|
|
845
|
-
cascade: z.array(udlCascadeEntrySchema).min(1).max(8).optional(),
|
|
846
|
-
agentDescription: udlAgentDescriptionSchema.optional(),
|
|
847
|
-
calls: z.array(udlCallSchema).min(1).optional(),
|
|
848
|
-
captureInput: z.record(udlFieldNameSchema, udlFieldNameSchema).optional(),
|
|
849
|
-
/** Names the quoting action whose offer this action spends. */
|
|
850
|
-
commit: udlActionNameSchema.optional(),
|
|
851
|
-
decidedAmount: udlDecidedAmountSchema.optional(),
|
|
852
|
-
deadline: udlDeadlineSchema.optional(),
|
|
853
|
-
decision: udlDecisionSchema.optional(),
|
|
854
|
-
distribute: udlDistributeSchema.optional(),
|
|
855
|
-
description: nonEmptyTextSchema.optional(),
|
|
856
|
-
due: udlDueSchema.optional(),
|
|
857
|
-
earnable: z.boolean().optional(),
|
|
858
|
-
effects: udlEffectsSchema.optional(),
|
|
859
|
-
eventName: z
|
|
860
|
-
.string()
|
|
861
|
-
.regex(eventNamePattern)
|
|
862
|
-
.meta({ "x-udl-reference": "instrument_event" })
|
|
863
|
-
.optional(),
|
|
864
|
-
examples: z.array(udlExampleSchema).min(1).optional(),
|
|
865
|
-
input: jsonObjectSchema.optional(),
|
|
866
|
-
moves: z.array(udlMoveSchema).default([]),
|
|
867
|
-
payout: udlPayoutSchema.optional(),
|
|
868
|
-
pieceStage: udlPieceStageSchema.optional(),
|
|
869
|
-
port: udlPortSchema.optional(),
|
|
870
|
-
quote: udlQuoteSchema.optional(),
|
|
871
|
-
publicAction: udlPublicActionSchema
|
|
872
|
-
.optional()
|
|
873
|
-
.describe("Author-approved public action name; the containing action key remains the lifecycle and execution identity"),
|
|
874
|
-
principal: z.literal("user_session").optional(),
|
|
875
|
-
reconcile: z.array(udlReconcileSchema).min(1).optional(),
|
|
876
|
-
remainder: udlRemainderSchema.optional(),
|
|
877
|
-
requiresAggregate: z.array(udlAggregateConditionSchema).min(1).optional(),
|
|
878
|
-
requiresChecks: z.array(udlCheckRequirementSchema).optional(),
|
|
879
|
-
requiresDrainedAccount: z.strictObject({ path: fieldPathSchema }).optional(),
|
|
880
|
-
requiresExposure: z.array(udlExposureRequirementSchema).min(1).optional(),
|
|
881
|
-
requiresRefs: z.array(udlGateSchema).min(1).optional(),
|
|
882
|
-
sandboxFailurePoint: z.enum(["funding", "release"]).optional(),
|
|
883
|
-
setsAt: udlSetsAtSchema.optional(),
|
|
884
|
-
signedSum: udlSignedSumSchema.optional(),
|
|
885
|
-
steps: z.array(udlStepSchema).default([]),
|
|
886
|
-
summary: nonEmptyTextSchema,
|
|
887
|
-
updates: z.array(udlFieldNameSchema).min(1).optional(),
|
|
888
|
-
};
|
|
889
|
-
const udlActionSchema = z.strictObject(udlActionShape);
|
|
890
|
-
const udlAggregateBaseShape = {
|
|
891
|
-
childInstrumentId: udlInstrumentIdSchema,
|
|
892
|
-
childRefField: udlFieldNameSchema,
|
|
893
|
-
childStatuses: z.array(udlSnakeCaseSchema).min(1),
|
|
894
|
-
parentField: udlFieldNameSchema,
|
|
895
|
-
};
|
|
896
|
-
// Two measures, mutually exclusive by strictness: a sum cap over a child money
|
|
897
|
-
// field, or a count cap (optionally windowed to the rolling `days` ending at
|
|
898
|
-
// the child's own as-written date-time value).
|
|
899
|
-
const udlAggregateSchema = z.union([
|
|
223
|
+
export const udlKernelOperationSchema = z.enum([
|
|
224
|
+
"internal_transfer.create",
|
|
225
|
+
"internal_transfer.reserve",
|
|
226
|
+
"internal_transfer.post",
|
|
227
|
+
"internal_transfer.void",
|
|
228
|
+
]);
|
|
229
|
+
export const udlMoveSchema = z.discriminatedUnion("operation", [
|
|
230
|
+
z.strictObject({
|
|
231
|
+
key: name,
|
|
232
|
+
operation: z.literal("internal_transfer.create"),
|
|
233
|
+
capture: name.optional(),
|
|
234
|
+
amount: value,
|
|
235
|
+
from: path,
|
|
236
|
+
to: path,
|
|
237
|
+
}),
|
|
238
|
+
z.strictObject({
|
|
239
|
+
key: name,
|
|
240
|
+
operation: z.literal("internal_transfer.reserve"),
|
|
241
|
+
amount: value,
|
|
242
|
+
from: path,
|
|
243
|
+
to: path,
|
|
244
|
+
capture: name,
|
|
245
|
+
}),
|
|
900
246
|
z.strictObject({
|
|
901
|
-
|
|
902
|
-
|
|
247
|
+
key: name,
|
|
248
|
+
operation: z.literal("internal_transfer.post"),
|
|
249
|
+
capture: name.optional(),
|
|
250
|
+
transfer: path,
|
|
903
251
|
}),
|
|
904
252
|
z.strictObject({
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
field: udlFieldNameSchema,
|
|
910
|
-
days: z.number().int().min(1).max(3650),
|
|
911
|
-
})
|
|
912
|
-
.optional(),
|
|
253
|
+
key: name,
|
|
254
|
+
operation: z.literal("internal_transfer.void"),
|
|
255
|
+
capture: name.optional(),
|
|
256
|
+
transfer: path,
|
|
913
257
|
}),
|
|
914
258
|
]);
|
|
915
|
-
const
|
|
916
|
-
|
|
259
|
+
const clock = z.strictObject({ at: path, offset: integer.optional() });
|
|
260
|
+
export const udlActionSchema = z.strictObject({
|
|
261
|
+
summary: text,
|
|
262
|
+
publicAction: name.optional(),
|
|
263
|
+
event: text,
|
|
264
|
+
actor: z.union([
|
|
265
|
+
z.literal("caller"),
|
|
266
|
+
z.literal("clock"),
|
|
267
|
+
z.strictObject({ party: name }),
|
|
268
|
+
z.strictObject({ parent: instrumentId }),
|
|
269
|
+
]),
|
|
270
|
+
input: z.array(udlFieldSchema).max(128),
|
|
271
|
+
requires: z.array(udlRequirementSchema).max(128),
|
|
272
|
+
due: clock.optional(),
|
|
273
|
+
deadline: clock.optional(),
|
|
274
|
+
set: z.record(name, value).optional(),
|
|
275
|
+
calculate: z.array(udlCalculationSchema).max(128).optional(),
|
|
276
|
+
moves: z.array(udlMoveSchema).max(256),
|
|
277
|
+
invoke: z
|
|
278
|
+
.array(z.union([
|
|
279
|
+
z.strictObject({
|
|
280
|
+
instrument: instrumentId,
|
|
281
|
+
action: z.literal("create"),
|
|
282
|
+
input: z.record(name, value),
|
|
283
|
+
}),
|
|
284
|
+
z.strictObject({
|
|
285
|
+
reference: path,
|
|
286
|
+
action: name,
|
|
287
|
+
input: z.record(name, value),
|
|
288
|
+
}),
|
|
289
|
+
z.strictObject({
|
|
290
|
+
selection,
|
|
291
|
+
action: name,
|
|
292
|
+
input: z.record(name, value),
|
|
293
|
+
}),
|
|
294
|
+
]))
|
|
295
|
+
.max(16)
|
|
296
|
+
.optional(),
|
|
297
|
+
approval: z
|
|
917
298
|
.strictObject({
|
|
918
|
-
|
|
919
|
-
|
|
299
|
+
target: path,
|
|
300
|
+
action: name,
|
|
301
|
+
party: name,
|
|
302
|
+
expires: path,
|
|
303
|
+
input: z.record(name, value),
|
|
304
|
+
decision: z.enum(["approved", "declined"]),
|
|
920
305
|
})
|
|
921
306
|
.optional(),
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
307
|
+
});
|
|
308
|
+
export const udlLifecycleSchema = z.strictObject({
|
|
309
|
+
states: z.array(name).min(1).max(64),
|
|
310
|
+
initial: name,
|
|
311
|
+
transitions: z.record(name, z.strictObject({ from: z.array(name).min(1).max(64), to: name })),
|
|
312
|
+
});
|
|
313
|
+
export const udlInstrumentSchema = z.strictObject({
|
|
314
|
+
id: instrumentId,
|
|
315
|
+
title: text,
|
|
316
|
+
summary: text,
|
|
317
|
+
fields: z.array(udlFieldSchema).max(256),
|
|
318
|
+
calculate: z.array(udlCalculationSchema).max(128),
|
|
319
|
+
lifecycle: udlLifecycleSchema,
|
|
320
|
+
actions: z.record(name, udlActionSchema),
|
|
321
|
+
actionOrder: z.array(name).min(1).max(128),
|
|
322
|
+
invariants: z.array(udlRequirementSchema).max(128).optional(),
|
|
323
|
+
examples: z
|
|
324
|
+
.array(z.strictObject({ name: text, input: z.json() }))
|
|
931
325
|
.max(16)
|
|
932
326
|
.optional(),
|
|
933
|
-
actionLibrary: udlActionLibrarySchema.optional(),
|
|
934
|
-
actionOrder: z.array(udlActionNameSchema).min(1),
|
|
935
|
-
agentDescription: udlAgentDescriptionSchema.optional(),
|
|
936
|
-
aggregateInvariants: z.array(udlAggregateSchema).min(1).optional(),
|
|
937
|
-
callerParkedStates: z
|
|
938
|
-
.record(udlSnakeCaseSchema, nonEmptyTextSchema)
|
|
939
|
-
.optional(),
|
|
940
|
-
description: nonEmptyTextSchema.optional(),
|
|
941
|
-
dials: z.array(udlDialSchema).optional(),
|
|
942
|
-
distinctParties: z.literal(true).optional(),
|
|
943
|
-
derivedAmounts: z.array(udlDerivedAmountSchema).min(1).max(64).optional(),
|
|
944
|
-
feeRules: z.array(udlFeeRuleSchema).min(1).max(4).optional(),
|
|
945
|
-
fields: z.record(udlFieldNameSchema, jsonObjectSchema),
|
|
946
|
-
id: udlInstrumentIdSchema,
|
|
947
|
-
idPrefix: z
|
|
948
|
-
.string()
|
|
949
|
-
.regex(idPrefixPattern, "must contain 2 to 8 lowercase letters"),
|
|
950
|
-
lifecycle: udlLifecycleSchema,
|
|
951
|
-
nav: z.array(nonEmptyTextSchema).min(1).optional(),
|
|
952
|
-
parties: z.record(udlPartyRoleSchema, udlFieldNameSchema).optional(),
|
|
953
|
-
partitions: z.array(udlPartitionSchema).min(1).optional(),
|
|
954
|
-
piecePlan: udlPiecePlanSchema.optional(),
|
|
955
|
-
required: z.array(udlFieldNameSchema),
|
|
956
|
-
subject: udlInstrumentSubjectSchema.optional(),
|
|
957
|
-
summary: nonEmptyTextSchema,
|
|
958
|
-
surfaceVisibility: z.enum(["internal", "public", "system"]).optional(),
|
|
959
|
-
templateId: udlSnakeCaseSchema.optional(),
|
|
960
|
-
title: nonEmptyTextSchema,
|
|
961
|
-
update: udlUpdatePolicySchema.optional(),
|
|
962
|
-
actions: z.record(udlActionNameSchema, udlActionSchema),
|
|
963
|
-
};
|
|
964
|
-
const udlInstrumentSchema = z.strictObject(udlInstrumentShape);
|
|
965
|
-
export const udlClauseVocabulary = [
|
|
966
|
-
{
|
|
967
|
-
scope: "action",
|
|
968
|
-
spelling: "funding",
|
|
969
|
-
target: "funding",
|
|
970
|
-
cardinality: "one",
|
|
971
|
-
effects: [
|
|
972
|
-
{
|
|
973
|
-
kind: "moves",
|
|
974
|
-
per: "clause",
|
|
975
|
-
signature: { fixed: "transfer.internal" },
|
|
976
|
-
},
|
|
977
|
-
],
|
|
978
|
-
},
|
|
979
|
-
{
|
|
980
|
-
scope: "action",
|
|
981
|
-
spelling: "receipt distribution",
|
|
982
|
-
target: "receiptDistribution",
|
|
983
|
-
cardinality: "one",
|
|
984
|
-
effects: [
|
|
985
|
-
{ kind: "decides", per: "clause", signature: { fixed: "allocation" } },
|
|
986
|
-
{ kind: "moves", per: "clause", signature: { fixed: "allocation" } },
|
|
987
|
-
],
|
|
988
|
-
},
|
|
989
|
-
{
|
|
990
|
-
cardinality: "one",
|
|
991
|
-
scope: "action",
|
|
992
|
-
spelling: "requires allocation",
|
|
993
|
-
target: "requiresAllocation",
|
|
994
|
-
effects: [
|
|
995
|
-
{ kind: "decides", per: "clause", signature: { fixed: "allocation" } },
|
|
996
|
-
],
|
|
997
|
-
},
|
|
998
|
-
{
|
|
999
|
-
cardinality: "one",
|
|
1000
|
-
scope: "instrument",
|
|
1001
|
-
spelling: "allocation",
|
|
1002
|
-
target: "allocation",
|
|
1003
|
-
},
|
|
1004
|
-
{
|
|
1005
|
-
cardinality: "one",
|
|
1006
|
-
scope: "instrument",
|
|
1007
|
-
spelling: "contributions",
|
|
1008
|
-
target: "contributions",
|
|
1009
|
-
},
|
|
1010
|
-
{
|
|
1011
|
-
cardinality: "one",
|
|
1012
|
-
scope: "action",
|
|
1013
|
-
spelling: "allocate",
|
|
1014
|
-
target: "allocate",
|
|
1015
|
-
effects: [
|
|
1016
|
-
{ kind: "decides", per: "clause", signature: { fixed: "allocation" } },
|
|
1017
|
-
{ kind: "moves", per: "clause", signature: { fixed: "allocation" } },
|
|
1018
|
-
],
|
|
1019
|
-
},
|
|
1020
|
-
{
|
|
1021
|
-
cardinality: "one",
|
|
1022
|
-
scope: "action",
|
|
1023
|
-
spelling: "contribution stage",
|
|
1024
|
-
target: "contributionStage",
|
|
1025
|
-
effects: [
|
|
1026
|
-
{
|
|
1027
|
-
kind: "moves",
|
|
1028
|
-
per: "clause",
|
|
1029
|
-
signature: { fixed: "transfer.internal" },
|
|
1030
|
-
},
|
|
1031
|
-
],
|
|
1032
|
-
},
|
|
1033
|
-
{
|
|
1034
|
-
cardinality: "many",
|
|
1035
|
-
scope: "instrument",
|
|
1036
|
-
spelling: "date order",
|
|
1037
|
-
target: "dateOrder",
|
|
1038
|
-
},
|
|
1039
|
-
{
|
|
1040
|
-
cardinality: "one",
|
|
1041
|
-
scope: "action",
|
|
1042
|
-
spelling: "unique",
|
|
1043
|
-
target: "unique",
|
|
1044
|
-
effects: [
|
|
1045
|
-
{
|
|
1046
|
-
kind: "decides",
|
|
1047
|
-
per: "clause",
|
|
1048
|
-
signature: { fixed: "subject_unique" },
|
|
1049
|
-
},
|
|
1050
|
-
],
|
|
1051
|
-
},
|
|
1052
|
-
{
|
|
1053
|
-
cardinality: "many",
|
|
1054
|
-
scope: "action",
|
|
1055
|
-
spelling: "transitions refs",
|
|
1056
|
-
target: "transitionsRefs",
|
|
1057
|
-
effects: [
|
|
1058
|
-
{
|
|
1059
|
-
kind: "decides",
|
|
1060
|
-
per: "element",
|
|
1061
|
-
signature: { fixed: "referenced_transition" },
|
|
1062
|
-
},
|
|
1063
|
-
],
|
|
1064
|
-
},
|
|
1065
|
-
{
|
|
1066
|
-
cardinality: "many",
|
|
1067
|
-
scope: "action",
|
|
1068
|
-
spelling: "cascade",
|
|
1069
|
-
target: "cascade",
|
|
1070
|
-
effects: [
|
|
1071
|
-
{
|
|
1072
|
-
kind: "decides",
|
|
1073
|
-
per: "element",
|
|
1074
|
-
signature: { fixed: "cascade_transition" },
|
|
1075
|
-
},
|
|
1076
|
-
],
|
|
1077
|
-
},
|
|
1078
|
-
{
|
|
1079
|
-
cardinality: "one",
|
|
1080
|
-
literalKeys: true,
|
|
1081
|
-
scope: "instrument",
|
|
1082
|
-
spelling: "action library",
|
|
1083
|
-
target: "actionLibrary",
|
|
1084
|
-
},
|
|
1085
|
-
{
|
|
1086
|
-
cardinality: "one",
|
|
1087
|
-
scope: "action",
|
|
1088
|
-
spelling: "agent description",
|
|
1089
|
-
target: "agentDescription",
|
|
1090
|
-
},
|
|
1091
|
-
{
|
|
1092
|
-
cardinality: "many",
|
|
1093
|
-
literalKeys: true,
|
|
1094
|
-
scope: "action",
|
|
1095
|
-
spelling: "calls",
|
|
1096
|
-
target: "calls",
|
|
1097
|
-
},
|
|
1098
|
-
{
|
|
1099
|
-
cardinality: "one",
|
|
1100
|
-
scope: "action",
|
|
1101
|
-
spelling: "requires input",
|
|
1102
|
-
target: "requiresInput",
|
|
1103
|
-
literalKeys: true,
|
|
1104
|
-
},
|
|
1105
|
-
{
|
|
1106
|
-
cardinality: "one",
|
|
1107
|
-
scope: "action",
|
|
1108
|
-
spelling: "engine owned",
|
|
1109
|
-
target: "engineOwned",
|
|
1110
|
-
},
|
|
1111
|
-
{
|
|
1112
|
-
cardinality: "one",
|
|
1113
|
-
scope: "action",
|
|
1114
|
-
spelling: "capture engine",
|
|
1115
|
-
target: "captureEngine",
|
|
1116
|
-
literalKeys: true,
|
|
1117
|
-
},
|
|
1118
|
-
{
|
|
1119
|
-
cardinality: "one",
|
|
1120
|
-
scope: "action",
|
|
1121
|
-
spelling: "capture input",
|
|
1122
|
-
target: "captureInput",
|
|
1123
|
-
},
|
|
1124
|
-
{
|
|
1125
|
-
cardinality: "one",
|
|
1126
|
-
// The committing action consumes the quote through its priced moves.
|
|
1127
|
-
// An extra row here would bill the same movement twice.
|
|
1128
|
-
effects: [],
|
|
1129
|
-
scope: "action",
|
|
1130
|
-
spelling: "commit",
|
|
1131
|
-
target: "commit",
|
|
1132
|
-
},
|
|
1133
|
-
{
|
|
1134
|
-
cardinality: "one",
|
|
1135
|
-
effects: [
|
|
1136
|
-
{
|
|
1137
|
-
kind: "holds",
|
|
1138
|
-
per: "clause",
|
|
1139
|
-
signature: { fixed: "quote" },
|
|
1140
|
-
},
|
|
1141
|
-
{
|
|
1142
|
-
kind: "schedules",
|
|
1143
|
-
per: "clause",
|
|
1144
|
-
signature: { fixed: "expiry" },
|
|
1145
|
-
},
|
|
1146
|
-
],
|
|
1147
|
-
linearOutputs: ["netRef"],
|
|
1148
|
-
scope: "action",
|
|
1149
|
-
spelling: "quote",
|
|
1150
|
-
target: "quote",
|
|
1151
|
-
},
|
|
1152
|
-
{
|
|
1153
|
-
cardinality: "one",
|
|
1154
|
-
linearOutputs: ["field"],
|
|
1155
|
-
scope: "action",
|
|
1156
|
-
spelling: "decided amount",
|
|
1157
|
-
target: "decidedAmount",
|
|
1158
|
-
},
|
|
1159
|
-
{
|
|
1160
|
-
cardinality: "one",
|
|
1161
|
-
effects: [
|
|
1162
|
-
{
|
|
1163
|
-
kind: "schedules",
|
|
1164
|
-
per: "clause",
|
|
1165
|
-
signature: { fixed: "deadline" },
|
|
1166
|
-
},
|
|
1167
|
-
],
|
|
1168
|
-
scope: "action",
|
|
1169
|
-
spelling: "deadline",
|
|
1170
|
-
target: "deadline",
|
|
1171
|
-
},
|
|
1172
|
-
{
|
|
1173
|
-
cardinality: "one",
|
|
1174
|
-
effects: [
|
|
1175
|
-
{
|
|
1176
|
-
kind: "decides",
|
|
1177
|
-
per: "clause",
|
|
1178
|
-
signature: { fromField: "capability" },
|
|
1179
|
-
},
|
|
1180
|
-
],
|
|
1181
|
-
scope: "action",
|
|
1182
|
-
spelling: "decision",
|
|
1183
|
-
target: "decision",
|
|
1184
|
-
},
|
|
1185
|
-
{
|
|
1186
|
-
cardinality: "one",
|
|
1187
|
-
linearOutputs: ["amountRef"],
|
|
1188
|
-
scope: "action",
|
|
1189
|
-
spelling: "computes distribute",
|
|
1190
|
-
target: "distribute",
|
|
1191
|
-
},
|
|
1192
|
-
{
|
|
1193
|
-
cardinality: "one",
|
|
1194
|
-
scope: "action",
|
|
1195
|
-
spelling: "description",
|
|
1196
|
-
target: "description",
|
|
1197
|
-
},
|
|
1198
|
-
{
|
|
1199
|
-
cardinality: "one",
|
|
1200
|
-
effects: [
|
|
1201
|
-
{
|
|
1202
|
-
kind: "schedules",
|
|
1203
|
-
per: "clause",
|
|
1204
|
-
signature: { fixed: "due" },
|
|
1205
|
-
},
|
|
1206
|
-
],
|
|
1207
|
-
scope: "action",
|
|
1208
|
-
spelling: "due",
|
|
1209
|
-
target: "due",
|
|
1210
|
-
},
|
|
1211
|
-
{
|
|
1212
|
-
cardinality: "one",
|
|
1213
|
-
scope: "action",
|
|
1214
|
-
spelling: "earnable",
|
|
1215
|
-
target: "earnable",
|
|
1216
|
-
},
|
|
1217
|
-
{
|
|
1218
|
-
cardinality: "one",
|
|
1219
|
-
scope: "action",
|
|
1220
|
-
spelling: "event name",
|
|
1221
|
-
target: "eventName",
|
|
1222
|
-
},
|
|
1223
|
-
{
|
|
1224
|
-
cardinality: "many",
|
|
1225
|
-
scope: "action",
|
|
1226
|
-
spelling: "examples",
|
|
1227
|
-
target: "examples",
|
|
1228
|
-
},
|
|
1229
|
-
{
|
|
1230
|
-
cardinality: "one",
|
|
1231
|
-
scope: "action",
|
|
1232
|
-
spelling: "input",
|
|
1233
|
-
target: "input",
|
|
1234
|
-
},
|
|
1235
|
-
{
|
|
1236
|
-
cardinality: "many",
|
|
1237
|
-
effects: [
|
|
1238
|
-
{
|
|
1239
|
-
kind: "moves",
|
|
1240
|
-
per: "element",
|
|
1241
|
-
signature: { movementClass: true },
|
|
1242
|
-
},
|
|
1243
|
-
{
|
|
1244
|
-
kind: "holds",
|
|
1245
|
-
per: "element",
|
|
1246
|
-
signature: { fixed: "reserve" },
|
|
1247
|
-
},
|
|
1248
|
-
],
|
|
1249
|
-
linearSink: true,
|
|
1250
|
-
scope: "action",
|
|
1251
|
-
spelling: "moves",
|
|
1252
|
-
target: "moves",
|
|
1253
|
-
},
|
|
1254
|
-
{
|
|
1255
|
-
cardinality: "one",
|
|
1256
|
-
effects: [
|
|
1257
|
-
{
|
|
1258
|
-
kind: "moves",
|
|
1259
|
-
per: "clause",
|
|
1260
|
-
signature: { fixed: "payout.external" },
|
|
1261
|
-
},
|
|
1262
|
-
],
|
|
1263
|
-
linearSink: true,
|
|
1264
|
-
scope: "action",
|
|
1265
|
-
spelling: "payout",
|
|
1266
|
-
target: "payout",
|
|
1267
|
-
},
|
|
1268
|
-
{
|
|
1269
|
-
cardinality: "one",
|
|
1270
|
-
literalKeys: true,
|
|
1271
|
-
scope: "instrument",
|
|
1272
|
-
spelling: "piece plan",
|
|
1273
|
-
target: "piecePlan",
|
|
1274
|
-
},
|
|
1275
|
-
{
|
|
1276
|
-
cardinality: "one",
|
|
1277
|
-
literalKeys: true,
|
|
1278
|
-
scope: "action",
|
|
1279
|
-
spelling: "piece stage",
|
|
1280
|
-
target: "pieceStage",
|
|
1281
|
-
},
|
|
1282
|
-
{
|
|
1283
|
-
cardinality: "one",
|
|
1284
|
-
effects: [
|
|
1285
|
-
{
|
|
1286
|
-
kind: "decides",
|
|
1287
|
-
per: "clause",
|
|
1288
|
-
signature: { fixed: "tenant_port" },
|
|
1289
|
-
},
|
|
1290
|
-
],
|
|
1291
|
-
scope: "action",
|
|
1292
|
-
spelling: "port",
|
|
1293
|
-
target: "port",
|
|
1294
|
-
},
|
|
1295
|
-
{
|
|
1296
|
-
cardinality: "one",
|
|
1297
|
-
scope: "action",
|
|
1298
|
-
spelling: "principal",
|
|
1299
|
-
target: "principal",
|
|
1300
|
-
},
|
|
1301
|
-
{
|
|
1302
|
-
cardinality: "one",
|
|
1303
|
-
scope: "action",
|
|
1304
|
-
spelling: "public action",
|
|
1305
|
-
target: "publicAction",
|
|
1306
|
-
},
|
|
1307
|
-
{
|
|
1308
|
-
cardinality: "many",
|
|
1309
|
-
effects: [
|
|
1310
|
-
{
|
|
1311
|
-
kind: "reads",
|
|
1312
|
-
per: "element",
|
|
1313
|
-
signature: { fixed: "reconcile" },
|
|
1314
|
-
},
|
|
1315
|
-
],
|
|
1316
|
-
scope: "action",
|
|
1317
|
-
spelling: "reconcile",
|
|
1318
|
-
target: "reconcile",
|
|
1319
|
-
},
|
|
1320
|
-
{
|
|
1321
|
-
cardinality: "one",
|
|
1322
|
-
linearOutputs: ["amountRef"],
|
|
1323
|
-
scope: "action",
|
|
1324
|
-
spelling: "computes remainder",
|
|
1325
|
-
target: "remainder",
|
|
1326
|
-
},
|
|
1327
|
-
{
|
|
1328
|
-
cardinality: "many",
|
|
1329
|
-
effects: [
|
|
1330
|
-
{
|
|
1331
|
-
kind: "reads",
|
|
1332
|
-
per: "clause",
|
|
1333
|
-
signature: { fixed: "requires_aggregate" },
|
|
1334
|
-
},
|
|
1335
|
-
],
|
|
1336
|
-
scope: "action",
|
|
1337
|
-
spelling: "requires aggregate",
|
|
1338
|
-
target: "requiresAggregate",
|
|
1339
|
-
},
|
|
1340
|
-
{
|
|
1341
|
-
cardinality: "many",
|
|
1342
|
-
effects: [
|
|
1343
|
-
{
|
|
1344
|
-
kind: "reads",
|
|
1345
|
-
per: "clause",
|
|
1346
|
-
signature: { fixed: "requires_checks" },
|
|
1347
|
-
},
|
|
1348
|
-
],
|
|
1349
|
-
scope: "action",
|
|
1350
|
-
spelling: "requires checks",
|
|
1351
|
-
target: "requiresChecks",
|
|
1352
|
-
},
|
|
1353
|
-
{
|
|
1354
|
-
cardinality: "one",
|
|
1355
|
-
scope: "action",
|
|
1356
|
-
spelling: "requires drained",
|
|
1357
|
-
target: "requiresDrainedAccount",
|
|
1358
|
-
},
|
|
1359
|
-
{
|
|
1360
|
-
cardinality: "many",
|
|
1361
|
-
scope: "action",
|
|
1362
|
-
spelling: "requires exposure",
|
|
1363
|
-
target: "requiresExposure",
|
|
1364
|
-
},
|
|
1365
|
-
{
|
|
1366
|
-
cardinality: "many",
|
|
1367
|
-
effects: [
|
|
1368
|
-
{
|
|
1369
|
-
kind: "reads",
|
|
1370
|
-
per: "clause",
|
|
1371
|
-
signature: { fixed: "requires_refs" },
|
|
1372
|
-
},
|
|
1373
|
-
],
|
|
1374
|
-
scope: "action",
|
|
1375
|
-
spelling: "requires refs",
|
|
1376
|
-
target: "requiresRefs",
|
|
1377
|
-
},
|
|
1378
|
-
{
|
|
1379
|
-
cardinality: "one",
|
|
1380
|
-
scope: "action",
|
|
1381
|
-
spelling: "sandbox failure point",
|
|
1382
|
-
target: "sandboxFailurePoint",
|
|
1383
|
-
},
|
|
1384
|
-
{
|
|
1385
|
-
cardinality: "one",
|
|
1386
|
-
scope: "action",
|
|
1387
|
-
spelling: "sets at",
|
|
1388
|
-
target: "setsAt",
|
|
1389
|
-
},
|
|
1390
|
-
{
|
|
1391
|
-
cardinality: "one",
|
|
1392
|
-
linearOutputs: ["amountRef"],
|
|
1393
|
-
scope: "action",
|
|
1394
|
-
spelling: "computes signed_sum",
|
|
1395
|
-
target: "signedSum",
|
|
1396
|
-
},
|
|
1397
|
-
{
|
|
1398
|
-
cardinality: "many",
|
|
1399
|
-
linearSink: true,
|
|
1400
|
-
scope: "action",
|
|
1401
|
-
spelling: "steps",
|
|
1402
|
-
target: "steps",
|
|
1403
|
-
},
|
|
1404
|
-
{
|
|
1405
|
-
cardinality: "one",
|
|
1406
|
-
scope: "action",
|
|
1407
|
-
spelling: "summary",
|
|
1408
|
-
target: "summary",
|
|
1409
|
-
},
|
|
1410
|
-
{
|
|
1411
|
-
cardinality: "many",
|
|
1412
|
-
scope: "action",
|
|
1413
|
-
spelling: "updates",
|
|
1414
|
-
target: "updates",
|
|
1415
|
-
},
|
|
1416
|
-
{
|
|
1417
|
-
cardinality: "many",
|
|
1418
|
-
effects: [
|
|
1419
|
-
{
|
|
1420
|
-
kind: "notifies",
|
|
1421
|
-
per: "element",
|
|
1422
|
-
signature: { fromField: "channel" },
|
|
1423
|
-
},
|
|
1424
|
-
],
|
|
1425
|
-
scope: "action",
|
|
1426
|
-
spelling: "notify",
|
|
1427
|
-
target: "effects.notifies",
|
|
1428
|
-
},
|
|
1429
|
-
{
|
|
1430
|
-
cardinality: "one",
|
|
1431
|
-
scope: "instrument",
|
|
1432
|
-
spelling: "agent description",
|
|
1433
|
-
target: "agentDescription",
|
|
1434
|
-
},
|
|
1435
|
-
{
|
|
1436
|
-
cardinality: "many",
|
|
1437
|
-
scope: "instrument",
|
|
1438
|
-
spelling: "aggregate invariants",
|
|
1439
|
-
target: "aggregateInvariants",
|
|
1440
|
-
},
|
|
1441
|
-
{
|
|
1442
|
-
cardinality: "one",
|
|
1443
|
-
scope: "instrument",
|
|
1444
|
-
spelling: "caller parked states",
|
|
1445
|
-
target: "callerParkedStates",
|
|
1446
|
-
},
|
|
1447
|
-
{
|
|
1448
|
-
cardinality: "one",
|
|
1449
|
-
scope: "instrument",
|
|
1450
|
-
spelling: "description",
|
|
1451
|
-
target: "description",
|
|
1452
|
-
},
|
|
1453
|
-
{
|
|
1454
|
-
cardinality: "many",
|
|
1455
|
-
scope: "instrument",
|
|
1456
|
-
spelling: "dials",
|
|
1457
|
-
target: "dials",
|
|
1458
|
-
},
|
|
1459
|
-
{
|
|
1460
|
-
cardinality: "one",
|
|
1461
|
-
scope: "instrument",
|
|
1462
|
-
spelling: "distinct parties",
|
|
1463
|
-
target: "distinctParties",
|
|
1464
|
-
},
|
|
1465
|
-
{
|
|
1466
|
-
cardinality: "many",
|
|
1467
|
-
scope: "instrument",
|
|
1468
|
-
spelling: "computes derived",
|
|
1469
|
-
target: "derivedAmounts",
|
|
1470
|
-
},
|
|
1471
|
-
{
|
|
1472
|
-
cardinality: "many",
|
|
1473
|
-
scope: "instrument",
|
|
1474
|
-
spelling: "computes fees",
|
|
1475
|
-
target: "feeRules",
|
|
1476
|
-
},
|
|
1477
|
-
{
|
|
1478
|
-
cardinality: "one",
|
|
1479
|
-
scope: "instrument",
|
|
1480
|
-
spelling: "id prefix",
|
|
1481
|
-
target: "idPrefix",
|
|
1482
|
-
},
|
|
1483
|
-
{
|
|
1484
|
-
cardinality: "many",
|
|
1485
|
-
scope: "instrument",
|
|
1486
|
-
spelling: "nav",
|
|
1487
|
-
target: "nav",
|
|
1488
|
-
},
|
|
1489
|
-
{
|
|
1490
|
-
cardinality: "many",
|
|
1491
|
-
scope: "instrument",
|
|
1492
|
-
spelling: "partitions",
|
|
1493
|
-
target: "partitions",
|
|
1494
|
-
},
|
|
1495
|
-
{
|
|
1496
|
-
cardinality: "one",
|
|
1497
|
-
scope: "instrument",
|
|
1498
|
-
spelling: "subject",
|
|
1499
|
-
target: "subject",
|
|
1500
|
-
},
|
|
1501
|
-
{
|
|
1502
|
-
cardinality: "one",
|
|
1503
|
-
scope: "instrument",
|
|
1504
|
-
spelling: "summary",
|
|
1505
|
-
target: "summary",
|
|
1506
|
-
},
|
|
1507
|
-
{
|
|
1508
|
-
cardinality: "one",
|
|
1509
|
-
scope: "instrument",
|
|
1510
|
-
spelling: "surface visibility",
|
|
1511
|
-
target: "surfaceVisibility",
|
|
1512
|
-
},
|
|
1513
|
-
{
|
|
1514
|
-
cardinality: "one",
|
|
1515
|
-
scope: "instrument",
|
|
1516
|
-
spelling: "template binding",
|
|
1517
|
-
target: "templateBinding",
|
|
1518
|
-
},
|
|
1519
|
-
{
|
|
1520
|
-
cardinality: "one",
|
|
1521
|
-
scope: "instrument",
|
|
1522
|
-
spelling: "template id",
|
|
1523
|
-
target: "templateId",
|
|
1524
|
-
},
|
|
1525
|
-
{
|
|
1526
|
-
cardinality: "one",
|
|
1527
|
-
scope: "instrument",
|
|
1528
|
-
spelling: "title",
|
|
1529
|
-
target: "title",
|
|
1530
|
-
},
|
|
1531
|
-
{
|
|
1532
|
-
cardinality: "one",
|
|
1533
|
-
scope: "instrument",
|
|
1534
|
-
spelling: "update",
|
|
1535
|
-
target: "update",
|
|
1536
|
-
},
|
|
1537
|
-
{
|
|
1538
|
-
cardinality: "one",
|
|
1539
|
-
effects: [],
|
|
1540
|
-
scope: "action",
|
|
1541
|
-
spelling: "request authority",
|
|
1542
|
-
target: "requestAuthority",
|
|
1543
|
-
},
|
|
1544
|
-
];
|
|
1545
|
-
const udlDocumentShapeSchema = z.strictObject({
|
|
1546
|
-
dials: z.array(udlCompositionDialSchema).min(1).optional(),
|
|
1547
|
-
instruments: z.array(udlInstrumentSchema).min(1),
|
|
1548
|
-
product: udlSnakeCaseSchema,
|
|
1549
|
-
subjects: z.array(udlSubjectSchema),
|
|
1550
|
-
title: nonEmptyTextSchema,
|
|
1551
|
-
udl: z.literal(UDL_FORMAT_VERSION),
|
|
1552
|
-
version: z.number().int().positive(),
|
|
1553
327
|
});
|
|
1554
|
-
const
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
: [];
|
|
1563
|
-
}
|
|
1564
|
-
function declaredMoneyRefKeys(instrument) {
|
|
1565
|
-
return new Set([
|
|
1566
|
-
...Object.values(instrument.actions).flatMap((action) => [
|
|
1567
|
-
...(action.remainder
|
|
1568
|
-
? [
|
|
1569
|
-
action.remainder.amountRef,
|
|
1570
|
-
...(action.remainder.accumulateRef
|
|
1571
|
-
? [action.remainder.accumulateRef]
|
|
1572
|
-
: []),
|
|
1573
|
-
]
|
|
1574
|
-
: []),
|
|
1575
|
-
...(action.signedSum
|
|
1576
|
-
? [
|
|
1577
|
-
action.signedSum.amountRef,
|
|
1578
|
-
...action.signedSum.sources.map((source) => source.subtotalRef),
|
|
1579
|
-
]
|
|
1580
|
-
: []),
|
|
1581
|
-
...(action.distribute ? [action.distribute.amountRef] : []),
|
|
1582
|
-
...(action.quote ? [action.quote.chargeRef, action.quote.netRef] : []),
|
|
1583
|
-
]),
|
|
1584
|
-
]);
|
|
1585
|
-
}
|
|
1586
|
-
export const udlDocumentSchema = udlDocumentShapeSchema.superRefine((document, context) => {
|
|
1587
|
-
document.instruments.forEach((instrument, instrumentIndex) => {
|
|
1588
|
-
instrument.derivedAmounts?.forEach((amount, amountIndex) => {
|
|
1589
|
-
const base = [
|
|
1590
|
-
"instruments",
|
|
1591
|
-
instrumentIndex,
|
|
1592
|
-
"derivedAmounts",
|
|
1593
|
-
amountIndex,
|
|
1594
|
-
];
|
|
1595
|
-
if (!isMoneyField(instrument.fields[amount.field])) {
|
|
1596
|
-
context.addIssue({
|
|
1597
|
-
code: "custom",
|
|
1598
|
-
message: `derived amount target ${amount.field} must be a declared money field`,
|
|
1599
|
-
path: [...base, "field"],
|
|
1600
|
-
});
|
|
1601
|
-
}
|
|
1602
|
-
if (!isMoneyField(instrument.fields[amount.sourceField])) {
|
|
1603
|
-
context.addIssue({
|
|
1604
|
-
code: "custom",
|
|
1605
|
-
message: `derived amount source ${amount.sourceField} must be a declared money field`,
|
|
1606
|
-
path: [...base, "sourceField"],
|
|
1607
|
-
});
|
|
1608
|
-
}
|
|
1609
|
-
if (amount.field === amount.sourceField) {
|
|
1610
|
-
context.addIssue({
|
|
1611
|
-
code: "custom",
|
|
1612
|
-
message: "a derived amount cannot derive from itself",
|
|
1613
|
-
path: [...base, "sourceField"],
|
|
1614
|
-
});
|
|
1615
|
-
}
|
|
1616
|
-
});
|
|
1617
|
-
Object.entries(instrument.actions).forEach(([actionName, action]) => {
|
|
1618
|
-
const distribute = action.distribute;
|
|
1619
|
-
if (!distribute)
|
|
1620
|
-
return;
|
|
1621
|
-
const base = [
|
|
1622
|
-
"instruments",
|
|
1623
|
-
instrumentIndex,
|
|
1624
|
-
"actions",
|
|
1625
|
-
actionName,
|
|
1626
|
-
"distribute",
|
|
1627
|
-
];
|
|
1628
|
-
const refSchema = instrument.fields[distribute.refField];
|
|
1629
|
-
const parents = refSchema
|
|
1630
|
-
? referenceTargets(refSchema, document.instruments)
|
|
1631
|
-
: [];
|
|
1632
|
-
if (parents.length !== 1) {
|
|
1633
|
-
context.addIssue({
|
|
1634
|
-
code: "custom",
|
|
1635
|
-
message: `distribute refField ${distribute.refField} must identify exactly one parent instrument`,
|
|
1636
|
-
path: [...base, "refField"],
|
|
1637
|
-
});
|
|
1638
|
-
}
|
|
1639
|
-
if (!isMoneyField(instrument.fields[distribute.weightField])) {
|
|
1640
|
-
context.addIssue({
|
|
1641
|
-
code: "custom",
|
|
1642
|
-
message: `distribute weightField ${distribute.weightField} must be a declared money field`,
|
|
1643
|
-
path: [...base, "weightField"],
|
|
1644
|
-
});
|
|
1645
|
-
}
|
|
1646
|
-
distribute.statuses.forEach((status, statusIndex) => {
|
|
1647
|
-
if (instrument.lifecycle.states.includes(status))
|
|
1648
|
-
return;
|
|
1649
|
-
context.addIssue({
|
|
1650
|
-
code: "custom",
|
|
1651
|
-
message: `distribute status ${status} is not declared by ${instrument.id}`,
|
|
1652
|
-
path: [...base, "statuses", statusIndex],
|
|
1653
|
-
});
|
|
1654
|
-
});
|
|
1655
|
-
const parent = parents[0];
|
|
1656
|
-
if (!parent)
|
|
1657
|
-
return;
|
|
1658
|
-
const poolMatch = /^(fields|refs)\.([a-z][A-Za-z0-9]*)$/.exec(distribute.pool.path);
|
|
1659
|
-
const root = poolMatch?.[1];
|
|
1660
|
-
const key = poolMatch?.[2];
|
|
1661
|
-
const poolDeclared = root === "fields"
|
|
1662
|
-
? isMoneyField(parent.fields[key ?? ""])
|
|
1663
|
-
: root === "refs"
|
|
1664
|
-
? declaredMoneyRefKeys(parent).has(key ?? "")
|
|
1665
|
-
: false;
|
|
1666
|
-
if (!poolDeclared) {
|
|
1667
|
-
context.addIssue({
|
|
1668
|
-
code: "custom",
|
|
1669
|
-
message: `distribute pool ${distribute.pool.path} must be a declared money field or ref of ${parent.id}`,
|
|
1670
|
-
path: [...base, "pool", "path"],
|
|
1671
|
-
});
|
|
1672
|
-
}
|
|
1673
|
-
});
|
|
1674
|
-
});
|
|
328
|
+
export const udlDocumentSchema = z.strictObject({
|
|
329
|
+
udl: z.literal(UDL_FORMAT_VERSION),
|
|
330
|
+
version: integer.positive(),
|
|
331
|
+
product: name,
|
|
332
|
+
title: text,
|
|
333
|
+
currency: z.literal("SAR"),
|
|
334
|
+
parties: z.record(name, udlPartySchema),
|
|
335
|
+
instruments: z.array(udlInstrumentSchema).min(1).max(256),
|
|
1675
336
|
});
|
|
1676
337
|
//# sourceMappingURL=schema.js.map
|