@hyperscale0/udl 1.0.0-rc.1 → 1.0.123
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 +5 -211
- package/LICENSE.md +356 -0
- package/NOTICE.md +8 -0
- package/README.md +14 -106
- package/dist/canonical.d.ts.map +1 -1
- package/dist/canonical.js +1 -29
- package/dist/canonical.js.map +1 -1
- package/dist/diagnostics.d.ts +13 -165
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +33 -157
- package/dist/diagnostics.js.map +1 -1
- package/dist/field-value.d.ts +5 -0
- package/dist/field-value.d.ts.map +1 -0
- package/dist/field-value.js +85 -0
- package/dist/field-value.js.map +1 -0
- package/dist/finance.d.ts +10 -53
- package/dist/finance.d.ts.map +1 -1
- package/dist/finance.js +252 -536
- package/dist/finance.js.map +1 -1
- package/dist/index.d.ts +9 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -9
- package/dist/index.js.map +1 -1
- package/dist/json.d.ts +2 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +30 -0
- package/dist/json.js.map +1 -0
- package/dist/limits.d.ts +3 -28
- package/dist/limits.d.ts.map +1 -1
- package/dist/limits.js +5 -31
- package/dist/limits.js.map +1 -1
- package/dist/object-contract.d.ts +140 -0
- package/dist/object-contract.d.ts.map +1 -0
- package/dist/object-contract.js +314 -0
- package/dist/object-contract.js.map +1 -0
- package/dist/object-semantics-schema.d.ts +5710 -0
- package/dist/object-semantics-schema.d.ts.map +1 -0
- package/dist/object-semantics-schema.js +119 -0
- package/dist/object-semantics-schema.js.map +1 -0
- package/dist/object-semantics.d.ts +6 -0
- package/dist/object-semantics.d.ts.map +1 -0
- package/dist/object-semantics.js +279 -0
- package/dist/object-semantics.js.map +1 -0
- package/dist/object-structures.d.ts +4 -0
- package/dist/object-structures.d.ts.map +1 -0
- package/dist/object-structures.js +134 -0
- package/dist/object-structures.js.map +1 -0
- package/dist/reporting-validation.d.ts +8 -0
- package/dist/reporting-validation.d.ts.map +1 -0
- package/dist/reporting-validation.js +252 -0
- package/dist/reporting-validation.js.map +1 -0
- package/dist/reporting.d.ts +477 -0
- package/dist/reporting.d.ts.map +1 -0
- package/dist/reporting.js +169 -0
- package/dist/reporting.js.map +1 -0
- package/dist/schema.d.ts +5572 -2710
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +444 -1121
- package/dist/schema.js.map +1 -1
- package/dist/validation.d.ts +10 -73
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +1109 -2569
- package/dist/validation.js.map +1 -1
- package/docs/assets/brand/manifest.json +30 -0
- package/docs/assets/brand/udl-horizontal-white.svg +1 -0
- package/docs/assets/brand/udl-horizontal.svg +1 -0
- package/docs/assets/brand/udl-stacked-white.svg +1 -0
- package/docs/assets/brand/udl-stacked.svg +1 -0
- package/docs/assets/udl.svg +11 -0
- package/package.json +13 -22
- package/spec/README.md +300 -172
- package/spec/cars.udl.json +249 -0
- package/spec/udl.schema.json +3066 -2242
- package/src/canonical.ts +1 -35
- package/src/diagnostics.ts +76 -209
- package/src/field-value.ts +87 -0
- package/src/finance.ts +327 -832
- package/src/index.ts +18 -95
- package/src/json.ts +34 -0
- package/src/limits.ts +5 -31
- package/src/object-contract.ts +559 -0
- package/src/object-semantics-schema.ts +148 -0
- package/src/object-semantics.ts +378 -0
- package/src/object-structures.ts +255 -0
- package/src/reporting-validation.ts +383 -0
- package/src/reporting.ts +178 -0
- package/src/schema.ts +510 -1277
- package/src/validation.ts +1630 -4545
- package/LICENSE +0 -661
- package/LICENSING.md +0 -51
- package/TRADEMARKS.md +0 -35
- 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/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-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/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/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/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/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 -54
- 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/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/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -184
- package/dist/cli.js.map +0 -1
- package/dist/effects.d.ts +0 -41
- package/dist/effects.d.ts.map +0 -1
- package/dist/effects.js +0 -110
- package/dist/effects.js.map +0 -1
- package/dist/evolution.d.ts +0 -120
- package/dist/evolution.d.ts.map +0 -1
- package/dist/evolution.js +0 -567
- package/dist/evolution.js.map +0 -1
- package/dist/parser.d.ts +0 -4
- package/dist/parser.d.ts.map +0 -1
- package/dist/parser.js +0 -44
- package/dist/parser.js.map +0 -1
- package/docs/README.md +0 -14
- 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 -15
- 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/llms-full.txt +0 -1241
- package/docs/llms.txt +0 -14
- package/docs/reference/canonical.md +0 -16
- package/docs/reference/clauses.md +0 -986
- package/docs/reference/cli.md +0 -22
- package/docs/reference/diagnostics.md +0 -32
- package/skills/udl/SKILL.md +0 -28
- package/src/check-profiles.ts +0 -80
- package/src/cli.ts +0 -196
- package/src/effects.ts +0 -163
- package/src/evolution.ts +0 -965
- package/src/parser.ts +0 -58
package/src/schema.ts
CHANGED
|
@@ -1,1350 +1,583 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import type { UdlEffectKind } from "./effects.js";
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { reportDefinitionSchema } from "./reporting.js";
|
|
3
|
+
import { writeJson } from "./json.js";
|
|
5
4
|
|
|
6
5
|
export const UDL_FORMAT_VERSION = 1 as const;
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const fieldPathPattern = /^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*)*$/;
|
|
11
|
-
const idPrefixPattern = /^[a-z]{2,8}$/;
|
|
12
|
-
const eventNamePattern = /^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+$/;
|
|
13
|
-
|
|
14
|
-
const udlSnakeCaseSchema = z
|
|
15
|
-
.string()
|
|
16
|
-
.regex(snakeCasePattern, "must be a snake_case identifier");
|
|
17
|
-
const udlActionNameSchema = z
|
|
18
|
-
.string()
|
|
19
|
-
.regex(snakeCasePattern, "must be a snake_case action identifier");
|
|
20
|
-
const udlFieldNameSchema = z
|
|
21
|
-
.string()
|
|
22
|
-
.regex(camelCasePattern, "must be a camelCase field name");
|
|
23
|
-
|
|
24
|
-
export const udlPublicActionSchema = z
|
|
25
|
-
.string()
|
|
26
|
-
.regex(camelCasePattern, "must be a camelCase public action name");
|
|
27
|
-
|
|
28
|
-
export const udlInstrumentActionIdSchema = z
|
|
29
|
-
.string()
|
|
30
|
-
.max(160)
|
|
31
|
-
.regex(
|
|
32
|
-
/^[a-z][a-z0-9_]*\.[a-z][a-z0-9_]*$/,
|
|
33
|
-
"must name an instrument action as instrument_id.action_key",
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
const nonEmptyTextSchema = z
|
|
37
|
-
.string()
|
|
38
|
-
.refine((value) => value.trim().length > 0, "must not be blank");
|
|
39
|
-
// Agent-facing presentation prose. Every MCP tool description an agent reads is
|
|
40
|
-
// this string, so it is capped: a 400-character ceiling keeps a 60-tool surface
|
|
41
|
-
// under the token budget a client spends before it can pick a tool.
|
|
42
|
-
const udlAgentDescriptionSchema = nonEmptyTextSchema.max(400);
|
|
43
|
-
const fieldPathSchema = z
|
|
6
|
+
/** Counts the root and every nested invocation, including selected and ranged children. */
|
|
7
|
+
export const MAX_ACTION_EXPANSION = 4096;
|
|
8
|
+
const name = z
|
|
44
9
|
.string()
|
|
45
|
-
.regex(
|
|
46
|
-
|
|
10
|
+
.regex(/^[a-z][a-zA-Z0-9_]*$/)
|
|
11
|
+
.max(80);
|
|
12
|
+
const text = z.string().min(1).max(2048);
|
|
13
|
+
const amount = z.string().regex(/^(0|[1-9][0-9]{0,17})$/);
|
|
14
|
+
const integer = z.number().int().safe();
|
|
15
|
+
const scalar = z.union([z.string(), integer, z.boolean()]);
|
|
16
|
+
const path = z
|
|
47
17
|
.string()
|
|
48
|
-
.regex(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const jsonObjectSchema = z.record(z.string(), z.json());
|
|
53
|
-
const stringMapSchema = z.record(nonEmptyTextSchema, nonEmptyTextSchema);
|
|
18
|
+
.regex(/^[a-z][a-zA-Z0-9_]*(?:\.[a-z][a-zA-Z0-9_]*)*$/)
|
|
19
|
+
.max(240);
|
|
20
|
+
const instrumentId = name.meta({ "x-udl-reference": "instrument" });
|
|
21
|
+
const objectKindId = name.meta({ "x-udl-reference": "object" });
|
|
54
22
|
|
|
55
|
-
const
|
|
56
|
-
"accounts_ledger_first_party",
|
|
57
|
-
"identity_verification",
|
|
58
|
-
"national_identity",
|
|
59
|
-
"credit_bureau",
|
|
60
|
-
"sanctions_screening",
|
|
61
|
-
"enforcement_instrument",
|
|
62
|
-
"credit_servicing",
|
|
63
|
-
"collections_agency",
|
|
64
|
-
"settlement_ingestion",
|
|
65
|
-
"payouts",
|
|
66
|
-
"banking_or_card_issuing",
|
|
67
|
-
"insurance_carrier",
|
|
68
|
-
"insurance_claims_adjuster",
|
|
69
|
-
"air_carrier",
|
|
70
|
-
"lodging_supplier",
|
|
71
|
-
"email_or_notification",
|
|
72
|
-
] as const;
|
|
73
|
-
export const udlProviderFamilyIdSchema = z.enum(providerFamilyIds);
|
|
23
|
+
export const udlPartyNameSchema = name;
|
|
74
24
|
|
|
75
|
-
const
|
|
25
|
+
export const udlObjectIdSchema = z.string().min(1).max(160);
|
|
26
|
+
export const udlExternalIdSchema = z.string().min(1).max(2048);
|
|
27
|
+
export const udlObjectRevisionSchema = integer.positive();
|
|
76
28
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
kind:
|
|
80
|
-
|
|
81
|
-
title: nonEmptyTextSchema,
|
|
82
|
-
version: z.number().int().positive(),
|
|
29
|
+
/** Currency belongs to the document. Accounts and amounts cannot override it. */
|
|
30
|
+
export const udlPartySchema = z.strictObject({
|
|
31
|
+
kind: z.enum(["person", "business", "staff"]),
|
|
32
|
+
role: name.optional(),
|
|
83
33
|
});
|
|
84
34
|
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
35
|
+
export const udlFamilySchema = z.strictObject({
|
|
36
|
+
module: name,
|
|
37
|
+
exportPath: path,
|
|
38
|
+
revision: integer.positive(),
|
|
88
39
|
});
|
|
89
40
|
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
output: z.json().optional(),
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const udlLifecycleTransitionSchema = z.strictObject({
|
|
97
|
-
from: z.array(udlSnakeCaseSchema).min(1),
|
|
98
|
-
to: udlSnakeCaseSchema,
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const udlLifecycleSchema = z.strictObject({
|
|
102
|
-
initial: udlSnakeCaseSchema,
|
|
103
|
-
states: z.array(udlSnakeCaseSchema).min(1),
|
|
104
|
-
transitions: z.record(udlActionNameSchema, udlLifecycleTransitionSchema),
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const udlUpdatePolicySchema = z.strictObject({
|
|
108
|
-
examples: z.array(udlExampleSchema).optional(),
|
|
109
|
-
fields: z.array(udlFieldNameSchema).min(1),
|
|
110
|
-
states: z.array(udlSnakeCaseSchema).min(1),
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
const udlGateSchema = z.strictObject({
|
|
114
|
-
/** Local field key <- referenced instance path; create actions only. */
|
|
115
|
-
bind: z.record(udlFieldNameSchema, fieldPathSchema).optional(),
|
|
116
|
-
field: udlFieldNameSchema,
|
|
117
|
-
/** Local instance path === referenced instance path at admission. */
|
|
118
|
-
match: z.record(fieldPathSchema, fieldPathSchema).optional(),
|
|
119
|
-
/** Opt-in over an optional reference field: absent passes, set is held to the clause. */
|
|
41
|
+
const fieldBase = {
|
|
42
|
+
name,
|
|
43
|
+
label: text.optional(),
|
|
120
44
|
optional: z.literal(true).optional(),
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
unique: z.literal(true).optional(),
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
const udlBindingSchema = z.discriminatedUnion("from", [
|
|
127
|
-
z.strictObject({ from: z.literal("const"), value: z.string() }),
|
|
128
|
-
z.strictObject({ from: z.literal("instance"), path: fieldPathSchema }),
|
|
129
|
-
z.strictObject({ from: z.literal("input"), path: fieldPathSchema }),
|
|
130
|
-
]);
|
|
131
|
-
|
|
132
|
-
const udlStepOperationSchema = z.enum([
|
|
133
|
-
"account.escrow.provision",
|
|
134
|
-
"account.freeze",
|
|
135
|
-
"account.unfreeze",
|
|
136
|
-
]);
|
|
137
|
-
|
|
138
|
-
const udlMoveOperationSchema = z.enum([
|
|
139
|
-
"internal_transfer.create",
|
|
140
|
-
"internal_transfer.reserve",
|
|
141
|
-
"internal_transfer.post",
|
|
142
|
-
"internal_transfer.void",
|
|
143
|
-
]);
|
|
144
|
-
|
|
145
|
-
export const udlKernelOperationSchema = z.enum([
|
|
146
|
-
...udlStepOperationSchema.options,
|
|
147
|
-
...udlMoveOperationSchema.options,
|
|
148
|
-
]);
|
|
149
|
-
|
|
150
|
-
const udlStepSchema = z.strictObject({
|
|
151
|
-
bind: z.record(fieldPathSchema, udlBindingSchema),
|
|
152
|
-
capture: stringMapSchema.optional(),
|
|
153
|
-
operation: udlStepOperationSchema,
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
const udlMoveSchema = z.strictObject({
|
|
157
|
-
bind: z.record(fieldPathSchema, udlBindingSchema),
|
|
158
|
-
capture: stringMapSchema.optional(),
|
|
159
|
-
key: udlSnakeCaseSchema,
|
|
160
|
-
operation: udlMoveOperationSchema,
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
const udlDueRecurrenceSchema = z.strictObject({
|
|
164
|
-
countField: udlFieldNameSchema.optional(),
|
|
165
|
-
delinquency: z.literal("parent_policy").optional(),
|
|
166
|
-
drainAction: udlActionNameSchema.optional(),
|
|
167
|
-
period: z.union([
|
|
168
|
-
nonEmptyTextSchema,
|
|
169
|
-
z.strictObject({
|
|
170
|
-
calendar: z.enum(["gregorian", "hijri"]),
|
|
171
|
-
monthEnd: z.literal("clamp_to_last_day"),
|
|
172
|
-
months: z.number().int().positive(),
|
|
173
|
-
}),
|
|
174
|
-
]),
|
|
175
|
-
liability: z.literal("one_open").optional(),
|
|
176
|
-
untilAction: udlActionNameSchema.optional(),
|
|
177
|
-
untilField: udlFieldNameSchema.optional(),
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
const udlDueParentStatusSchema = z.strictObject({
|
|
181
|
-
instrumentId: udlSnakeCaseSchema,
|
|
182
|
-
refField: udlFieldNameSchema,
|
|
183
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
const udlDueSchema = z.strictObject({
|
|
187
|
-
every: udlDueRecurrenceSchema.optional(),
|
|
188
|
-
field: udlFieldNameSchema,
|
|
189
|
-
offset: nonEmptyTextSchema.optional(),
|
|
190
|
-
whenParentStatus: udlDueParentStatusSchema.optional(),
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
const udlDeadlineSchema = z.strictObject({
|
|
194
|
-
field: udlFieldNameSchema,
|
|
195
|
-
offset: nonEmptyTextSchema.optional(),
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
const udlSetsAtSchema = z.strictObject({
|
|
199
|
-
field: udlFieldNameSchema,
|
|
200
|
-
marker: z.literal(true).optional(),
|
|
201
|
-
offset: nonEmptyTextSchema,
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
const udlQuoteChargeSchema = z.strictObject({
|
|
205
|
-
bps: z.number().int().min(0).max(9_999),
|
|
206
|
-
withinOffset: nonEmptyTextSchema.optional(),
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
// A priced, expiring offer. The quoting action splits `baseField` into a charge
|
|
210
|
-
// and a net at its own clock, freezes the fields the price was read from, and
|
|
211
|
-
// stamps an expiry. Only the paired `commit` action may spend the offer, and
|
|
212
|
-
// only while it is unexpired and its frozen fields still hold.
|
|
213
|
-
const udlQuoteShape = {
|
|
214
|
-
/** Date-time whose remaining time picks the charge tier; omit for elapsed age. */
|
|
215
|
-
anchorField: udlFieldNameSchema.optional(),
|
|
216
|
-
baseField: udlFieldNameSchema,
|
|
217
|
-
chargeRef: udlFieldNameSchema,
|
|
218
|
-
charges: z.array(udlQuoteChargeSchema).min(1),
|
|
219
|
-
/** Fixed ISO-8601 duration from the quoting action, or a stored deadline. */
|
|
220
|
-
expires: z.union([
|
|
221
|
-
z.strictObject({ field: udlFieldNameSchema }),
|
|
222
|
-
z.strictObject({ offset: nonEmptyTextSchema }),
|
|
223
|
-
]),
|
|
224
|
-
fixes: z.array(udlFieldNameSchema).min(1),
|
|
225
|
-
netDestinationField: udlFieldNameSchema,
|
|
226
|
-
netRef: udlFieldNameSchema,
|
|
45
|
+
description: text.optional(),
|
|
46
|
+
sensitive: z.literal(true).optional(),
|
|
227
47
|
};
|
|
228
|
-
const udlQuoteSchema = z.strictObject(udlQuoteShape);
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Where a quoting action stamps the instant its offer stops being committable.
|
|
232
|
-
* Derived from the author's net ref rather than a fixed name, so two offers on
|
|
233
|
-
* one instrument never share the slot.
|
|
234
|
-
*/
|
|
235
|
-
export function quoteExpiresAtRefKey(quote: {
|
|
236
|
-
readonly netRef: string;
|
|
237
|
-
}): string {
|
|
238
|
-
return `${quote.netRef}ExpiresAt`;
|
|
239
|
-
}
|
|
240
48
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Every ref key one quote seeds: the charge and the net the author named, plus
|
|
252
|
-
* the two the machinery derives to hold the offer itself. One derivation, read
|
|
253
|
-
* by the validator, the compiler, and the runtime alike.
|
|
254
|
-
*/
|
|
255
|
-
export function quoteSeededRefKeys(quote: {
|
|
256
|
-
readonly chargeRef: string;
|
|
257
|
-
readonly netRef: string;
|
|
258
|
-
}): readonly string[] {
|
|
259
|
-
return [
|
|
260
|
-
quote.chargeRef,
|
|
261
|
-
quote.netRef,
|
|
262
|
-
quoteExpiresAtRefKey(quote),
|
|
263
|
-
quoteFrozenRefKey(quote),
|
|
264
|
-
];
|
|
265
|
-
}
|
|
49
|
+
const referenceField = z.strictObject({
|
|
50
|
+
...fieldBase,
|
|
51
|
+
type: z.literal("ref"),
|
|
52
|
+
targetKind: z.enum(["instrument", "object"]),
|
|
53
|
+
targetFamily: udlFamilySchema.optional(),
|
|
54
|
+
target: z.union([name, z.array(name).min(1).max(16)]),
|
|
55
|
+
});
|
|
266
56
|
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
onTimeout: z.literal("decline"),
|
|
57
|
+
const listField = z.strictObject({
|
|
58
|
+
...fieldBase,
|
|
59
|
+
type: z.literal("list"),
|
|
60
|
+
item: z.enum(["money", "date", "text", "integer", "ref"]),
|
|
61
|
+
targetKind: z.enum(["instrument", "object"]).optional(),
|
|
62
|
+
targetFamily: udlFamilySchema.optional(),
|
|
63
|
+
target: name.optional(),
|
|
64
|
+
maxItems: integer.min(1).max(366),
|
|
276
65
|
});
|
|
277
66
|
|
|
278
|
-
const
|
|
67
|
+
export const udlFieldSchema = z.discriminatedUnion("type", [
|
|
68
|
+
z.strictObject({
|
|
69
|
+
...fieldBase,
|
|
70
|
+
type: z.literal("money"),
|
|
71
|
+
value: amount.optional(),
|
|
72
|
+
minimum: amount.optional(),
|
|
73
|
+
maximum: amount.optional(),
|
|
74
|
+
}),
|
|
75
|
+
z.strictObject({
|
|
76
|
+
...fieldBase,
|
|
77
|
+
type: z.literal("account"),
|
|
78
|
+
owner: z.union([name, z.strictObject({ adapter: name })]),
|
|
79
|
+
key: name.optional(),
|
|
80
|
+
book: z.enum(["cash", "claim"]).default("cash"),
|
|
81
|
+
contra: z.literal(true).optional(),
|
|
82
|
+
}),
|
|
83
|
+
referenceField,
|
|
84
|
+
z.strictObject({
|
|
85
|
+
...fieldBase,
|
|
86
|
+
type: z.literal("date"),
|
|
87
|
+
value: z.iso.datetime({ offset: true }).optional(),
|
|
88
|
+
}),
|
|
279
89
|
z.strictObject({
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
90
|
+
...fieldBase,
|
|
91
|
+
type: z.literal("duration"),
|
|
92
|
+
value: integer.positive().optional(),
|
|
283
93
|
}),
|
|
284
94
|
z.strictObject({
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
95
|
+
...fieldBase,
|
|
96
|
+
type: z.literal("text"),
|
|
97
|
+
value: text.optional(),
|
|
98
|
+
minLength: integer.positive().max(2048).optional(),
|
|
99
|
+
maxLength: integer.positive().max(2048).optional(),
|
|
100
|
+
// One anchored ASCII character class and a fixed repetition. No executable patterns.
|
|
101
|
+
pattern: z
|
|
102
|
+
.string()
|
|
103
|
+
.regex(/^\^\[[A-Za-z0-9-]+\]\{[1-9][0-9]{0,3}\}\$$/)
|
|
104
|
+
.optional(),
|
|
288
105
|
}),
|
|
289
106
|
z.strictObject({
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
107
|
+
...fieldBase,
|
|
108
|
+
type: z.literal("integer"),
|
|
109
|
+
value: integer.optional(),
|
|
110
|
+
minimum: integer.optional(),
|
|
111
|
+
maximum: integer.optional(),
|
|
293
112
|
}),
|
|
294
|
-
// Siblings summed against a cap read from the LOCKED anchor row's
|
|
295
|
-
// machinery-seeded ref (never a stored field on the counted rows).
|
|
296
113
|
z.strictObject({
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
114
|
+
...fieldBase,
|
|
115
|
+
type: z.literal("percent"),
|
|
116
|
+
value: integer.min(0).max(10000).optional(),
|
|
300
117
|
}),
|
|
301
118
|
z.strictObject({
|
|
302
|
-
|
|
303
|
-
|
|
119
|
+
...fieldBase,
|
|
120
|
+
type: z.literal("boolean"),
|
|
121
|
+
value: z.boolean().optional(),
|
|
304
122
|
}),
|
|
305
|
-
z.strictObject({ kind: z.literal("all_in") }),
|
|
306
123
|
z.strictObject({
|
|
307
|
-
|
|
308
|
-
|
|
124
|
+
...fieldBase,
|
|
125
|
+
type: z.literal("enum"),
|
|
126
|
+
values: z.array(name).min(1).max(64),
|
|
127
|
+
value: name.optional(),
|
|
309
128
|
}),
|
|
129
|
+
listField,
|
|
310
130
|
]);
|
|
311
131
|
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
132
|
+
const [
|
|
133
|
+
moneyField,
|
|
134
|
+
,
|
|
135
|
+
refField,
|
|
136
|
+
dateField,
|
|
137
|
+
durationField,
|
|
138
|
+
textField,
|
|
139
|
+
integerField,
|
|
140
|
+
percentField,
|
|
141
|
+
booleanField,
|
|
142
|
+
enumField,
|
|
143
|
+
boundedListField,
|
|
144
|
+
] = udlFieldSchema.options;
|
|
145
|
+
|
|
146
|
+
export const udlObjectFieldSchema = z.discriminatedUnion("type", [
|
|
147
|
+
moneyField,
|
|
148
|
+
refField,
|
|
149
|
+
dateField,
|
|
150
|
+
durationField,
|
|
151
|
+
textField,
|
|
152
|
+
integerField,
|
|
153
|
+
percentField,
|
|
154
|
+
booleanField,
|
|
155
|
+
enumField,
|
|
156
|
+
boundedListField,
|
|
157
|
+
]);
|
|
337
158
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
159
|
+
/** Values are constants or resolved typed paths, never executable strings. */
|
|
160
|
+
export const udlValueSchema = z.union([
|
|
161
|
+
z.strictObject({ literal: scalar }),
|
|
162
|
+
z.strictObject({ field: path }),
|
|
163
|
+
]);
|
|
164
|
+
const value = udlValueSchema;
|
|
165
|
+
|
|
166
|
+
const comparisonRequirement = z.strictObject({
|
|
167
|
+
kind: z.literal("compare"),
|
|
168
|
+
left: value,
|
|
169
|
+
operator: z.enum(["==", "!=", "<", "<=", ">", ">="]),
|
|
170
|
+
right: value,
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Alternatives are OR; each invocation path is a conjunction of scoped guards.
|
|
174
|
+
export const udlSubjectConditionsSchema = z
|
|
175
|
+
.array(
|
|
176
|
+
z
|
|
177
|
+
.array(
|
|
178
|
+
z.strictObject({
|
|
179
|
+
instrument: instrumentId,
|
|
180
|
+
action: name,
|
|
181
|
+
guard: comparisonRequirement,
|
|
182
|
+
valueType: z.enum(["money", "date"]).optional(),
|
|
183
|
+
}),
|
|
184
|
+
)
|
|
185
|
+
.min(1)
|
|
186
|
+
.max(32),
|
|
187
|
+
)
|
|
188
|
+
.min(1)
|
|
189
|
+
.max(128);
|
|
190
|
+
|
|
191
|
+
export const udlSubjectRequirementSchema = z.strictObject({
|
|
192
|
+
field: udlObjectFieldSchema,
|
|
193
|
+
// Present only for an authored rename.
|
|
194
|
+
objectField: name.optional(),
|
|
195
|
+
when: udlSubjectConditionsSchema.optional(),
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
export const adapterSubjectSnapshotSchema = z.strictObject({
|
|
199
|
+
provider: text,
|
|
200
|
+
capability: text,
|
|
201
|
+
operation: text,
|
|
202
|
+
declarationDigest: z.string().regex(/^[a-f0-9]{64}$/),
|
|
203
|
+
requirements: z.array(udlObjectFieldSchema).max(128),
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
export const udlActionSubjectSchema = z.strictObject({
|
|
207
|
+
requirements: z.array(udlSubjectRequirementSchema).max(128),
|
|
208
|
+
adapters: z
|
|
209
|
+
.array(
|
|
210
|
+
z.strictObject({
|
|
211
|
+
binding: name,
|
|
212
|
+
// null means unavailable, never "no requirements".
|
|
213
|
+
snapshot: adapterSubjectSnapshotSchema.nullable(),
|
|
214
|
+
renames: z.record(name, name).optional(),
|
|
215
|
+
}),
|
|
216
|
+
)
|
|
217
|
+
.max(16),
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
export const subjectPartyRoles = ["owner", "actor", "operator"] as const;
|
|
221
|
+
export const attachmentPartyBindingSchema = z.union([
|
|
222
|
+
z.strictObject({ role: z.enum(subjectPartyRoles) }),
|
|
223
|
+
z.strictObject({ party: name }),
|
|
224
|
+
]);
|
|
225
|
+
export type AttachmentPartyBinding = z.infer<
|
|
226
|
+
typeof attachmentPartyBindingSchema
|
|
227
|
+
>;
|
|
228
|
+
export const udlObjectAttachmentSchema = z.strictObject({
|
|
229
|
+
name,
|
|
230
|
+
title: text.optional(),
|
|
231
|
+
parent: name.optional(),
|
|
232
|
+
instrument: instrumentId,
|
|
233
|
+
parties: z.record(name, attachmentPartyBindingSchema),
|
|
234
|
+
});
|
|
235
|
+
export type SubjectPartyRole = (typeof subjectPartyRoles)[number];
|
|
236
|
+
export type UdlObjectAttachment = z.infer<typeof udlObjectAttachmentSchema>;
|
|
237
|
+
|
|
238
|
+
export const udlObjectKindSchema = z.strictObject({
|
|
239
|
+
entryActions: z.array(name).min(1).max(128).optional(),
|
|
240
|
+
id: objectKindId,
|
|
241
|
+
title: text,
|
|
242
|
+
authoredFields: z.array(name).max(256),
|
|
243
|
+
attachments: z.array(udlObjectAttachmentSchema).max(256),
|
|
244
|
+
fields: z.array(udlObjectFieldSchema).max(256),
|
|
245
|
+
columns: z.array(name).max(8),
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
const values = z.array(value).min(1).max(256);
|
|
249
|
+
|
|
250
|
+
const selection = z.strictObject({
|
|
251
|
+
family: udlFamilySchema.optional(),
|
|
252
|
+
instrument: z.union([instrumentId, z.array(instrumentId).min(1).max(16)]),
|
|
253
|
+
reference: name,
|
|
254
|
+
anchor: path,
|
|
255
|
+
states: z.array(name).min(1).max(64),
|
|
256
|
+
limit: integer.min(1).max(366),
|
|
257
|
+
order: z.array(path).min(1).max(4).optional(),
|
|
258
|
+
window: z
|
|
259
|
+
.strictObject({ field: name, milliseconds: integer.positive() })
|
|
260
|
+
.optional(),
|
|
261
|
+
where: z
|
|
262
|
+
.record(path, value)
|
|
263
|
+
.refine(
|
|
264
|
+
(filters) => Object.keys(filters).length <= 8,
|
|
265
|
+
"at most eight selection filters",
|
|
266
|
+
)
|
|
267
|
+
.meta({ maxProperties: 8 })
|
|
268
|
+
.optional(),
|
|
346
269
|
});
|
|
347
270
|
|
|
348
|
-
/**
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
*/
|
|
356
|
-
const udlReconcileSchema = z.strictObject({
|
|
357
|
-
/** `fields.<name>` or `refs.<name>`: the money this action says will land. */
|
|
358
|
-
amount: instanceValuePathSchema,
|
|
359
|
-
/** Where the matched evidence id lands in refs. */
|
|
360
|
-
capture: udlFieldNameSchema,
|
|
361
|
-
/** The ref naming the provider-side row the evidence must cite. */
|
|
362
|
-
counterpartyRef: udlFieldNameSchema,
|
|
363
|
-
currencyField: udlFieldNameSchema,
|
|
364
|
-
direction: z.enum(["credit", "debit"]),
|
|
365
|
-
/** Exactly one source. A reconcile never reads two ledgers at once. */
|
|
366
|
-
evidence: z.enum(["movement", "provider_confirmation", "statement_line"]),
|
|
367
|
-
/**
|
|
368
|
-
* Where an expectation that never matched lands. The named child instrument
|
|
369
|
-
* carries the break, and `maxOpen` caps how many of them one instance may
|
|
370
|
-
* hold open at once, the same count measure the aggregate invariants use.
|
|
371
|
-
*/
|
|
372
|
-
exception: z.strictObject({
|
|
373
|
-
amountField: udlFieldNameSchema,
|
|
374
|
-
childInstrumentId: udlSnakeCaseSchema,
|
|
375
|
-
maxOpen: z.number().int().min(1).max(1_000),
|
|
376
|
-
reasonField: udlFieldNameSchema,
|
|
377
|
-
refField: udlFieldNameSchema,
|
|
271
|
+
/** A finite, ordered calculation graph. Every result is a declared field. */
|
|
272
|
+
export const udlCalculationSchema = z.discriminatedUnion("op", [
|
|
273
|
+
z.strictObject({
|
|
274
|
+
target: name,
|
|
275
|
+
op: z.literal("at"),
|
|
276
|
+
list: path,
|
|
277
|
+
position: value,
|
|
378
278
|
}),
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
match: z.discriminatedUnion("law", [
|
|
385
|
-
z.strictObject({ law: z.literal("exact") }),
|
|
386
|
-
z.strictObject({
|
|
387
|
-
dial: udlSnakeCaseSchema,
|
|
388
|
-
law: z.literal("tolerance"),
|
|
389
|
-
minorUnits: z.number().int().positive(),
|
|
390
|
-
}),
|
|
391
|
-
z.strictObject({ law: z.literal("window") }),
|
|
392
|
-
]),
|
|
393
|
-
/** Fixed ISO-8601 duration from the expecting action, or a stored deadline. */
|
|
394
|
-
within: z.union([
|
|
395
|
-
z.strictObject({ field: udlFieldNameSchema }),
|
|
396
|
-
z.strictObject({ offset: nonEmptyTextSchema }),
|
|
397
|
-
]),
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
const udlSignedSumSourceSchema = z.strictObject({
|
|
401
|
-
amountField: udlFieldNameSchema,
|
|
402
|
-
instrumentId: udlSnakeCaseSchema,
|
|
403
|
-
refField: udlFieldNameSchema,
|
|
404
|
-
sign: z.enum(["add", "subtract"]),
|
|
405
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
406
|
-
subtotalRef: udlFieldNameSchema,
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
const udlSignedSumSchema = z.strictObject({
|
|
410
|
-
amountRef: udlFieldNameSchema,
|
|
411
|
-
onNegative: z.literal("refuse"),
|
|
412
|
-
onZero: z.enum(["refuse", "skip_steps"]),
|
|
413
|
-
sources: z.array(udlSignedSumSourceSchema).min(1),
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
const udlDistributeSchema = z.strictObject({
|
|
417
|
-
amountRef: udlFieldNameSchema,
|
|
418
|
-
onZero: z.enum(["refuse", "skip_steps"]),
|
|
419
|
-
pool: z.strictObject({
|
|
420
|
-
from: z.literal("parent"),
|
|
421
|
-
path: fieldPathSchema,
|
|
279
|
+
z.strictObject({
|
|
280
|
+
target: name,
|
|
281
|
+
op: z.literal("aggregate"),
|
|
282
|
+
selection,
|
|
283
|
+
measure: z.union([z.literal("count"), z.strictObject({ sum: path })]),
|
|
422
284
|
}),
|
|
423
|
-
refField: udlFieldNameSchema,
|
|
424
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
425
|
-
weightField: udlFieldNameSchema,
|
|
426
|
-
});
|
|
427
|
-
|
|
428
|
-
const udlRemainderCollectedSchema = z.strictObject({
|
|
429
|
-
amountField: udlFieldNameSchema,
|
|
430
|
-
instrumentId: udlSnakeCaseSchema,
|
|
431
|
-
path: z.literal("refs").optional(),
|
|
432
|
-
refField: udlFieldNameSchema,
|
|
433
|
-
statuses: z.array(udlSnakeCaseSchema).min(1),
|
|
434
|
-
});
|
|
435
|
-
|
|
436
|
-
const udlRemainderSchema = z.strictObject({
|
|
437
|
-
accumulateRef: udlFieldNameSchema.optional(),
|
|
438
|
-
amountRef: udlFieldNameSchema,
|
|
439
|
-
collected: z.array(udlRemainderCollectedSchema).optional(),
|
|
440
|
-
inputKey: udlFieldNameSchema.optional(),
|
|
441
|
-
onZero: z.enum(["refuse", "skip_steps"]),
|
|
442
|
-
totalPath: instanceValuePathSchema,
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
type UdlCheckRequirementShape = {
|
|
446
|
-
checkKind: string;
|
|
447
|
-
family: z.infer<typeof udlProviderFamilyIdSchema>;
|
|
448
|
-
maxAge?: string;
|
|
449
|
-
statuses: string[];
|
|
450
|
-
subjectField: string;
|
|
451
|
-
};
|
|
452
|
-
|
|
453
|
-
const udlCheckRequirementVariants = udlCheckEvidenceProfiles.map((profile) =>
|
|
454
285
|
z.strictObject({
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
286
|
+
target: name,
|
|
287
|
+
op: z.literal("ratio"),
|
|
288
|
+
amount: value,
|
|
289
|
+
numerator: value,
|
|
290
|
+
denominator: value,
|
|
291
|
+
rounding: z.literal("floor"),
|
|
460
292
|
}),
|
|
461
|
-
|
|
462
|
-
z.ZodType<UdlCheckRequirementShape>,
|
|
463
|
-
z.ZodType<UdlCheckRequirementShape>,
|
|
464
|
-
...z.ZodType<UdlCheckRequirementShape>[],
|
|
465
|
-
];
|
|
466
|
-
|
|
467
|
-
const udlCheckRequirementSchema = z.union(udlCheckRequirementVariants);
|
|
468
|
-
|
|
469
|
-
const udlDialSchema = z.discriminatedUnion("kind", [
|
|
293
|
+
z.strictObject({ target: name, op: z.literal("sum"), values }),
|
|
470
294
|
z.strictObject({
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
minOffset: nonEmptyTextSchema.optional(),
|
|
476
|
-
summary: nonEmptyTextSchema,
|
|
477
|
-
title: nonEmptyTextSchema,
|
|
295
|
+
target: name,
|
|
296
|
+
op: z.literal("subtract"),
|
|
297
|
+
base: value,
|
|
298
|
+
subtract: values,
|
|
478
299
|
}),
|
|
479
300
|
z.strictObject({
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
summary: nonEmptyTextSchema,
|
|
486
|
-
title: nonEmptyTextSchema,
|
|
301
|
+
target: name,
|
|
302
|
+
op: z.literal("rate"),
|
|
303
|
+
base: value,
|
|
304
|
+
bps: value,
|
|
305
|
+
rounding: z.literal("floor"),
|
|
487
306
|
}),
|
|
307
|
+
z.strictObject({ target: name, op: z.literal("minimum"), values }),
|
|
488
308
|
z.strictObject({
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
summary: nonEmptyTextSchema,
|
|
494
|
-
title: nonEmptyTextSchema,
|
|
309
|
+
target: name,
|
|
310
|
+
op: z.literal("multiply"),
|
|
311
|
+
amount: value,
|
|
312
|
+
units: value,
|
|
495
313
|
}),
|
|
496
314
|
z.strictObject({
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
315
|
+
target: name,
|
|
316
|
+
op: z.literal("divide"),
|
|
317
|
+
amount: value,
|
|
318
|
+
divisor: value,
|
|
319
|
+
rounding: z.literal("floor"),
|
|
320
|
+
}),
|
|
321
|
+
z.strictObject({
|
|
322
|
+
target: name,
|
|
323
|
+
op: z.literal("shift"),
|
|
324
|
+
date: value,
|
|
325
|
+
milliseconds: value,
|
|
326
|
+
direction: z.enum(["before", "after"]),
|
|
501
327
|
}),
|
|
502
328
|
]);
|
|
503
329
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
totalField: udlFieldNameSchema,
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
const udlDerivedAmountSchema = z.strictObject({
|
|
526
|
-
field: udlFieldNameSchema,
|
|
527
|
-
rounding: z.literal("floor"),
|
|
528
|
-
rule: z.strictObject({
|
|
529
|
-
bps: z.number().int().min(1).max(9_999),
|
|
530
|
-
kind: z.literal("percentage_of"),
|
|
330
|
+
export const udlRequirementSchema = z.discriminatedUnion("kind", [
|
|
331
|
+
z.strictObject({
|
|
332
|
+
kind: z.literal("hours"),
|
|
333
|
+
at: path,
|
|
334
|
+
start: integer.min(0).max(23),
|
|
335
|
+
end: integer.min(0).max(23),
|
|
336
|
+
timezone: text,
|
|
337
|
+
}),
|
|
338
|
+
comparisonRequirement,
|
|
339
|
+
z.strictObject({
|
|
340
|
+
kind: z.literal("state"),
|
|
341
|
+
reference: path,
|
|
342
|
+
states: z.array(name).min(1).max(64),
|
|
343
|
+
}),
|
|
344
|
+
z.strictObject({
|
|
345
|
+
kind: z.literal("unique"),
|
|
346
|
+
namespace: name,
|
|
347
|
+
fields: z.array(path).min(1).max(8),
|
|
531
348
|
}),
|
|
532
|
-
sourceField: udlFieldNameSchema,
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
const udlFeeLeafRuleSchema = z.discriminatedUnion("kind", [
|
|
536
349
|
z.strictObject({
|
|
537
|
-
|
|
538
|
-
|
|
350
|
+
kind: z.literal("aggregate"),
|
|
351
|
+
selection,
|
|
352
|
+
measure: z.union([z.literal("count"), z.strictObject({ sum: path })]),
|
|
353
|
+
operator: z.enum(["==", "<=", ">=", "<", ">"]),
|
|
354
|
+
value,
|
|
539
355
|
}),
|
|
540
356
|
z.strictObject({
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
357
|
+
kind: z.literal("evidence"),
|
|
358
|
+
instruction: path.optional(),
|
|
359
|
+
subject: path,
|
|
360
|
+
family: name,
|
|
361
|
+
check: name,
|
|
362
|
+
result: name,
|
|
363
|
+
maxAge: integer.positive(),
|
|
544
364
|
}),
|
|
545
365
|
]);
|
|
546
366
|
|
|
547
|
-
const
|
|
548
|
-
.
|
|
549
|
-
.
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
.array(
|
|
562
|
-
z.strictObject({
|
|
563
|
-
fromInclusive: nonNegativeDecimalIntegerSchema,
|
|
564
|
-
rule: udlFeeLeafRuleSchema,
|
|
565
|
-
toExclusive: nonNegativeDecimalIntegerSchema.optional(),
|
|
566
|
-
}),
|
|
567
|
-
)
|
|
568
|
-
.min(1)
|
|
569
|
-
.max(16),
|
|
570
|
-
}),
|
|
367
|
+
export const udlKernelOperationSchema = z.enum([
|
|
368
|
+
"internal_transfer.create",
|
|
369
|
+
"internal_transfer.reserve",
|
|
370
|
+
"internal_transfer.post",
|
|
371
|
+
"internal_transfer.void",
|
|
372
|
+
]);
|
|
373
|
+
const moveEconomics = z.strictObject({
|
|
374
|
+
purpose: z.enum([
|
|
375
|
+
"earning",
|
|
376
|
+
"principal",
|
|
377
|
+
"participant_payout",
|
|
378
|
+
"internal",
|
|
379
|
+
"prepaid_credit",
|
|
380
|
+
"pass_through",
|
|
571
381
|
]),
|
|
382
|
+
sourceParty: name,
|
|
383
|
+
reversalOf: path.optional(),
|
|
572
384
|
});
|
|
573
|
-
|
|
574
|
-
const udlDecidedAmountSchema = z.strictObject({
|
|
575
|
-
boundField: udlFieldNameSchema,
|
|
576
|
-
field: udlFieldNameSchema,
|
|
577
|
-
remainderAction: udlActionNameSchema,
|
|
578
|
-
});
|
|
579
|
-
|
|
580
|
-
const udlEffectRowSchema = z.strictObject({
|
|
581
|
-
signature: nonEmptyTextSchema,
|
|
582
|
-
source: nonEmptyTextSchema,
|
|
583
|
-
});
|
|
584
|
-
|
|
585
|
-
const udlNotifyEffectSchema = z.strictObject({
|
|
586
|
-
channel: udlSnakeCaseSchema,
|
|
587
|
-
role: udlSnakeCaseSchema,
|
|
588
|
-
signature: nonEmptyTextSchema,
|
|
589
|
-
source: nonEmptyTextSchema,
|
|
590
|
-
});
|
|
591
|
-
|
|
592
|
-
const udlEffectsShape = {
|
|
593
|
-
decides: z.array(udlEffectRowSchema).min(1).optional(),
|
|
594
|
-
holds: z.array(udlEffectRowSchema).min(1).optional(),
|
|
595
|
-
moves: z.array(udlEffectRowSchema).min(1).optional(),
|
|
596
|
-
notifies: z.array(udlNotifyEffectSchema).min(1).optional(),
|
|
597
|
-
reads: z.array(udlEffectRowSchema).min(1).optional(),
|
|
598
|
-
schedules: z.array(udlEffectRowSchema).min(1).optional(),
|
|
599
|
-
} satisfies Record<UdlEffectKind, z.ZodType>;
|
|
600
|
-
const udlEffectsSchema = z.strictObject(udlEffectsShape);
|
|
601
|
-
|
|
602
|
-
const udlActionShape = {
|
|
603
|
-
agentDescription: udlAgentDescriptionSchema.optional(),
|
|
604
|
-
captureInput: z.record(udlFieldNameSchema, udlFieldNameSchema).optional(),
|
|
605
|
-
/** Names the quoting action whose offer this action spends. */
|
|
606
|
-
commit: udlActionNameSchema.optional(),
|
|
607
|
-
decidedAmount: udlDecidedAmountSchema.optional(),
|
|
608
|
-
deadline: udlDeadlineSchema.optional(),
|
|
609
|
-
decision: udlDecisionSchema.optional(),
|
|
610
|
-
distribute: udlDistributeSchema.optional(),
|
|
611
|
-
description: nonEmptyTextSchema.optional(),
|
|
612
|
-
due: udlDueSchema.optional(),
|
|
613
|
-
earnable: z.boolean().optional(),
|
|
614
|
-
effects: udlEffectsSchema.optional(),
|
|
615
|
-
eventName: z.string().regex(eventNamePattern).optional(),
|
|
616
|
-
examples: z.array(udlExampleSchema).min(1).optional(),
|
|
617
|
-
input: jsonObjectSchema.optional(),
|
|
618
|
-
moves: z.array(udlMoveSchema).default([]),
|
|
619
|
-
payout: udlPayoutSchema.optional(),
|
|
620
|
-
port: udlPortSchema.optional(),
|
|
621
|
-
quote: udlQuoteSchema.optional(),
|
|
622
|
-
publicAction: udlPublicActionSchema
|
|
623
|
-
.optional()
|
|
624
|
-
.describe(
|
|
625
|
-
"Author-approved public action name; the containing action key remains the lifecycle and execution identity",
|
|
626
|
-
),
|
|
627
|
-
principal: z.literal("user_session").optional(),
|
|
628
|
-
reconcile: z.array(udlReconcileSchema).min(1).optional(),
|
|
629
|
-
remainder: udlRemainderSchema.optional(),
|
|
630
|
-
requiresAggregate: z.array(udlAggregateConditionSchema).min(1).optional(),
|
|
631
|
-
requiresChecks: z.array(udlCheckRequirementSchema).optional(),
|
|
632
|
-
requiresDrainedAccount: z.strictObject({ path: fieldPathSchema }).optional(),
|
|
633
|
-
requiresExposure: z.array(udlExposureRequirementSchema).min(1).optional(),
|
|
634
|
-
requiresRefs: z.array(udlGateSchema).min(1).optional(),
|
|
635
|
-
sandboxFailurePoint: z.enum(["funding", "release"]).optional(),
|
|
636
|
-
setsAt: udlSetsAtSchema.optional(),
|
|
637
|
-
signedSum: udlSignedSumSchema.optional(),
|
|
638
|
-
steps: z.array(udlStepSchema),
|
|
639
|
-
summary: nonEmptyTextSchema,
|
|
640
|
-
updates: z.array(udlFieldNameSchema).min(1).optional(),
|
|
641
|
-
};
|
|
642
|
-
const udlActionSchema = z.strictObject(udlActionShape);
|
|
643
|
-
|
|
644
|
-
const udlAggregateBaseShape = {
|
|
645
|
-
childInstrumentId: udlSnakeCaseSchema,
|
|
646
|
-
childRefField: udlFieldNameSchema,
|
|
647
|
-
childStatuses: z.array(udlSnakeCaseSchema).min(1),
|
|
648
|
-
parentField: udlFieldNameSchema,
|
|
649
|
-
};
|
|
650
|
-
|
|
651
|
-
// Two measures, mutually exclusive by strictness: a sum cap over a child money
|
|
652
|
-
// field, or a count cap (optionally windowed to the rolling `days` ending at
|
|
653
|
-
// the child's own as-written date-time value).
|
|
654
|
-
const udlAggregateSchema = z.union([
|
|
385
|
+
export const udlMoveSchema = z.discriminatedUnion("operation", [
|
|
655
386
|
z.strictObject({
|
|
656
|
-
|
|
657
|
-
|
|
387
|
+
key: name,
|
|
388
|
+
operation: z.literal("internal_transfer.create"),
|
|
389
|
+
economics: moveEconomics.optional(),
|
|
390
|
+
capture: name.optional(),
|
|
391
|
+
amount: value,
|
|
392
|
+
from: path,
|
|
393
|
+
to: path,
|
|
658
394
|
}),
|
|
659
395
|
z.strictObject({
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
396
|
+
key: name,
|
|
397
|
+
operation: z.literal("internal_transfer.reserve"),
|
|
398
|
+
economics: moveEconomics.optional(),
|
|
399
|
+
boundary: z.strictObject({ adapter: name }).optional(),
|
|
400
|
+
amount: value,
|
|
401
|
+
from: path,
|
|
402
|
+
to: path,
|
|
403
|
+
capture: name,
|
|
404
|
+
}),
|
|
405
|
+
z.strictObject({
|
|
406
|
+
key: name,
|
|
407
|
+
operation: z.literal("internal_transfer.post"),
|
|
408
|
+
economics: moveEconomics.optional(),
|
|
409
|
+
capture: name.optional(),
|
|
410
|
+
transfer: path,
|
|
411
|
+
}),
|
|
412
|
+
z.strictObject({
|
|
413
|
+
key: name,
|
|
414
|
+
operation: z.literal("internal_transfer.void"),
|
|
415
|
+
economics: moveEconomics.optional(),
|
|
416
|
+
capture: name.optional(),
|
|
417
|
+
transfer: path,
|
|
668
418
|
}),
|
|
669
419
|
]);
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
420
|
+
const clock = z.strictObject({
|
|
421
|
+
at: path,
|
|
422
|
+
offset: integer.optional(),
|
|
423
|
+
localDay: z
|
|
424
|
+
.strictObject({
|
|
425
|
+
days: integer.min(0).max(366),
|
|
426
|
+
direction: z.enum(["before", "after"]),
|
|
427
|
+
hour: integer.min(0).max(23),
|
|
428
|
+
timezone: text,
|
|
429
|
+
})
|
|
677
430
|
.optional(),
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
.regex(idPrefixPattern, "must contain 2 to 8 lowercase letters"),
|
|
688
|
-
lifecycle: udlLifecycleSchema,
|
|
689
|
-
nav: z.array(nonEmptyTextSchema).min(1).optional(),
|
|
690
|
-
parties: z
|
|
431
|
+
});
|
|
432
|
+
export const udlActionSchema = z.strictObject({
|
|
433
|
+
allowZero: z.literal(true).optional(),
|
|
434
|
+
purpose: z.enum(["obligation", "option"]).optional(),
|
|
435
|
+
summary: text,
|
|
436
|
+
title: text.optional(),
|
|
437
|
+
publicAction: name.optional(),
|
|
438
|
+
expansionLimit: z.literal(8192).optional(),
|
|
439
|
+
reminder: z
|
|
691
440
|
.strictObject({
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
441
|
+
installment: path,
|
|
442
|
+
recipient: path,
|
|
443
|
+
dueAt: path,
|
|
444
|
+
channel: z.literal("email"),
|
|
445
|
+
template: z.literal("payment_reminder"),
|
|
446
|
+
beforeDays: integer.min(0).max(366),
|
|
447
|
+
overdueDays: integer.min(1).max(366),
|
|
448
|
+
maxPerDay: integer.min(1).max(10),
|
|
449
|
+
startHour: integer.min(0).max(23),
|
|
450
|
+
endHour: integer.min(1).max(24),
|
|
451
|
+
timezone: text,
|
|
695
452
|
})
|
|
696
453
|
.optional(),
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
signature: { fixed: "expiry" },
|
|
778
|
-
},
|
|
779
|
-
],
|
|
780
|
-
linearOutputs: ["netRef"],
|
|
781
|
-
scope: "action",
|
|
782
|
-
spelling: "quote",
|
|
783
|
-
target: "quote",
|
|
784
|
-
},
|
|
785
|
-
{
|
|
786
|
-
cardinality: "one",
|
|
787
|
-
linearOutputs: ["field"],
|
|
788
|
-
scope: "action",
|
|
789
|
-
spelling: "decided amount",
|
|
790
|
-
target: "decidedAmount",
|
|
791
|
-
},
|
|
792
|
-
{
|
|
793
|
-
cardinality: "one",
|
|
794
|
-
effects: [
|
|
795
|
-
{
|
|
796
|
-
kind: "schedules",
|
|
797
|
-
per: "clause",
|
|
798
|
-
signature: { fixed: "deadline" },
|
|
799
|
-
},
|
|
800
|
-
],
|
|
801
|
-
scope: "action",
|
|
802
|
-
spelling: "deadline",
|
|
803
|
-
target: "deadline",
|
|
804
|
-
},
|
|
805
|
-
{
|
|
806
|
-
cardinality: "one",
|
|
807
|
-
effects: [
|
|
808
|
-
{
|
|
809
|
-
kind: "decides",
|
|
810
|
-
per: "clause",
|
|
811
|
-
signature: { fromField: "capability" },
|
|
812
|
-
},
|
|
813
|
-
],
|
|
814
|
-
scope: "action",
|
|
815
|
-
spelling: "decision",
|
|
816
|
-
target: "decision",
|
|
817
|
-
},
|
|
818
|
-
{
|
|
819
|
-
cardinality: "one",
|
|
820
|
-
linearOutputs: ["amountRef"],
|
|
821
|
-
scope: "action",
|
|
822
|
-
spelling: "computes distribute",
|
|
823
|
-
target: "distribute",
|
|
824
|
-
},
|
|
825
|
-
{
|
|
826
|
-
cardinality: "one",
|
|
827
|
-
scope: "action",
|
|
828
|
-
spelling: "description",
|
|
829
|
-
target: "description",
|
|
830
|
-
},
|
|
831
|
-
{
|
|
832
|
-
cardinality: "one",
|
|
833
|
-
effects: [
|
|
834
|
-
{
|
|
835
|
-
kind: "schedules",
|
|
836
|
-
per: "clause",
|
|
837
|
-
signature: { fixed: "due" },
|
|
838
|
-
},
|
|
839
|
-
],
|
|
840
|
-
scope: "action",
|
|
841
|
-
spelling: "due",
|
|
842
|
-
target: "due",
|
|
843
|
-
},
|
|
844
|
-
{
|
|
845
|
-
cardinality: "one",
|
|
846
|
-
scope: "action",
|
|
847
|
-
spelling: "earnable",
|
|
848
|
-
target: "earnable",
|
|
849
|
-
},
|
|
850
|
-
{
|
|
851
|
-
cardinality: "one",
|
|
852
|
-
scope: "action",
|
|
853
|
-
spelling: "event name",
|
|
854
|
-
target: "eventName",
|
|
855
|
-
},
|
|
856
|
-
{
|
|
857
|
-
cardinality: "many",
|
|
858
|
-
scope: "action",
|
|
859
|
-
spelling: "examples",
|
|
860
|
-
target: "examples",
|
|
861
|
-
},
|
|
862
|
-
{
|
|
863
|
-
cardinality: "one",
|
|
864
|
-
scope: "action",
|
|
865
|
-
spelling: "input",
|
|
866
|
-
target: "input",
|
|
867
|
-
},
|
|
868
|
-
{
|
|
869
|
-
cardinality: "many",
|
|
870
|
-
effects: [
|
|
871
|
-
{
|
|
872
|
-
kind: "moves",
|
|
873
|
-
per: "element",
|
|
874
|
-
signature: { movementClass: true },
|
|
875
|
-
},
|
|
876
|
-
{
|
|
877
|
-
kind: "holds",
|
|
878
|
-
per: "element",
|
|
879
|
-
signature: { fixed: "reserve" },
|
|
880
|
-
},
|
|
881
|
-
],
|
|
882
|
-
linearSink: true,
|
|
883
|
-
scope: "action",
|
|
884
|
-
spelling: "moves",
|
|
885
|
-
target: "moves",
|
|
886
|
-
},
|
|
887
|
-
{
|
|
888
|
-
cardinality: "one",
|
|
889
|
-
effects: [
|
|
890
|
-
{
|
|
891
|
-
kind: "moves",
|
|
892
|
-
per: "clause",
|
|
893
|
-
signature: { fixed: "payout.external" },
|
|
894
|
-
},
|
|
895
|
-
],
|
|
896
|
-
linearSink: true,
|
|
897
|
-
scope: "action",
|
|
898
|
-
spelling: "payout",
|
|
899
|
-
target: "payout",
|
|
900
|
-
},
|
|
901
|
-
{
|
|
902
|
-
cardinality: "one",
|
|
903
|
-
effects: [
|
|
904
|
-
{
|
|
905
|
-
kind: "decides",
|
|
906
|
-
per: "clause",
|
|
907
|
-
signature: { fixed: "tenant_port" },
|
|
908
|
-
},
|
|
909
|
-
],
|
|
910
|
-
scope: "action",
|
|
911
|
-
spelling: "port",
|
|
912
|
-
target: "port",
|
|
913
|
-
},
|
|
914
|
-
{
|
|
915
|
-
cardinality: "one",
|
|
916
|
-
scope: "action",
|
|
917
|
-
spelling: "principal",
|
|
918
|
-
target: "principal",
|
|
919
|
-
},
|
|
920
|
-
{
|
|
921
|
-
cardinality: "one",
|
|
922
|
-
scope: "action",
|
|
923
|
-
spelling: "public action",
|
|
924
|
-
target: "publicAction",
|
|
925
|
-
},
|
|
926
|
-
{
|
|
927
|
-
cardinality: "many",
|
|
928
|
-
effects: [
|
|
929
|
-
{
|
|
930
|
-
kind: "reads",
|
|
931
|
-
per: "element",
|
|
932
|
-
signature: { fixed: "reconcile" },
|
|
933
|
-
},
|
|
934
|
-
],
|
|
935
|
-
scope: "action",
|
|
936
|
-
spelling: "reconcile",
|
|
937
|
-
target: "reconcile",
|
|
938
|
-
},
|
|
939
|
-
{
|
|
940
|
-
cardinality: "one",
|
|
941
|
-
linearOutputs: ["amountRef"],
|
|
942
|
-
scope: "action",
|
|
943
|
-
spelling: "computes remainder",
|
|
944
|
-
target: "remainder",
|
|
945
|
-
},
|
|
946
|
-
{
|
|
947
|
-
cardinality: "many",
|
|
948
|
-
effects: [
|
|
949
|
-
{
|
|
950
|
-
kind: "reads",
|
|
951
|
-
per: "clause",
|
|
952
|
-
signature: { fixed: "requires_aggregate" },
|
|
953
|
-
},
|
|
954
|
-
],
|
|
955
|
-
scope: "action",
|
|
956
|
-
spelling: "requires aggregate",
|
|
957
|
-
target: "requiresAggregate",
|
|
958
|
-
},
|
|
959
|
-
{
|
|
960
|
-
cardinality: "many",
|
|
961
|
-
effects: [
|
|
962
|
-
{
|
|
963
|
-
kind: "reads",
|
|
964
|
-
per: "clause",
|
|
965
|
-
signature: { fixed: "requires_checks" },
|
|
966
|
-
},
|
|
967
|
-
],
|
|
968
|
-
scope: "action",
|
|
969
|
-
spelling: "requires checks",
|
|
970
|
-
target: "requiresChecks",
|
|
971
|
-
},
|
|
972
|
-
{
|
|
973
|
-
cardinality: "one",
|
|
974
|
-
scope: "action",
|
|
975
|
-
spelling: "requires drained",
|
|
976
|
-
target: "requiresDrainedAccount",
|
|
977
|
-
},
|
|
978
|
-
{
|
|
979
|
-
cardinality: "many",
|
|
980
|
-
scope: "action",
|
|
981
|
-
spelling: "requires exposure",
|
|
982
|
-
target: "requiresExposure",
|
|
983
|
-
},
|
|
984
|
-
{
|
|
985
|
-
cardinality: "many",
|
|
986
|
-
effects: [
|
|
987
|
-
{
|
|
988
|
-
kind: "reads",
|
|
989
|
-
per: "clause",
|
|
990
|
-
signature: { fixed: "requires_refs" },
|
|
991
|
-
},
|
|
992
|
-
],
|
|
993
|
-
scope: "action",
|
|
994
|
-
spelling: "requires refs",
|
|
995
|
-
target: "requiresRefs",
|
|
996
|
-
},
|
|
997
|
-
{
|
|
998
|
-
cardinality: "one",
|
|
999
|
-
scope: "action",
|
|
1000
|
-
spelling: "sandbox failure point",
|
|
1001
|
-
target: "sandboxFailurePoint",
|
|
1002
|
-
},
|
|
1003
|
-
{
|
|
1004
|
-
cardinality: "one",
|
|
1005
|
-
scope: "action",
|
|
1006
|
-
spelling: "sets at",
|
|
1007
|
-
target: "setsAt",
|
|
1008
|
-
},
|
|
1009
|
-
{
|
|
1010
|
-
cardinality: "one",
|
|
1011
|
-
linearOutputs: ["amountRef"],
|
|
1012
|
-
scope: "action",
|
|
1013
|
-
spelling: "computes signed_sum",
|
|
1014
|
-
target: "signedSum",
|
|
1015
|
-
},
|
|
1016
|
-
{
|
|
1017
|
-
cardinality: "many",
|
|
1018
|
-
linearSink: true,
|
|
1019
|
-
scope: "action",
|
|
1020
|
-
spelling: "steps",
|
|
1021
|
-
target: "steps",
|
|
1022
|
-
},
|
|
1023
|
-
{
|
|
1024
|
-
cardinality: "one",
|
|
1025
|
-
scope: "action",
|
|
1026
|
-
spelling: "summary",
|
|
1027
|
-
target: "summary",
|
|
1028
|
-
},
|
|
1029
|
-
{
|
|
1030
|
-
cardinality: "many",
|
|
1031
|
-
scope: "action",
|
|
1032
|
-
spelling: "updates",
|
|
1033
|
-
target: "updates",
|
|
1034
|
-
},
|
|
1035
|
-
{
|
|
1036
|
-
cardinality: "many",
|
|
1037
|
-
effects: [
|
|
1038
|
-
{
|
|
1039
|
-
kind: "notifies",
|
|
1040
|
-
per: "element",
|
|
1041
|
-
signature: { fromField: "channel" },
|
|
1042
|
-
},
|
|
1043
|
-
],
|
|
1044
|
-
scope: "action",
|
|
1045
|
-
spelling: "notify",
|
|
1046
|
-
target: "effects.notifies",
|
|
1047
|
-
},
|
|
1048
|
-
{
|
|
1049
|
-
cardinality: "one",
|
|
1050
|
-
scope: "instrument",
|
|
1051
|
-
spelling: "agent description",
|
|
1052
|
-
target: "agentDescription",
|
|
1053
|
-
},
|
|
1054
|
-
{
|
|
1055
|
-
cardinality: "many",
|
|
1056
|
-
scope: "instrument",
|
|
1057
|
-
spelling: "aggregate invariants",
|
|
1058
|
-
target: "aggregateInvariants",
|
|
1059
|
-
},
|
|
1060
|
-
{
|
|
1061
|
-
cardinality: "one",
|
|
1062
|
-
scope: "instrument",
|
|
1063
|
-
spelling: "caller parked states",
|
|
1064
|
-
target: "callerParkedStates",
|
|
1065
|
-
},
|
|
1066
|
-
{
|
|
1067
|
-
cardinality: "one",
|
|
1068
|
-
scope: "instrument",
|
|
1069
|
-
spelling: "description",
|
|
1070
|
-
target: "description",
|
|
1071
|
-
},
|
|
1072
|
-
{
|
|
1073
|
-
cardinality: "many",
|
|
1074
|
-
scope: "instrument",
|
|
1075
|
-
spelling: "dials",
|
|
1076
|
-
target: "dials",
|
|
1077
|
-
},
|
|
1078
|
-
{
|
|
1079
|
-
cardinality: "one",
|
|
1080
|
-
scope: "instrument",
|
|
1081
|
-
spelling: "distinct parties",
|
|
1082
|
-
target: "distinctParties",
|
|
1083
|
-
},
|
|
1084
|
-
{
|
|
1085
|
-
cardinality: "many",
|
|
1086
|
-
scope: "instrument",
|
|
1087
|
-
spelling: "computes derived",
|
|
1088
|
-
target: "derivedAmounts",
|
|
1089
|
-
},
|
|
1090
|
-
{
|
|
1091
|
-
cardinality: "many",
|
|
1092
|
-
scope: "instrument",
|
|
1093
|
-
spelling: "computes fees",
|
|
1094
|
-
target: "feeRules",
|
|
1095
|
-
},
|
|
1096
|
-
{
|
|
1097
|
-
cardinality: "one",
|
|
1098
|
-
scope: "instrument",
|
|
1099
|
-
spelling: "id prefix",
|
|
1100
|
-
target: "idPrefix",
|
|
1101
|
-
},
|
|
1102
|
-
{
|
|
1103
|
-
cardinality: "many",
|
|
1104
|
-
scope: "instrument",
|
|
1105
|
-
spelling: "nav",
|
|
1106
|
-
target: "nav",
|
|
1107
|
-
},
|
|
1108
|
-
{
|
|
1109
|
-
cardinality: "many",
|
|
1110
|
-
scope: "instrument",
|
|
1111
|
-
spelling: "partitions",
|
|
1112
|
-
target: "partitions",
|
|
1113
|
-
},
|
|
1114
|
-
{
|
|
1115
|
-
cardinality: "one",
|
|
1116
|
-
scope: "instrument",
|
|
1117
|
-
spelling: "subject",
|
|
1118
|
-
target: "subject",
|
|
1119
|
-
},
|
|
1120
|
-
{
|
|
1121
|
-
cardinality: "one",
|
|
1122
|
-
scope: "instrument",
|
|
1123
|
-
spelling: "summary",
|
|
1124
|
-
target: "summary",
|
|
1125
|
-
},
|
|
1126
|
-
{
|
|
1127
|
-
cardinality: "one",
|
|
1128
|
-
scope: "instrument",
|
|
1129
|
-
spelling: "surface visibility",
|
|
1130
|
-
target: "surfaceVisibility",
|
|
1131
|
-
},
|
|
1132
|
-
{
|
|
1133
|
-
cardinality: "one",
|
|
1134
|
-
scope: "instrument",
|
|
1135
|
-
spelling: "template id",
|
|
1136
|
-
target: "templateId",
|
|
1137
|
-
},
|
|
1138
|
-
{
|
|
1139
|
-
cardinality: "one",
|
|
1140
|
-
scope: "instrument",
|
|
1141
|
-
spelling: "title",
|
|
1142
|
-
target: "title",
|
|
1143
|
-
},
|
|
1144
|
-
{
|
|
1145
|
-
cardinality: "one",
|
|
1146
|
-
scope: "instrument",
|
|
1147
|
-
spelling: "update",
|
|
1148
|
-
target: "update",
|
|
1149
|
-
},
|
|
1150
|
-
] as const satisfies readonly UdlClauseVocabularyEntry[];
|
|
1151
|
-
|
|
1152
|
-
const udlDocumentShapeSchema = z.strictObject({
|
|
1153
|
-
dials: z.array(udlCompositionDialSchema).min(1).optional(),
|
|
1154
|
-
instruments: z.array(udlInstrumentSchema).min(1),
|
|
1155
|
-
product: udlSnakeCaseSchema,
|
|
1156
|
-
subjects: z.array(udlSubjectSchema),
|
|
1157
|
-
title: nonEmptyTextSchema,
|
|
454
|
+
event: text,
|
|
455
|
+
actor: z.union([
|
|
456
|
+
z.literal("caller"),
|
|
457
|
+
z.literal("clock"),
|
|
458
|
+
z.strictObject({ party: name }),
|
|
459
|
+
z.strictObject({
|
|
460
|
+
parent: z.union([instrumentId, z.array(instrumentId).min(1).max(16)]),
|
|
461
|
+
}),
|
|
462
|
+
]),
|
|
463
|
+
subject: udlActionSubjectSchema.optional(),
|
|
464
|
+
input: z.array(udlFieldSchema).max(128),
|
|
465
|
+
requires: z.array(udlRequirementSchema).max(128),
|
|
466
|
+
due: clock.optional(),
|
|
467
|
+
deadline: clock.optional(),
|
|
468
|
+
set: z.record(name, value).optional(),
|
|
469
|
+
calculate: z.array(udlCalculationSchema).max(128).optional(),
|
|
470
|
+
moves: z.array(udlMoveSchema).max(256),
|
|
471
|
+
invoke: z
|
|
472
|
+
.array(
|
|
473
|
+
z.union([
|
|
474
|
+
z.strictObject({
|
|
475
|
+
instrument: instrumentId,
|
|
476
|
+
action: z.literal("create"),
|
|
477
|
+
input: z.record(name, value),
|
|
478
|
+
guard: comparisonRequirement.optional(),
|
|
479
|
+
range: z
|
|
480
|
+
.strictObject({
|
|
481
|
+
count: value,
|
|
482
|
+
maximum: integer.min(1).max(366),
|
|
483
|
+
bind: name,
|
|
484
|
+
})
|
|
485
|
+
.optional(),
|
|
486
|
+
}),
|
|
487
|
+
z.strictObject({
|
|
488
|
+
reference: path,
|
|
489
|
+
action: name,
|
|
490
|
+
input: z.record(name, value),
|
|
491
|
+
guard: comparisonRequirement.optional(),
|
|
492
|
+
}),
|
|
493
|
+
z.strictObject({
|
|
494
|
+
selection,
|
|
495
|
+
action: name,
|
|
496
|
+
input: z.record(name, value),
|
|
497
|
+
guard: comparisonRequirement.optional(),
|
|
498
|
+
}),
|
|
499
|
+
]),
|
|
500
|
+
)
|
|
501
|
+
.max(16)
|
|
502
|
+
.optional(),
|
|
503
|
+
});
|
|
504
|
+
export const udlLifecycleSchema = z.strictObject({
|
|
505
|
+
states: z.array(name).min(1).max(64),
|
|
506
|
+
labels: z.record(name, text).optional(),
|
|
507
|
+
initial: name,
|
|
508
|
+
transitions: z.record(
|
|
509
|
+
name,
|
|
510
|
+
z.strictObject({ from: z.array(name).min(1).max(64), to: name }),
|
|
511
|
+
),
|
|
512
|
+
});
|
|
513
|
+
export const udlInstrumentSchema = z.strictObject({
|
|
514
|
+
scope: z.literal("product").optional(),
|
|
515
|
+
reports: z.array(reportDefinitionSchema).max(16).optional(),
|
|
516
|
+
revisioned: z.literal(true).optional(),
|
|
517
|
+
family: udlFamilySchema.optional(),
|
|
518
|
+
id: instrumentId,
|
|
519
|
+
subject: objectKindId.optional(),
|
|
520
|
+
title: text,
|
|
521
|
+
summary: text,
|
|
522
|
+
fields: z.array(udlFieldSchema).max(256),
|
|
523
|
+
calculate: z.array(udlCalculationSchema).max(128),
|
|
524
|
+
lifecycle: udlLifecycleSchema,
|
|
525
|
+
actions: z.record(name, udlActionSchema),
|
|
526
|
+
actionOrder: z.array(name).min(1).max(128),
|
|
527
|
+
invariants: z.array(udlRequirementSchema).max(128).optional(),
|
|
528
|
+
examples: z
|
|
529
|
+
.array(z.strictObject({ name: text, input: z.json() }))
|
|
530
|
+
.max(16)
|
|
531
|
+
.optional(),
|
|
532
|
+
});
|
|
533
|
+
export const udlDocumentSchema = z.strictObject({
|
|
1158
534
|
udl: z.literal(UDL_FORMAT_VERSION),
|
|
1159
|
-
version:
|
|
535
|
+
version: integer.positive(),
|
|
536
|
+
product: name,
|
|
537
|
+
title: text,
|
|
538
|
+
currency: z.literal("SAR"),
|
|
539
|
+
parties: z.record(name, udlPartySchema),
|
|
540
|
+
objects: z.array(udlObjectKindSchema).max(256),
|
|
541
|
+
instruments: z.array(udlInstrumentSchema).max(256),
|
|
1160
542
|
});
|
|
1161
543
|
|
|
1162
|
-
type
|
|
1163
|
-
|
|
1164
|
-
|
|
544
|
+
export type UdlFamily = z.infer<typeof udlFamilySchema>;
|
|
545
|
+
export type UdlDocument = z.infer<typeof udlDocumentSchema>;
|
|
546
|
+
export type UdlInstrument = z.infer<typeof udlInstrumentSchema>;
|
|
547
|
+
export type UdlField = z.infer<typeof udlFieldSchema>;
|
|
548
|
+
export type UdlParty = z.infer<typeof udlPartySchema>;
|
|
549
|
+
export type UdlValue = z.infer<typeof udlValueSchema>;
|
|
550
|
+
export type UdlCalculation = z.infer<typeof udlCalculationSchema>;
|
|
551
|
+
export type UdlRequirement = z.infer<typeof udlRequirementSchema>;
|
|
552
|
+
export type UdlAction = z.infer<typeof udlActionSchema>;
|
|
553
|
+
export type UdlMove = z.infer<typeof udlMoveSchema>;
|
|
554
|
+
export type UdlLifecycle = z.infer<typeof udlLifecycleSchema>;
|
|
555
|
+
export type UdlKernelOperation = z.infer<typeof udlKernelOperationSchema>;
|
|
1165
556
|
|
|
1166
|
-
|
|
1167
|
-
schema: Readonly<Record<string, unknown>> | undefined,
|
|
1168
|
-
): boolean {
|
|
1169
|
-
return (
|
|
1170
|
-
typeof schema?.pattern === "string" && moneyPatterns.has(schema.pattern)
|
|
1171
|
-
);
|
|
1172
|
-
}
|
|
557
|
+
export type UdlSelection = z.infer<typeof selection>;
|
|
1173
558
|
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
const match = /^\^([a-z]{2,8})_\(sandbox\|live\)_\[a-z0-9\]\{8,64\}\$$/.exec(
|
|
1182
|
-
schema.pattern,
|
|
1183
|
-
);
|
|
1184
|
-
if (!match) return [];
|
|
1185
|
-
const prefix = match[1] as string;
|
|
1186
|
-
const probe = `${prefix}_sandbox_0123456789abcdef`;
|
|
1187
|
-
if (typeof schema.const === "string" && schema.const !== probe) return [];
|
|
1188
|
-
if (Array.isArray(schema.enum) && !schema.enum.includes(probe)) return [];
|
|
1189
|
-
if (typeof schema.minLength === "number" && probe.length < schema.minLength) {
|
|
1190
|
-
return [];
|
|
1191
|
-
}
|
|
1192
|
-
if (typeof schema.maxLength === "number" && probe.length > schema.maxLength) {
|
|
1193
|
-
return [];
|
|
1194
|
-
}
|
|
1195
|
-
return instruments.filter((instrument) => instrument.idPrefix === prefix);
|
|
1196
|
-
}
|
|
559
|
+
export type UdlObjectField = z.infer<typeof udlObjectFieldSchema>;
|
|
560
|
+
export type UdlObjectKind = z.infer<typeof udlObjectKindSchema>;
|
|
561
|
+
export type UdlActionSubject = z.infer<typeof udlActionSubjectSchema>;
|
|
562
|
+
export type UdlSubjectRequirement = z.infer<typeof udlSubjectRequirementSchema>;
|
|
563
|
+
export type UdlAdapterSubjectSnapshot = z.infer<
|
|
564
|
+
typeof adapterSubjectSnapshotSchema
|
|
565
|
+
>;
|
|
1197
566
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
...action.signedSum.sources.map((source) => source.subtotalRef),
|
|
1215
|
-
]
|
|
1216
|
-
: []),
|
|
1217
|
-
...(action.distribute ? [action.distribute.amountRef] : []),
|
|
1218
|
-
...(action.quote ? [action.quote.chargeRef, action.quote.netRef] : []),
|
|
1219
|
-
]),
|
|
1220
|
-
]);
|
|
567
|
+
/** Names and display text may differ; executable constraints must match. */
|
|
568
|
+
export function sameObjectField(
|
|
569
|
+
left: UdlObjectField,
|
|
570
|
+
right: UdlObjectField,
|
|
571
|
+
): boolean {
|
|
572
|
+
const signature = (field: UdlObjectField) =>
|
|
573
|
+
writeJson(
|
|
574
|
+
Object.fromEntries(
|
|
575
|
+
Object.entries(field).filter(
|
|
576
|
+
([key, value]) =>
|
|
577
|
+
!["name", "label", "description", "optional"].includes(key) &&
|
|
578
|
+
value !== undefined,
|
|
579
|
+
),
|
|
580
|
+
),
|
|
581
|
+
);
|
|
582
|
+
return signature(left) === signature(right);
|
|
1221
583
|
}
|
|
1222
|
-
|
|
1223
|
-
export const udlDocumentSchema = udlDocumentShapeSchema.superRefine(
|
|
1224
|
-
(document, context) => {
|
|
1225
|
-
document.instruments.forEach((instrument, instrumentIndex) => {
|
|
1226
|
-
instrument.derivedAmounts?.forEach((amount, amountIndex) => {
|
|
1227
|
-
const base = [
|
|
1228
|
-
"instruments",
|
|
1229
|
-
instrumentIndex,
|
|
1230
|
-
"derivedAmounts",
|
|
1231
|
-
amountIndex,
|
|
1232
|
-
] as const;
|
|
1233
|
-
if (!isMoneyField(instrument.fields[amount.field])) {
|
|
1234
|
-
context.addIssue({
|
|
1235
|
-
code: "custom",
|
|
1236
|
-
message: `derived amount target ${amount.field} must be a declared money field`,
|
|
1237
|
-
path: [...base, "field"],
|
|
1238
|
-
});
|
|
1239
|
-
}
|
|
1240
|
-
if (!isMoneyField(instrument.fields[amount.sourceField])) {
|
|
1241
|
-
context.addIssue({
|
|
1242
|
-
code: "custom",
|
|
1243
|
-
message: `derived amount source ${amount.sourceField} must be a declared money field`,
|
|
1244
|
-
path: [...base, "sourceField"],
|
|
1245
|
-
});
|
|
1246
|
-
}
|
|
1247
|
-
if (amount.field === amount.sourceField) {
|
|
1248
|
-
context.addIssue({
|
|
1249
|
-
code: "custom",
|
|
1250
|
-
message: "a derived amount cannot derive from itself",
|
|
1251
|
-
path: [...base, "sourceField"],
|
|
1252
|
-
});
|
|
1253
|
-
}
|
|
1254
|
-
});
|
|
1255
|
-
|
|
1256
|
-
Object.entries(instrument.actions).forEach(([actionName, action]) => {
|
|
1257
|
-
const distribute = action.distribute;
|
|
1258
|
-
if (!distribute) return;
|
|
1259
|
-
const base = [
|
|
1260
|
-
"instruments",
|
|
1261
|
-
instrumentIndex,
|
|
1262
|
-
"actions",
|
|
1263
|
-
actionName,
|
|
1264
|
-
"distribute",
|
|
1265
|
-
] as const;
|
|
1266
|
-
const refSchema = instrument.fields[distribute.refField];
|
|
1267
|
-
const parents = refSchema
|
|
1268
|
-
? referenceTargets(refSchema, document.instruments)
|
|
1269
|
-
: [];
|
|
1270
|
-
if (parents.length !== 1) {
|
|
1271
|
-
context.addIssue({
|
|
1272
|
-
code: "custom",
|
|
1273
|
-
message: `distribute refField ${distribute.refField} must identify exactly one parent instrument`,
|
|
1274
|
-
path: [...base, "refField"],
|
|
1275
|
-
});
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
if (!isMoneyField(instrument.fields[distribute.weightField])) {
|
|
1279
|
-
context.addIssue({
|
|
1280
|
-
code: "custom",
|
|
1281
|
-
message: `distribute weightField ${distribute.weightField} must be a declared money field`,
|
|
1282
|
-
path: [...base, "weightField"],
|
|
1283
|
-
});
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
distribute.statuses.forEach((status, statusIndex) => {
|
|
1287
|
-
if (instrument.lifecycle.states.includes(status)) return;
|
|
1288
|
-
context.addIssue({
|
|
1289
|
-
code: "custom",
|
|
1290
|
-
message: `distribute status ${status} is not declared by ${instrument.id}`,
|
|
1291
|
-
path: [...base, "statuses", statusIndex],
|
|
1292
|
-
});
|
|
1293
|
-
});
|
|
1294
|
-
|
|
1295
|
-
const parent = parents[0];
|
|
1296
|
-
if (!parent) return;
|
|
1297
|
-
const poolMatch = /^(fields|refs)\.([a-z][A-Za-z0-9]*)$/.exec(
|
|
1298
|
-
distribute.pool.path,
|
|
1299
|
-
);
|
|
1300
|
-
const root = poolMatch?.[1];
|
|
1301
|
-
const key = poolMatch?.[2];
|
|
1302
|
-
const poolDeclared =
|
|
1303
|
-
root === "fields"
|
|
1304
|
-
? isMoneyField(parent.fields[key ?? ""])
|
|
1305
|
-
: root === "refs"
|
|
1306
|
-
? declaredMoneyRefKeys(parent).has(key ?? "")
|
|
1307
|
-
: false;
|
|
1308
|
-
if (!poolDeclared) {
|
|
1309
|
-
context.addIssue({
|
|
1310
|
-
code: "custom",
|
|
1311
|
-
message: `distribute pool ${distribute.pool.path} must be a declared money field or ref of ${parent.id}`,
|
|
1312
|
-
path: [...base, "pool", "path"],
|
|
1313
|
-
});
|
|
1314
|
-
}
|
|
1315
|
-
});
|
|
1316
|
-
});
|
|
1317
|
-
},
|
|
1318
|
-
);
|
|
1319
|
-
|
|
1320
|
-
export type UdlAggregate = z.infer<typeof udlAggregateSchema>;
|
|
1321
|
-
export type UdlAggregateCondition = z.infer<typeof udlAggregateConditionSchema>;
|
|
1322
|
-
export type UdlBinding = z.infer<typeof udlBindingSchema>;
|
|
1323
|
-
export type UdlDeclaredValuePolicy = z.infer<
|
|
1324
|
-
typeof udlDeclaredValuePolicySchema
|
|
1325
|
-
>;
|
|
1326
|
-
export type UdlDecision = z.infer<typeof udlDecisionSchema>;
|
|
1327
|
-
export type UdlCompositionDial = z.infer<typeof udlCompositionDialSchema>;
|
|
1328
|
-
export type UdlDial = z.infer<typeof udlDialSchema>;
|
|
1329
|
-
export type UdlDocument = z.infer<typeof udlDocumentSchema>;
|
|
1330
|
-
export type UdlDue = z.infer<typeof udlDueSchema>;
|
|
1331
|
-
export type UdlEffects = z.infer<typeof udlEffectsSchema>;
|
|
1332
|
-
export type UdlExample = z.infer<typeof udlExampleSchema>;
|
|
1333
|
-
export type UdlGate = z.infer<typeof udlGateSchema>;
|
|
1334
|
-
export type UdlKernelOperation = z.infer<typeof udlKernelOperationSchema>;
|
|
1335
|
-
export type UdlLifecycle = z.infer<typeof udlLifecycleSchema>;
|
|
1336
|
-
export type UdlLifecycleTransition = z.infer<
|
|
1337
|
-
typeof udlLifecycleTransitionSchema
|
|
1338
|
-
>;
|
|
1339
|
-
export type UdlInstrument = z.infer<typeof udlInstrumentSchema>;
|
|
1340
|
-
export type UdlInstrumentSubject = z.infer<typeof udlInstrumentSubjectSchema>;
|
|
1341
|
-
export type UdlMove = z.infer<typeof udlMoveSchema>;
|
|
1342
|
-
export type UdlPayout = z.infer<typeof udlPayoutSchema>;
|
|
1343
|
-
export type UdlQuote = z.infer<typeof udlQuoteSchema>;
|
|
1344
|
-
export type UdlProviderFamilyId = z.infer<typeof udlProviderFamilyIdSchema>;
|
|
1345
|
-
export type UdlCheckRequirement = z.infer<typeof udlCheckRequirementSchema>;
|
|
1346
|
-
export type UdlReconcile = z.infer<typeof udlReconcileSchema>;
|
|
1347
|
-
export type UdlRemainder = z.infer<typeof udlRemainderSchema>;
|
|
1348
|
-
export type UdlStep = z.infer<typeof udlStepSchema>;
|
|
1349
|
-
export type UdlSubject = z.infer<typeof udlSubjectSchema>;
|
|
1350
|
-
export type UdlAction = z.infer<typeof udlActionSchema>;
|