@hyperscale0/udl 3.2.0 → 4.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/src/schema.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as z from "zod";
2
2
  import { reportDefinitionSchema } from "./reporting.js";
3
3
 
4
- export const UDL_FORMAT_VERSION = 3 as const;
4
+ export const UDL_FORMAT_VERSION = 4 as const;
5
5
  /** Counts the root and every nested invocation, including selected and ranged children. */
6
6
  export const MAX_ACTION_EXPANSION = 4096;
7
7
  const name = z
@@ -17,6 +17,13 @@ const path = z
17
17
  .regex(/^[a-z][a-zA-Z0-9_]*(?:\.[a-z][a-zA-Z0-9_]*)*$/)
18
18
  .max(240);
19
19
  const instrumentId = name.meta({ "x-udl-reference": "instrument" });
20
+ const objectKindId = name.meta({ "x-udl-reference": "object" });
21
+
22
+ export const udlPartyNameSchema = name;
23
+
24
+ export const udlObjectIdSchema = z.string().min(1).max(160);
25
+ export const udlExternalIdSchema = z.string().min(1).max(2048);
26
+ export const udlObjectRevisionSchema = integer.positive();
20
27
 
21
28
  /** Currency belongs to the document. Accounts and amounts cannot override it. */
22
29
  export const udlPartySchema = z.strictObject({
@@ -24,11 +31,37 @@ export const udlPartySchema = z.strictObject({
24
31
  role: name.optional(),
25
32
  });
26
33
 
34
+ export const udlFamilySchema = z.strictObject({
35
+ module: name,
36
+ exportPath: path,
37
+ revision: integer.positive(),
38
+ });
39
+
27
40
  const fieldBase = {
28
41
  name,
29
42
  optional: z.literal(true).optional(),
30
43
  description: text.optional(),
44
+ sensitive: z.literal(true).optional(),
31
45
  };
46
+
47
+ const referenceField = z.strictObject({
48
+ ...fieldBase,
49
+ type: z.literal("ref"),
50
+ targetKind: z.enum(["instrument", "object"]),
51
+ targetFamily: udlFamilySchema.optional(),
52
+ target: z.union([name, z.array(name).min(1).max(16)]),
53
+ });
54
+
55
+ const listField = z.strictObject({
56
+ ...fieldBase,
57
+ type: z.literal("list"),
58
+ item: z.enum(["money", "date", "text", "integer", "ref"]),
59
+ targetKind: z.enum(["instrument", "object"]).optional(),
60
+ targetFamily: udlFamilySchema.optional(),
61
+ target: name.optional(),
62
+ maxItems: integer.min(1).max(366),
63
+ });
64
+
32
65
  export const udlFieldSchema = z.discriminatedUnion("type", [
33
66
  z.strictObject({
34
67
  ...fieldBase,
@@ -44,13 +77,8 @@ export const udlFieldSchema = z.discriminatedUnion("type", [
44
77
  key: name.optional(),
45
78
  book: z.enum(["cash", "claim"]).default("cash"),
46
79
  contra: z.literal(true).optional(),
47
- external: z.literal(true).optional(),
48
- }),
49
- z.strictObject({
50
- ...fieldBase,
51
- type: z.literal("ref"),
52
- target: z.union([instrumentId, z.array(instrumentId).min(1).max(16)]),
53
80
  }),
81
+ referenceField,
54
82
  z.strictObject({
55
83
  ...fieldBase,
56
84
  type: z.literal("date"),
@@ -96,15 +124,89 @@ export const udlFieldSchema = z.discriminatedUnion("type", [
96
124
  values: z.array(name).min(1).max(64),
97
125
  value: name.optional(),
98
126
  }),
99
- z.strictObject({
100
- ...fieldBase,
101
- type: z.literal("list"),
102
- item: z.enum(["money", "date", "text", "integer", "ref"]),
103
- target: instrumentId.optional(),
104
- maxItems: integer.min(1).max(366),
105
- }),
127
+ listField,
128
+ ]);
129
+
130
+ const [
131
+ moneyField,
132
+ ,
133
+ refField,
134
+ dateField,
135
+ durationField,
136
+ textField,
137
+ integerField,
138
+ percentField,
139
+ booleanField,
140
+ enumField,
141
+ boundedListField,
142
+ ] = udlFieldSchema.options;
143
+
144
+ export const udlObjectFieldSchema = z.discriminatedUnion("type", [
145
+ moneyField,
146
+ refField,
147
+ dateField,
148
+ durationField,
149
+ textField,
150
+ integerField,
151
+ percentField,
152
+ booleanField,
153
+ enumField,
154
+ boundedListField,
106
155
  ]);
107
156
 
157
+ export const udlSubjectRequirementSchema = z.strictObject({
158
+ field: udlObjectFieldSchema,
159
+ // Present only for an authored rename.
160
+ objectField: name.optional(),
161
+ });
162
+
163
+ export const adapterSubjectSnapshotSchema = z.strictObject({
164
+ provider: text,
165
+ capability: text,
166
+ operation: text,
167
+ declarationDigest: z.string().regex(/^[a-f0-9]{64}$/),
168
+ requirements: z.array(udlObjectFieldSchema).max(128),
169
+ });
170
+
171
+ export const udlActionSubjectSchema = z.strictObject({
172
+ requirements: z.array(udlSubjectRequirementSchema).max(128),
173
+ adapters: z
174
+ .array(
175
+ z.strictObject({
176
+ binding: name,
177
+ // null means unavailable, never "no requirements".
178
+ snapshot: adapterSubjectSnapshotSchema.nullable(),
179
+ renames: z.record(name, name).optional(),
180
+ }),
181
+ )
182
+ .max(16),
183
+ });
184
+
185
+ export const subjectPartyRoles = ["owner", "actor", "operator"] as const;
186
+ export const attachmentPartyBindingSchema = z.union([
187
+ z.strictObject({ role: z.enum(subjectPartyRoles) }),
188
+ z.strictObject({ party: name }),
189
+ ]);
190
+ export type AttachmentPartyBinding = z.infer<
191
+ typeof attachmentPartyBindingSchema
192
+ >;
193
+ export const udlObjectAttachmentSchema = z.strictObject({
194
+ name,
195
+ instrument: instrumentId,
196
+ parties: z.record(name, attachmentPartyBindingSchema),
197
+ });
198
+ export type SubjectPartyRole = (typeof subjectPartyRoles)[number];
199
+ export type UdlObjectAttachment = z.infer<typeof udlObjectAttachmentSchema>;
200
+
201
+ export const udlObjectKindSchema = z.strictObject({
202
+ id: objectKindId,
203
+ title: text,
204
+ authoredFields: z.array(name).max(256),
205
+ attachments: z.array(udlObjectAttachmentSchema).max(256),
206
+ fields: z.array(udlObjectFieldSchema).max(256),
207
+ columns: z.array(name).max(8),
208
+ });
209
+
108
210
  /** Values are constants or resolved typed paths, never executable strings. */
109
211
  export const udlValueSchema = z.union([
110
212
  z.strictObject({ literal: scalar }),
@@ -114,6 +216,7 @@ const value = udlValueSchema;
114
216
  const values = z.array(value).min(1).max(256);
115
217
 
116
218
  const selection = z.strictObject({
219
+ family: udlFamilySchema.optional(),
117
220
  instrument: z.union([instrumentId, z.array(instrumentId).min(1).max(16)]),
118
221
  reference: name,
119
222
  anchor: path,
@@ -231,9 +334,12 @@ export const udlRequirementSchema = z.discriminatedUnion("kind", [
231
334
  party: name,
232
335
  action: name.optional(),
233
336
  decision: z.enum(["approved", "declined"]),
337
+ differentFromInitiator: z.literal(true).optional(),
338
+ protectedRequest: path.default("self"),
234
339
  }),
235
340
  z.strictObject({
236
341
  kind: z.literal("evidence"),
342
+ instruction: path.optional(),
237
343
  subject: path,
238
344
  family: name,
239
345
  check: name,
@@ -260,6 +366,7 @@ export const udlMoveSchema = z.discriminatedUnion("operation", [
260
366
  z.strictObject({
261
367
  key: name,
262
368
  operation: z.literal("internal_transfer.reserve"),
369
+ boundary: z.strictObject({ adapter: name }).optional(),
263
370
  amount: value,
264
371
  from: path,
265
372
  to: path,
@@ -319,6 +426,7 @@ export const udlActionSchema = z.strictObject({
319
426
  parent: z.union([instrumentId, z.array(instrumentId).min(1).max(16)]),
320
427
  }),
321
428
  ]),
429
+ subject: udlActionSubjectSchema.optional(),
322
430
  input: z.array(udlFieldSchema).max(128),
323
431
  requires: z.array(udlRequirementSchema).max(128),
324
432
  due: clock.optional(),
@@ -360,6 +468,7 @@ export const udlActionSchema = z.strictObject({
360
468
  .optional(),
361
469
  approval: z
362
470
  .strictObject({
471
+ protectedRequest: path.default("self"),
363
472
  target: path,
364
473
  action: name,
365
474
  party: name,
@@ -380,7 +489,9 @@ export const udlLifecycleSchema = z.strictObject({
380
489
  export const udlInstrumentSchema = z.strictObject({
381
490
  reports: z.array(reportDefinitionSchema).max(16).optional(),
382
491
  revisioned: z.literal(true).optional(),
492
+ family: udlFamilySchema.optional(),
383
493
  id: instrumentId,
494
+ subject: objectKindId.optional(),
384
495
  title: text,
385
496
  summary: text,
386
497
  fields: z.array(udlFieldSchema).max(256),
@@ -401,9 +512,11 @@ export const udlDocumentSchema = z.strictObject({
401
512
  title: text,
402
513
  currency: z.literal("SAR"),
403
514
  parties: z.record(name, udlPartySchema),
404
- instruments: z.array(udlInstrumentSchema).min(1).max(256),
515
+ objects: z.array(udlObjectKindSchema).max(256),
516
+ instruments: z.array(udlInstrumentSchema).max(256),
405
517
  });
406
518
 
519
+ export type UdlFamily = z.infer<typeof udlFamilySchema>;
407
520
  export type UdlDocument = z.infer<typeof udlDocumentSchema>;
408
521
  export type UdlInstrument = z.infer<typeof udlInstrumentSchema>;
409
522
  export type UdlField = z.infer<typeof udlFieldSchema>;
@@ -417,3 +530,33 @@ export type UdlLifecycle = z.infer<typeof udlLifecycleSchema>;
417
530
  export type UdlKernelOperation = z.infer<typeof udlKernelOperationSchema>;
418
531
 
419
532
  export type UdlSelection = z.infer<typeof selection>;
533
+
534
+ export type UdlObjectField = z.infer<typeof udlObjectFieldSchema>;
535
+ export type UdlObjectKind = z.infer<typeof udlObjectKindSchema>;
536
+ export type UdlActionSubject = z.infer<typeof udlActionSubjectSchema>;
537
+ export type UdlSubjectRequirement = z.infer<typeof udlSubjectRequirementSchema>;
538
+ export type UdlAdapterSubjectSnapshot = z.infer<
539
+ typeof adapterSubjectSnapshotSchema
540
+ >;
541
+
542
+ /** Names and display text may differ; executable constraints must match. */
543
+ export function sameObjectField(
544
+ left: UdlObjectField,
545
+ right: UdlObjectField,
546
+ ): boolean {
547
+ const signature = (field: UdlObjectField) =>
548
+ JSON.stringify(
549
+ Object.fromEntries(
550
+ Object.entries(field)
551
+ .filter(
552
+ ([key, value]) =>
553
+ !["name", "description", "optional"].includes(key) &&
554
+ value !== undefined,
555
+ )
556
+ .sort(([left], [right]) =>
557
+ left < right ? -1 : left > right ? 1 : 0,
558
+ ),
559
+ ),
560
+ );
561
+ return signature(left) === signature(right);
562
+ }