@altopelago/aeos-core 0.11.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +9 -0
  2. package/dist/bin/aeos-validator.d.ts +1 -1
  3. package/dist/bin/aeos-validator.js +9 -5
  4. package/dist/bin/aeos-validator.js.map +1 -1
  5. package/dist/index.d.ts +6 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +2 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/rules/numericForm.d.ts.map +1 -1
  10. package/dist/rules/numericForm.js +1 -9
  11. package/dist/rules/numericForm.js.map +1 -1
  12. package/dist/rules/stringForm.js +1 -1
  13. package/dist/rules/stringForm.js.map +1 -1
  14. package/dist/rules/typeCheck.d.ts +1 -0
  15. package/dist/rules/typeCheck.d.ts.map +1 -1
  16. package/dist/rules/typeCheck.js +6 -2
  17. package/dist/rules/typeCheck.js.map +1 -1
  18. package/dist/schema-codec.d.ts.map +1 -1
  19. package/dist/schema-codec.js +142 -8
  20. package/dist/schema-codec.js.map +1 -1
  21. package/dist/schema-tools.d.ts +90 -0
  22. package/dist/schema-tools.d.ts.map +1 -0
  23. package/dist/schema-tools.js +465 -0
  24. package/dist/schema-tools.js.map +1 -0
  25. package/dist/telex.d.ts +14 -0
  26. package/dist/telex.d.ts.map +1 -0
  27. package/dist/telex.js +33 -0
  28. package/dist/telex.js.map +1 -0
  29. package/dist/types/aes.d.ts +9 -3
  30. package/dist/types/aes.d.ts.map +1 -1
  31. package/dist/types/schema.d.ts +22 -1
  32. package/dist/types/schema.d.ts.map +1 -1
  33. package/dist/types/schema.js.map +1 -1
  34. package/dist/util/datatypes.d.ts +13 -0
  35. package/dist/util/datatypes.d.ts.map +1 -0
  36. package/dist/util/datatypes.js +50 -0
  37. package/dist/util/datatypes.js.map +1 -0
  38. package/dist/validate.d.ts.map +1 -1
  39. package/dist/validate.js +207 -42
  40. package/dist/validate.js.map +1 -1
  41. package/package.json +6 -6
@@ -4,11 +4,17 @@
4
4
  * Re-exports AES types from @altopelago/aeon-aes.
5
5
  * These are type-only imports to maintain zero runtime dependencies.
6
6
  */
7
- import type { AssignmentEvent } from '@altopelago/aeon-aes';
7
+ import type { AssignmentEvent, TelexRecord } from '@altopelago/aeon-aes';
8
8
  import type { Span as AeonSpan } from '@altopelago/aeon-lexer';
9
- export type { AssignmentEvent, AeonSpan };
9
+ export type { AssignmentEvent, AeonSpan, TelexRecord };
10
+ /** A decoded portable AES body record; header-plane records are filtered first. */
11
+ export type PortableAesBodyEvent = TelexRecord & {
12
+ readonly path: string;
13
+ readonly kind: string;
14
+ readonly header?: never;
15
+ };
10
16
  /**
11
17
  * Readonly AES array type for validation input
12
18
  */
13
- export type AES = readonly AssignmentEvent[];
19
+ export type AES = readonly (AssignmentEvent | PortableAesBodyEvent)[];
14
20
  //# sourceMappingURL=aes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aes.d.ts","sourceRoot":"","sources":["../../src/types/aes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAG/D,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,GAAG,GAAG,SAAS,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"aes.d.ts","sourceRoot":"","sources":["../../src/types/aes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAG/D,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AAEvD,mFAAmF;AACnF,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,GAAG,GAAG,SAAS,CAAC,eAAe,GAAG,oBAAoB,CAAC,EAAE,CAAC"}
@@ -63,7 +63,7 @@ export interface ConstraintsV1 {
63
63
  readonly max_length?: number;
64
64
  /** AEOS portable pattern for string matching */
65
65
  readonly pattern?: string;
66
- /** Datatype label (presence check only, no capacity) */
66
+ /** Exact datatype-label constraint; deeper datatype semantics belong in datatype_rules. */
67
67
  readonly datatype?: string;
68
68
  /** Attribute entry constraints keyed by attribute name */
69
69
  readonly attributes?: Readonly<Record<string, AttributeConstraintsV1>>;
@@ -74,6 +74,14 @@ export interface ConstraintsV1 {
74
74
  * Schema rule for an exact SANSA path or non-exact SANSA selector
75
75
  */
76
76
  export interface SchemaRule {
77
+ /** Stable identity for this declaration across schema versions. */
78
+ readonly declaration_id?: string;
79
+ /** Optional semantic lineage shared by related declarations. */
80
+ readonly lineage_id?: string;
81
+ /** Optional short consumer-facing name; non-operational schema metadata. */
82
+ readonly label?: string;
83
+ /** Optional consumer-facing purpose and usage description; non-operational schema metadata. */
84
+ readonly description?: string;
77
85
  /** Exact SANSA path this rule applies to */
78
86
  readonly path?: string;
79
87
  /** SANSA selector this rule applies to */
@@ -81,12 +89,25 @@ export interface SchemaRule {
81
89
  /** Constraints to apply */
82
90
  readonly constraints: ConstraintsV1;
83
91
  }
92
+ export type SchemaEvolutionKindV1 = 'add' | 'remove' | 'rename' | 'move' | 'constraint-change' | 'datatype-change' | 'split' | 'merge' | 'derive' | 'replace';
93
+ /** Authored temporal intent relating declarations across schema versions. */
94
+ export interface SchemaEvolutionV1 {
95
+ readonly change_id: string;
96
+ readonly kind: SchemaEvolutionKindV1;
97
+ readonly from_declarations: readonly string[];
98
+ readonly to_declarations: readonly string[];
99
+ readonly from_contract?: string;
100
+ readonly transform?: string;
101
+ readonly note?: string;
102
+ }
84
103
  /**
85
104
  * AEOS Schema v1
86
105
  */
87
106
  export interface SchemaV1 {
88
107
  /** Array of rules */
89
108
  readonly rules: readonly SchemaRule[];
109
+ /** Authored changes from an earlier schema into this schema. */
110
+ readonly evolution?: readonly SchemaEvolutionV1[];
90
111
  /** Open-world or closed-world validation policy */
91
112
  readonly world?: 'open' | 'closed';
92
113
  /** Optional schema-wide reference policy */
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/types/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/types/schema.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/types/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoJH;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAwB,IAAI,GAAG,CAAC;IAC9D,UAAU;IACV,MAAM;IACN,QAAQ;IACR,UAAU;IACV,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,aAAa;IACb,aAAa;IACb,WAAW;IACX,gBAAgB;IAChB,0BAA0B;IAC1B,wBAAwB;IACxB,SAAS;IACT,cAAc;IACd,cAAc;IACd,cAAc;IACd,MAAM;IACN,YAAY;IACZ,YAAY;IACZ,OAAO;IACP,yBAAyB;IACzB,WAAW;IACX,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,SAAS;IACT,UAAU;IACV,YAAY;IACZ,mBAAmB;CACtB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,WAAoC;IACzE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/types/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA0LH;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAwB,IAAI,GAAG,CAAC;IAC9D,UAAU;IACV,MAAM;IACN,QAAQ;IACR,UAAU;IACV,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,aAAa;IACb,aAAa;IACb,WAAW;IACX,gBAAgB;IAChB,0BAA0B;IAC1B,wBAAwB;IACxB,SAAS;IACT,cAAc;IACd,cAAc;IACd,cAAc;IACd,MAAM;IACN,YAAY;IACZ,YAAY;IACZ,OAAO;IACP,yBAAyB;IACzB,WAAW;IACX,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,SAAS;IACT,UAAU;IACV,YAAY;IACZ,mBAAmB;CACtB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,WAAoC;IACzE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Return the base name of a datatype without generic parameters or clarifiers.
3
+ */
4
+ export declare function datatypeBase(datatype: string): string;
5
+ /**
6
+ * Parse the JSON-compatible values from a datatype clarifier list.
7
+ */
8
+ export declare function parseClarifierValues(datatype: string): (string | number)[];
9
+ /**
10
+ * Resolve the radix declared by a built-in numeric datatype.
11
+ */
12
+ export declare function declaredRadixFromDatatype(datatype: string | undefined): number | null;
13
+ //# sourceMappingURL=datatypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datatypes.d.ts","sourceRoot":"","sources":["../../src/util/datatypes.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOrD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAW1E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAWrF"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Return the base name of a datatype without generic parameters or clarifiers.
3
+ */
4
+ export function datatypeBase(datatype) {
5
+ const genericIdx = datatype.indexOf('<');
6
+ const clarifierIdx = datatype.indexOf('[');
7
+ const endIdx = [genericIdx, clarifierIdx]
8
+ .filter((idx) => idx >= 0)
9
+ .reduce((min, idx) => Math.min(min, idx), datatype.length);
10
+ return datatype.slice(0, endIdx);
11
+ }
12
+ /**
13
+ * Parse the JSON-compatible values from a datatype clarifier list.
14
+ */
15
+ export function parseClarifierValues(datatype) {
16
+ const start = datatype.indexOf('[');
17
+ if (start < 0 || !datatype.endsWith(']'))
18
+ return [];
19
+ const payload = datatype.slice(start + 1, -1);
20
+ try {
21
+ const parsed = JSON.parse(`[${payload}]`);
22
+ if (!Array.isArray(parsed))
23
+ return [];
24
+ return parsed.filter((value) => typeof value === 'string' || typeof value === 'number');
25
+ }
26
+ catch {
27
+ return [];
28
+ }
29
+ }
30
+ /**
31
+ * Resolve the radix declared by a built-in numeric datatype.
32
+ */
33
+ export function declaredRadixFromDatatype(datatype) {
34
+ if (datatype === undefined)
35
+ return null;
36
+ const trimmed = datatype.trim();
37
+ if (trimmed.toLowerCase() === 'decimal')
38
+ return 10;
39
+ const alias = /^radix(2|6|8|12)$/i.exec(trimmed);
40
+ if (alias)
41
+ return Number(alias[1]);
42
+ if (datatypeBase(trimmed).toLowerCase() !== 'radix')
43
+ return null;
44
+ const values = parseClarifierValues(trimmed);
45
+ if (values.length !== 1 || typeof values[0] !== 'number')
46
+ return null;
47
+ const value = values[0];
48
+ return Number.isInteger(value) && value >= 2 && value <= 64 ? value : null;
49
+ }
50
+ //# sourceMappingURL=datatypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datatypes.js","sourceRoot":"","sources":["../../src/util/datatypes.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IACzC,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,CAAC,UAAU,EAAE,YAAY,CAAC;SACpC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;SACzB,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/D,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,GAAG,CAAY,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,CAAC;QACtC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAA4B,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;IACtH,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAA4B;IAClE,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,OAAO,CAAC,WAAW,EAAE,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnD,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,KAAK;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IACjE,MAAM,MAAM,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/E,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAc,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAW1D,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AA4EzE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,gCAAgC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;IAErE,+DAA+D;IAC/D,QAAQ,CAAC,cAAc,CAAC,EAAE,gBAAgB,CAAC;CAE9C;AAiJD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CACpB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,QAAQ,EAChB,OAAO,GAAE,eAAoB,GAC9B,cAAc,CAmXhB"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAwB,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAc,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAY1D,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAuFzE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,gCAAgC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;IAErE,+DAA+D;IAC/D,QAAQ,CAAC,cAAc,CAAC,EAAE,gBAAgB,CAAC;CAE9C;AAiJD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CACpB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,QAAQ,EAChB,OAAO,GAAE,eAAoB,GAC9B,cAAc,CAuYhB"}
package/dist/validate.js CHANGED
@@ -13,7 +13,9 @@ import { checkTypes } from './rules/typeCheck.js';
13
13
  import { checkReferenceForms } from './rules/referenceForm.js';
14
14
  import { checkNumericForm } from './rules/numericForm.js';
15
15
  import { checkStringForm, checkPatterns, matchesPortablePattern } from './rules/stringForm.js';
16
+ import { datatypeBase, declaredRadixFromDatatype, parseClarifierValues } from './util/datatypes.js';
16
17
  import { parseAddress, resolveAddress, } from '@altopelago/sansa';
18
+ import { formatDatatypeDescriptor, } from '@altopelago/aeon-aes';
17
19
  const TYPE_ALIASES = {
18
20
  NumberLiteral: ['NumberLiteral'],
19
21
  StringLiteral: ['StringLiteral'],
@@ -34,10 +36,11 @@ const TYPE_ALIASES = {
34
36
  DateLiteral: ['DateLiteral'],
35
37
  TimeLiteral: ['TimeLiteral'],
36
38
  DateTimeLiteral: ['DateTimeLiteral'],
37
- ZRUTDateTimeLiteral: ['ZRUTDateTimeLiteral'],
39
+ WTCDateTimeLiteral: ['WTCDateTimeLiteral'],
38
40
  CloneReference: ['CloneReference'],
39
41
  PointerReference: ['PointerReference'],
40
42
  NodeLiteral: ['NodeLiteral'],
43
+ NodeHead: ['NodeHead'],
41
44
  };
42
45
  function formatQuotedMemberSegment(key) {
43
46
  return `.[${JSON.stringify(String(key))}]`;
@@ -107,7 +110,7 @@ const STRING_LIKE_VALUE_TYPES = new Set([
107
110
  'DateLiteral',
108
111
  'TimeLiteral',
109
112
  'DateTimeLiteral',
110
- 'ZRUTDateTimeLiteral',
113
+ 'WTCDateTimeLiteral',
111
114
  ]);
112
115
  function stringLikePayloadLength(event) {
113
116
  if (!STRING_LIKE_VALUE_TYPES.has(event.type))
@@ -206,6 +209,8 @@ export function validate(aes, schema, options = {}) {
206
209
  // Phase 3: (moved to run after Phase 2)
207
210
  // Helpers: format canonical path (local, no runtime AEON deps)
208
211
  function formatCanonicalPath(path) {
212
+ if (typeof path === 'string')
213
+ return path;
209
214
  if (!path || !Array.isArray(path.segments))
210
215
  return '$';
211
216
  let result = '';
@@ -234,6 +239,10 @@ export function validate(aes, schema, options = {}) {
234
239
  function toTuple(span) {
235
240
  if (!span)
236
241
  return null;
242
+ if (typeof span === 'string') {
243
+ const match = span.match(/^(0|[1-9][0-9]*):(0|[1-9][0-9]*)$/u);
244
+ return match === null ? null : [Number(match[1]), Number(match[2])];
245
+ }
237
246
  if (Array.isArray(span) && span.length === 2 && typeof span[0] === 'number')
238
247
  return span;
239
248
  if (span.start && span.end && typeof span.start.offset === 'number')
@@ -243,24 +252,9 @@ export function validate(aes, schema, options = {}) {
243
252
  function decodeSeparatorChars(datatype) {
244
253
  if (!datatype)
245
254
  return [];
246
- const match = datatype.match(/\[([^\]]*)\]$/);
247
- if (!match)
248
- return [];
249
- const payload = match[1] ?? '';
250
- if (payload.length === 0)
255
+ if (datatypeBase(datatype).toLowerCase() !== 'sep')
251
256
  return [];
252
- const separators = [];
253
- let i = 0;
254
- while (i < payload.length) {
255
- separators.push(payload[i]);
256
- i += 1;
257
- if (i < payload.length) {
258
- if (payload[i] !== ',')
259
- return [];
260
- i += 1;
261
- }
262
- }
263
- return separators;
257
+ return parseClarifierValues(datatype).filter((value) => typeof value === 'string');
264
258
  }
265
259
  // Phase 2 — Baseline invariants
266
260
  const seen = new Map();
@@ -278,6 +272,7 @@ export function validate(aes, schema, options = {}) {
278
272
  const element = elements[i];
279
273
  const attributes = buildAttributeInfoMap(element?.attributes);
280
274
  const info = {
275
+ ...(typeof element?.structuralId === 'string' ? { identity: element.structuralId } : {}),
281
276
  type: typeof element?.type === 'string' ? element.type : 'Unknown',
282
277
  raw: typeof element?.raw === 'string' ? element.raw : '',
283
278
  value: typeof element?.value === 'string' ? element.value : '',
@@ -302,6 +297,7 @@ export function validate(aes, schema, options = {}) {
302
297
  const valueNode = entry?.value;
303
298
  const nestedAttributes = buildAttributeInfoMap(entry?.annotations);
304
299
  const info = {
300
+ ...(typeof entry?.structuralId === 'string' ? { identity: entry.structuralId } : {}),
305
301
  type: typeof valueNode?.type === 'string' ? valueNode.type : 'Unknown',
306
302
  raw: typeof valueNode?.raw === 'string' ? valueNode.raw : '',
307
303
  value: typeof valueNode?.value === 'string' ? valueNode.value : '',
@@ -319,6 +315,7 @@ export function validate(aes, schema, options = {}) {
319
315
  for (const [key, attribute] of attributes.entries()) {
320
316
  const attributePath = appendAttributePath(basePath, key);
321
317
  eventsByPath.set(attributePath, {
318
+ ...(attribute.identity !== undefined ? { identity: attribute.identity } : {}),
322
319
  type: attribute.type,
323
320
  raw: attribute.raw,
324
321
  value: attribute.value,
@@ -332,6 +329,7 @@ export function validate(aes, schema, options = {}) {
332
329
  for (let i = 0; i < aes.length; i++) {
333
330
  const event = aes[i];
334
331
  const pathStr = formatCanonicalPath(event.path);
332
+ const portable = isPortableTelexRecord(event);
335
333
  if (pathStr.length > resourcePolicy.max_path_length) {
336
334
  emitResourceError(ctx, pathStr, `Path length ${pathStr.length} exceeds max_path_length ${resourcePolicy.max_path_length}`, toTuple(event.span));
337
335
  }
@@ -355,9 +353,27 @@ export function validate(aes, schema, options = {}) {
355
353
  else {
356
354
  seen.set(pathStr, event.span);
357
355
  // Collect event info for Phase 5-7 checks
358
- if (event.value && typeof event.value.type === 'string') {
356
+ if (portable) {
357
+ const value = typeof event.value === 'string' ? event.value : '';
358
+ const datatype = portableDatatype(event);
359
+ const info = {
360
+ ...(typeof event.identity === 'string' ? { identity: event.identity } : {}),
361
+ type: event.kind,
362
+ raw: value,
363
+ value,
364
+ ...(datatype !== undefined ? { datatype } : {}),
365
+ span: toTuple(event.span),
366
+ ...((event.kind === 'CloneReference' || event.kind === 'PointerReference')
367
+ && typeof event.value === 'string'
368
+ ? { referencePath: parsePortableReferencePath(event.value) }
369
+ : {}),
370
+ };
371
+ eventsByPath.set(pathStr, info);
372
+ }
373
+ else if (event.value && typeof event.value.type === 'string') {
359
374
  const attributes = buildAttributeInfoMap(event.annotations);
360
375
  const info = {
376
+ ...(typeof event.structuralId === 'string' ? { identity: event.structuralId } : {}),
361
377
  type: event.value.type,
362
378
  raw: typeof event.value.raw === 'string' ? event.value.raw : '',
363
379
  value: typeof event.value.value === 'string' ? event.value.value : '',
@@ -393,18 +409,26 @@ export function validate(aes, schema, options = {}) {
393
409
  }
394
410
  // Register index even for first occurrence
395
411
  }
412
+ hydratePortableAttributes(eventsByPath, aes);
413
+ hydratePortableContainerArities(aes, containerArity, resourcePolicy, ctx, toTuple);
396
414
  for (const [path, info] of eventsByPath) {
397
415
  enforceStringLengthResourceBudget(info, path, resourcePolicy, ctx);
398
416
  }
399
417
  // Optional separator literal trailing-delimiter policy
400
418
  if (trailingSeparatorPolicy !== 'off') {
401
419
  for (const event of aes) {
402
- if (event?.value?.type !== 'SeparatorLiteral')
420
+ const portable = isPortableTelexRecord(event);
421
+ const kind = portable ? event.kind : event?.value?.type;
422
+ if (kind !== 'SeparatorLiteral')
403
423
  continue;
404
- const payload = typeof event.value.value === 'string' ? event.value.value : '';
424
+ const payload = portable
425
+ ? (typeof event.value === 'string' ? event.value : '')
426
+ : (typeof event.value.value === 'string' ? event.value.value : '');
405
427
  if (payload.length === 0)
406
428
  continue;
407
- const separators = decodeSeparatorChars(typeof event.datatype === 'string' ? event.datatype : undefined);
429
+ const separators = decodeSeparatorChars(portable
430
+ ? portableDatatype(event)
431
+ : (typeof event.datatype === 'string' ? event.datatype : undefined));
408
432
  if (separators.length === 0)
409
433
  continue;
410
434
  const lastChar = payload[payload.length - 1];
@@ -542,7 +566,7 @@ function checkWorldPolicy(schema, aes, boundPaths, eventsByPath, ctx) {
542
566
  }
543
567
  for (const event of aes) {
544
568
  const key = typeof event.key === 'string' ? event.key : '';
545
- if (key.startsWith('aeon:'))
569
+ if (event.sourcePlane === 'header' || (event.sourcePlane === undefined && key.startsWith('aeon:')))
546
570
  continue;
547
571
  const path = formatCanonicalPathLocal(event.path);
548
572
  if (!boundPaths.has(path))
@@ -784,6 +808,8 @@ function insertAeosSansaResolvePath(root, path, info) {
784
808
  }
785
809
  }
786
810
  current.info = info;
811
+ if (info.identity !== undefined)
812
+ current.identity = info.identity;
787
813
  }
788
814
  function getOrCreateChildBinding(parent, path, identity) {
789
815
  const existing = parent.children.find((child) => identity.name !== undefined
@@ -1017,14 +1043,6 @@ function validateAttributeEntry(path, entry, constraints, datatypeRules, ctx) {
1017
1043
  validateAttributeMap(path, entry.attributes, effectiveConstraints, datatypeRules, ctx);
1018
1044
  }
1019
1045
  }
1020
- function datatypeBase(datatype) {
1021
- const genericIdx = datatype.indexOf('<');
1022
- const separatorIdx = datatype.indexOf('[');
1023
- const endIdx = [genericIdx, separatorIdx]
1024
- .filter((idx) => idx >= 0)
1025
- .reduce((min, idx) => Math.min(min, idx), datatype.length);
1026
- return datatype.slice(0, endIdx);
1027
- }
1028
1046
  function mergeDatatypeRuleConstraints(constraints, datatype, datatypeRules) {
1029
1047
  if (!datatype || !datatypeRules)
1030
1048
  return constraints;
@@ -1158,15 +1176,6 @@ function radixConstraintMatches(datatype, raw, constraints) {
1158
1176
  return false;
1159
1177
  return firstInvalidRadixDigit(raw, constraints.radix) === null;
1160
1178
  }
1161
- function declaredRadixFromDatatype(datatype) {
1162
- if (datatype === undefined)
1163
- return null;
1164
- const match = /^radix(?:\[(\d+)\]|(\d+))$/i.exec(datatype.trim());
1165
- if (!match)
1166
- return null;
1167
- const value = Number(match[1] ?? match[2]);
1168
- return Number.isInteger(value) && value >= 0 ? value : null;
1169
- }
1170
1179
  function isStringType(type) {
1171
1180
  return type === 'StringLiteral'
1172
1181
  || type === 'TrimtickLiteral'
@@ -1178,7 +1187,7 @@ function isStringType(type) {
1178
1187
  || type === 'DateLiteral'
1179
1188
  || type === 'TimeLiteral'
1180
1189
  || type === 'DateTimeLiteral'
1181
- || type === 'ZRUTDateTimeLiteral';
1190
+ || type === 'WTCDateTimeLiteral';
1182
1191
  }
1183
1192
  function countFormDigits(type, raw) {
1184
1193
  if (type === 'NumberLiteral')
@@ -1222,7 +1231,159 @@ function isNegative(raw) {
1222
1231
  function isFormNegative(raw) {
1223
1232
  return /^[$#%^]?-/.test(raw) || raw.startsWith('-');
1224
1233
  }
1234
+ function isPortableTelexRecord(value) {
1235
+ if (value === null || typeof value !== 'object')
1236
+ return false;
1237
+ const record = value;
1238
+ return typeof record.path === 'string' && typeof record.kind === 'string' && record.header === undefined;
1239
+ }
1240
+ function portableDatatype(record) {
1241
+ if (typeof record.datatype !== 'string')
1242
+ return undefined;
1243
+ if (!Array.isArray(record.generics) || !Array.isArray(record.clarifiers))
1244
+ return record.datatype;
1245
+ return formatDatatypeDescriptor({
1246
+ datatype: record.datatype,
1247
+ generics: record.generics,
1248
+ clarifiers: record.clarifiers,
1249
+ });
1250
+ }
1251
+ function parsePortablePath(path) {
1252
+ if (!path.startsWith('$'))
1253
+ throw new TypeError(`Expected absolute portable AES path: ${path}`);
1254
+ const segments = [];
1255
+ const prefixes = [];
1256
+ let cursor = 1;
1257
+ while (cursor < path.length) {
1258
+ const start = cursor;
1259
+ let type;
1260
+ if (path.startsWith('.@.', cursor)) {
1261
+ type = 'attribute';
1262
+ cursor += 3;
1263
+ }
1264
+ else if (path[cursor] === '.') {
1265
+ type = 'member';
1266
+ cursor += 1;
1267
+ }
1268
+ else if (path[cursor] === '[') {
1269
+ const match = path.slice(cursor).match(/^\[(0|[1-9][0-9]*)\]/u);
1270
+ if (match === null)
1271
+ throw new TypeError(`Invalid portable AES index: ${path}`);
1272
+ cursor += match[0].length;
1273
+ segments.push({ type: 'index', index: Number(match[1]) });
1274
+ prefixes.push(path.slice(0, cursor));
1275
+ continue;
1276
+ }
1277
+ else {
1278
+ throw new TypeError(`Invalid portable AES path: ${path}`);
1279
+ }
1280
+ let key;
1281
+ if (path[cursor] === '[' && path[cursor + 1] === '"') {
1282
+ let end = cursor + 2;
1283
+ let escaped = false;
1284
+ for (; end < path.length; end += 1) {
1285
+ const character = path[end];
1286
+ if (escaped)
1287
+ escaped = false;
1288
+ else if (character === '\\')
1289
+ escaped = true;
1290
+ else if (character === '"')
1291
+ break;
1292
+ }
1293
+ if (path[end] !== '"' || path[end + 1] !== ']')
1294
+ throw new TypeError(`Invalid quoted member: ${path}`);
1295
+ key = JSON.parse(path.slice(cursor + 1, end + 1));
1296
+ cursor = end + 2;
1297
+ }
1298
+ else {
1299
+ const match = path.slice(cursor).match(/^[A-Za-z_][A-Za-z0-9_]*/u);
1300
+ if (match === null)
1301
+ throw new TypeError(`Invalid portable AES member: ${path}`);
1302
+ key = match[0];
1303
+ cursor += key.length;
1304
+ }
1305
+ segments.push({ type, key });
1306
+ prefixes.push(path.slice(0, cursor));
1307
+ if (cursor === start)
1308
+ throw new TypeError(`Invalid portable AES path: ${path}`);
1309
+ }
1310
+ return { segments, prefixes };
1311
+ }
1312
+ function parsePortableReferencePath(path) {
1313
+ return parsePortablePath(path).segments.map((segment) => {
1314
+ if (segment.type === 'index')
1315
+ return segment.index;
1316
+ if (segment.type === 'attribute')
1317
+ return { type: 'attr', key: segment.key };
1318
+ return segment.key;
1319
+ });
1320
+ }
1321
+ function hydratePortableAttributes(eventsByPath, aes) {
1322
+ const attributes = aes
1323
+ .filter(isPortableTelexRecord)
1324
+ .map((record) => {
1325
+ try {
1326
+ return { record, details: parsePortablePath(record.path) };
1327
+ }
1328
+ catch {
1329
+ return null;
1330
+ }
1331
+ })
1332
+ .filter((entry) => entry !== null)
1333
+ .filter(({ details }) => details.segments.at(-1)?.type === 'attribute')
1334
+ .sort((a, b) => a.details.segments.length - b.details.segments.length);
1335
+ for (const { record, details } of attributes) {
1336
+ const final = details.segments.at(-1);
1337
+ if (final?.type !== 'attribute')
1338
+ continue;
1339
+ const ownerPath = details.prefixes.at(-2) ?? '$';
1340
+ const owner = eventsByPath.get(ownerPath);
1341
+ const attribute = eventsByPath.get(record.path);
1342
+ if (owner === undefined || attribute === undefined)
1343
+ continue;
1344
+ const mapped = new Map(owner.attributes ?? []);
1345
+ mapped.set(final.key, attribute);
1346
+ owner.attributes = mapped;
1347
+ }
1348
+ }
1349
+ function hydratePortableContainerArities(aes, containerArity, resourcePolicy, ctx, toTuple) {
1350
+ const records = aes.filter(isPortableTelexRecord);
1351
+ if (records.length === 0)
1352
+ return;
1353
+ const details = new Map();
1354
+ for (const record of records) {
1355
+ try {
1356
+ details.set(record.path, parsePortablePath(record.path));
1357
+ }
1358
+ catch {
1359
+ // The portable AES validation layer reports malformed paths.
1360
+ }
1361
+ }
1362
+ for (const record of records) {
1363
+ if (!['ObjectNode', 'ListNode', 'TupleLiteral', 'NodeLiteral', 'NodeHead'].includes(record.kind))
1364
+ continue;
1365
+ const childOwner = record.kind === 'NodeLiteral' ? `${record.path}[0]` : record.path;
1366
+ let count = 0;
1367
+ for (const candidate of records) {
1368
+ const candidateDetails = details.get(candidate.path);
1369
+ if (candidateDetails === undefined)
1370
+ continue;
1371
+ const parent = candidateDetails.prefixes.at(-2) ?? '$';
1372
+ const last = candidateDetails.segments.at(-1);
1373
+ if (parent !== childOwner || last === undefined)
1374
+ continue;
1375
+ if (record.kind === 'ObjectNode' ? last.type === 'member' : last.type === 'index')
1376
+ count += 1;
1377
+ }
1378
+ containerArity.set(record.path, count);
1379
+ if (count > resourcePolicy.max_container_children_default) {
1380
+ emitResourceError(ctx, record.path, `Container child count ${count} exceeds max_container_children_default ${resourcePolicy.max_container_children_default}`, toTuple(record.span));
1381
+ }
1382
+ }
1383
+ }
1225
1384
  function formatCanonicalPathLocal(path) {
1385
+ if (typeof path === 'string')
1386
+ return path;
1226
1387
  if (!path || !Array.isArray(path.segments))
1227
1388
  return '$';
1228
1389
  let result = '';
@@ -1251,6 +1412,10 @@ function formatCanonicalPathLocal(path) {
1251
1412
  function toTupleLocal(span) {
1252
1413
  if (!span)
1253
1414
  return null;
1415
+ if (typeof span === 'string') {
1416
+ const match = span.match(/^(0|[1-9][0-9]*):(0|[1-9][0-9]*)$/u);
1417
+ return match === null ? null : [Number(match[1]), Number(match[2])];
1418
+ }
1254
1419
  if (Array.isArray(span) && span.length === 2 && typeof span[0] === 'number')
1255
1420
  return span;
1256
1421
  if (span.start && span.end && typeof span.start.offset === 'number')