@hyperscale0/udl 3.2.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/dist/diagnostics.d.ts +1 -1
  4. package/dist/diagnostics.d.ts.map +1 -1
  5. package/dist/diagnostics.js +11 -1
  6. package/dist/diagnostics.js.map +1 -1
  7. package/dist/evolution.d.ts.map +1 -1
  8. package/dist/evolution.js +5 -0
  9. package/dist/evolution.js.map +1 -1
  10. package/dist/index.d.ts +2 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +2 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/instrument-references.d.ts.map +1 -1
  15. package/dist/instrument-references.js +21 -1
  16. package/dist/instrument-references.js.map +1 -1
  17. package/dist/object-contract.d.ts +144 -0
  18. package/dist/object-contract.d.ts.map +1 -0
  19. package/dist/object-contract.js +279 -0
  20. package/dist/object-contract.js.map +1 -0
  21. package/dist/reporting.d.ts +0 -1
  22. package/dist/reporting.d.ts.map +1 -1
  23. package/dist/reporting.js +0 -1
  24. package/dist/reporting.js.map +1 -1
  25. package/dist/schema.d.ts +1815 -126
  26. package/dist/schema.d.ts.map +1 -1
  27. package/dist/schema.js +100 -33
  28. package/dist/schema.js.map +1 -1
  29. package/dist/validation.d.ts +5 -2
  30. package/dist/validation.d.ts.map +1 -1
  31. package/dist/validation.js +403 -146
  32. package/dist/validation.js.map +1 -1
  33. package/docs/README.md +66 -17
  34. package/package.json +4 -4
  35. package/spec/README.md +66 -17
  36. package/spec/{darb.udl.json → cars.udl.json} +7 -7
  37. package/spec/udl.schema.json +2876 -6516
  38. package/src/diagnostics.ts +27 -1
  39. package/src/evolution.ts +8 -0
  40. package/src/index.ts +3 -0
  41. package/src/instrument-references.ts +25 -1
  42. package/src/object-contract.ts +464 -0
  43. package/src/reporting.ts +0 -1
  44. package/src/schema.ts +155 -33
  45. package/src/validation.ts +635 -174
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,14 +124,88 @@ 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,
155
+ ]);
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 }),
106
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
+ });
107
209
 
108
210
  /** Values are constants or resolved typed paths, never executable strings. */
109
211
  export const udlValueSchema = z.union([
@@ -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,
@@ -225,15 +328,9 @@ export const udlRequirementSchema = z.discriminatedUnion("kind", [
225
328
  operator: z.enum(["==", "<=", ">=", "<", ">"]),
226
329
  value,
227
330
  }),
228
- z.strictObject({
229
- kind: z.literal("approval"),
230
- target: path.default("self"),
231
- party: name,
232
- action: name.optional(),
233
- decision: z.enum(["approved", "declined"]),
234
- }),
235
331
  z.strictObject({
236
332
  kind: z.literal("evidence"),
333
+ instruction: path.optional(),
237
334
  subject: path,
238
335
  family: name,
239
336
  check: name,
@@ -260,6 +357,7 @@ export const udlMoveSchema = z.discriminatedUnion("operation", [
260
357
  z.strictObject({
261
358
  key: name,
262
359
  operation: z.literal("internal_transfer.reserve"),
360
+ boundary: z.strictObject({ adapter: name }).optional(),
263
361
  amount: value,
264
362
  from: path,
265
363
  to: path,
@@ -294,7 +392,6 @@ export const udlActionSchema = z.strictObject({
294
392
  summary: text,
295
393
  publicAction: name.optional(),
296
394
  expansionLimit: z.literal(8192).optional(),
297
- humanApproval: z.literal("distinct_member").optional(),
298
395
  reminder: z
299
396
  .strictObject({
300
397
  installment: path,
@@ -319,6 +416,7 @@ export const udlActionSchema = z.strictObject({
319
416
  parent: z.union([instrumentId, z.array(instrumentId).min(1).max(16)]),
320
417
  }),
321
418
  ]),
419
+ subject: udlActionSubjectSchema.optional(),
322
420
  input: z.array(udlFieldSchema).max(128),
323
421
  requires: z.array(udlRequirementSchema).max(128),
324
422
  due: clock.optional(),
@@ -358,16 +456,6 @@ export const udlActionSchema = z.strictObject({
358
456
  )
359
457
  .max(16)
360
458
  .optional(),
361
- approval: z
362
- .strictObject({
363
- target: path,
364
- action: name,
365
- party: name,
366
- expires: path,
367
- input: z.record(name, value),
368
- decision: z.enum(["approved", "declined"]),
369
- })
370
- .optional(),
371
459
  });
372
460
  export const udlLifecycleSchema = z.strictObject({
373
461
  states: z.array(name).min(1).max(64),
@@ -380,7 +468,9 @@ export const udlLifecycleSchema = z.strictObject({
380
468
  export const udlInstrumentSchema = z.strictObject({
381
469
  reports: z.array(reportDefinitionSchema).max(16).optional(),
382
470
  revisioned: z.literal(true).optional(),
471
+ family: udlFamilySchema.optional(),
383
472
  id: instrumentId,
473
+ subject: objectKindId.optional(),
384
474
  title: text,
385
475
  summary: text,
386
476
  fields: z.array(udlFieldSchema).max(256),
@@ -401,9 +491,11 @@ export const udlDocumentSchema = z.strictObject({
401
491
  title: text,
402
492
  currency: z.literal("SAR"),
403
493
  parties: z.record(name, udlPartySchema),
404
- instruments: z.array(udlInstrumentSchema).min(1).max(256),
494
+ objects: z.array(udlObjectKindSchema).max(256),
495
+ instruments: z.array(udlInstrumentSchema).max(256),
405
496
  });
406
497
 
498
+ export type UdlFamily = z.infer<typeof udlFamilySchema>;
407
499
  export type UdlDocument = z.infer<typeof udlDocumentSchema>;
408
500
  export type UdlInstrument = z.infer<typeof udlInstrumentSchema>;
409
501
  export type UdlField = z.infer<typeof udlFieldSchema>;
@@ -417,3 +509,33 @@ export type UdlLifecycle = z.infer<typeof udlLifecycleSchema>;
417
509
  export type UdlKernelOperation = z.infer<typeof udlKernelOperationSchema>;
418
510
 
419
511
  export type UdlSelection = z.infer<typeof selection>;
512
+
513
+ export type UdlObjectField = z.infer<typeof udlObjectFieldSchema>;
514
+ export type UdlObjectKind = z.infer<typeof udlObjectKindSchema>;
515
+ export type UdlActionSubject = z.infer<typeof udlActionSubjectSchema>;
516
+ export type UdlSubjectRequirement = z.infer<typeof udlSubjectRequirementSchema>;
517
+ export type UdlAdapterSubjectSnapshot = z.infer<
518
+ typeof adapterSubjectSnapshotSchema
519
+ >;
520
+
521
+ /** Names and display text may differ; executable constraints must match. */
522
+ export function sameObjectField(
523
+ left: UdlObjectField,
524
+ right: UdlObjectField,
525
+ ): boolean {
526
+ const signature = (field: UdlObjectField) =>
527
+ JSON.stringify(
528
+ Object.fromEntries(
529
+ Object.entries(field)
530
+ .filter(
531
+ ([key, value]) =>
532
+ !["name", "description", "optional"].includes(key) &&
533
+ value !== undefined,
534
+ )
535
+ .sort(([left], [right]) =>
536
+ left < right ? -1 : left > right ? 1 : 0,
537
+ ),
538
+ ),
539
+ );
540
+ return signature(left) === signature(right);
541
+ }