@kashscript/lexicons 0.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 (78) hide show
  1. package/LICENSE +199 -0
  2. package/README.md +73 -0
  3. package/dist/engine.d.ts +48 -0
  4. package/dist/engine.d.ts.map +1 -0
  5. package/dist/engine.js +110 -0
  6. package/dist/engine.js.map +1 -0
  7. package/dist/envelope.d.ts +59 -0
  8. package/dist/envelope.d.ts.map +1 -0
  9. package/dist/envelope.js +43 -0
  10. package/dist/envelope.js.map +1 -0
  11. package/dist/extensions/social.d.ts +82 -0
  12. package/dist/extensions/social.d.ts.map +1 -0
  13. package/dist/extensions/social.js +99 -0
  14. package/dist/extensions/social.js.map +1 -0
  15. package/dist/extensions/trade.d.ts +94 -0
  16. package/dist/extensions/trade.d.ts.map +1 -0
  17. package/dist/extensions/trade.js +116 -0
  18. package/dist/extensions/trade.js.map +1 -0
  19. package/dist/extensions/zkp.d.ts +76 -0
  20. package/dist/extensions/zkp.d.ts.map +1 -0
  21. package/dist/extensions/zkp.js +68 -0
  22. package/dist/extensions/zkp.js.map +1 -0
  23. package/dist/index.d.ts +26 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +28 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/json-schema.d.ts +18 -0
  28. package/dist/json-schema.d.ts.map +1 -0
  29. package/dist/json-schema.js +125 -0
  30. package/dist/json-schema.js.map +1 -0
  31. package/dist/lexicons/index.d.ts +32 -0
  32. package/dist/lexicons/index.d.ts.map +1 -0
  33. package/dist/lexicons/index.js +59 -0
  34. package/dist/lexicons/index.js.map +1 -0
  35. package/dist/lexicons/kash-id-audit.d.ts +32 -0
  36. package/dist/lexicons/kash-id-audit.d.ts.map +1 -0
  37. package/dist/lexicons/kash-id-audit.js +21 -0
  38. package/dist/lexicons/kash-id-audit.js.map +1 -0
  39. package/dist/lexicons/kash-id-preferences.d.ts +60 -0
  40. package/dist/lexicons/kash-id-preferences.d.ts.map +1 -0
  41. package/dist/lexicons/kash-id-preferences.js +43 -0
  42. package/dist/lexicons/kash-id-preferences.js.map +1 -0
  43. package/dist/lexicons/kash-id-profile.d.ts +46 -0
  44. package/dist/lexicons/kash-id-profile.d.ts.map +1 -0
  45. package/dist/lexicons/kash-id-profile.js +31 -0
  46. package/dist/lexicons/kash-id-profile.js.map +1 -0
  47. package/dist/registry.d.ts +78 -0
  48. package/dist/registry.d.ts.map +1 -0
  49. package/dist/registry.js +133 -0
  50. package/dist/registry.js.map +1 -0
  51. package/dist/schema.d.ts +101 -0
  52. package/dist/schema.d.ts.map +1 -0
  53. package/dist/schema.js +224 -0
  54. package/dist/schema.js.map +1 -0
  55. package/dist/semver.d.ts +29 -0
  56. package/dist/semver.d.ts.map +1 -0
  57. package/dist/semver.js +42 -0
  58. package/dist/semver.js.map +1 -0
  59. package/dist/types.d.ts +21 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +8 -0
  62. package/dist/types.js.map +1 -0
  63. package/package.json +80 -0
  64. package/src/engine.ts +141 -0
  65. package/src/envelope.ts +128 -0
  66. package/src/extensions/social.ts +179 -0
  67. package/src/extensions/trade.ts +210 -0
  68. package/src/extensions/zkp.ts +108 -0
  69. package/src/index.ts +30 -0
  70. package/src/json-schema.ts +141 -0
  71. package/src/lexicons/index.ts +68 -0
  72. package/src/lexicons/kash-id-audit.ts +61 -0
  73. package/src/lexicons/kash-id-preferences.ts +114 -0
  74. package/src/lexicons/kash-id-profile.ts +82 -0
  75. package/src/registry.ts +168 -0
  76. package/src/schema.ts +347 -0
  77. package/src/semver.ts +56 -0
  78. package/src/types.ts +27 -0
@@ -0,0 +1,133 @@
1
+ /**
2
+ * LexiconRegistry — agnostic storage for Lexicon definitions.
3
+ *
4
+ * The registry holds a map of Lexicon IDs (NSID@semver) to schema definitions.
5
+ * It is **empty by default**: no Identity, Social, or Trade lexicons are
6
+ * pre-registered. Consumers explicitly register a Standard Library or load
7
+ * Extensions at bootstrap time (see `./engine.ts` and the Standard Library /
8
+ * Extension exports).
9
+ *
10
+ * The class does ZERO validation work itself — it just stores and resolves.
11
+ * Validation is performed by `validateEvent` (see `./engine.ts`) which
12
+ * accepts a registry as a parameter. This decoupling preserves the
13
+ * Box-vs-Content separation: the registry (Box) never knows about any
14
+ * specific domain (Content).
15
+ */
16
+ import { compareSemver, isForwardCompatible, parseLexiconId } from "./semver";
17
+ /**
18
+ * In-memory map of registered lexicons.
19
+ *
20
+ * Multiple major versions for the same NSID may co-exist. The registry
21
+ * resolves by exact match first, then by forward-compatible major.
22
+ */
23
+ export class LexiconRegistry {
24
+ byId = new Map();
25
+ byNsid = new Map();
26
+ /** Number of registered definitions. */
27
+ get size() {
28
+ return this.byId.size;
29
+ }
30
+ register(arg1, arg2, arg3) {
31
+ if (typeof arg1 === "string") {
32
+ if (arg2 === undefined) {
33
+ throw new TypeError("LexiconRegistry.register(id, schema): schema is required");
34
+ }
35
+ const parsed = parseLexiconId(arg1);
36
+ if (parsed === null) {
37
+ throw new TypeError(`LexiconRegistry.register: invalid lexicon ID "${arg1}"`);
38
+ }
39
+ const entry = {
40
+ id: arg1,
41
+ nsid: parsed.nsid,
42
+ semver: parsed.semver,
43
+ bodySchema: arg2,
44
+ ...(arg3?.title !== undefined ? { title: arg3.title } : {}),
45
+ ...(arg3?.description !== undefined ? { description: arg3.description } : {}),
46
+ };
47
+ return this.addEntry(entry);
48
+ }
49
+ return this.addEntry(arg1);
50
+ }
51
+ /** Register a batch of entries (typically a Standard Library or Extension export). */
52
+ registerAll(entries) {
53
+ for (const entry of entries)
54
+ this.addEntry(entry);
55
+ return this;
56
+ }
57
+ /** Exact-match lookup by full Lexicon ID. Returns undefined when not present. */
58
+ get(id) {
59
+ return this.byId.get(id);
60
+ }
61
+ /**
62
+ * Forward-compatible lookup by NSID + caller-supplied semver.
63
+ * Returns the highest-version registered entry whose major matches the caller.
64
+ */
65
+ resolve(nsid, semver) {
66
+ const candidates = this.byNsid.get(nsid);
67
+ if (!candidates)
68
+ return undefined;
69
+ for (const def of candidates) {
70
+ if (isForwardCompatible(def.semver, semver))
71
+ return def;
72
+ }
73
+ return undefined;
74
+ }
75
+ /** True if any version of the given NSID is registered. */
76
+ has(nsid) {
77
+ return this.byNsid.has(nsid);
78
+ }
79
+ /** True if the exact Lexicon ID is registered. */
80
+ hasId(id) {
81
+ return this.byId.has(id);
82
+ }
83
+ /** All registered Lexicon IDs, in insertion order. */
84
+ list() {
85
+ return Array.from(this.byId.keys());
86
+ }
87
+ /** All registered entries. */
88
+ entries() {
89
+ return Array.from(this.byId.values());
90
+ }
91
+ /** All NSIDs present in the registry. */
92
+ namespaces() {
93
+ return Array.from(this.byNsid.keys());
94
+ }
95
+ /** Drop every registered entry. */
96
+ clear() {
97
+ this.byId.clear();
98
+ this.byNsid.clear();
99
+ }
100
+ /** Remove a single entry by its full Lexicon ID. Returns whether anything was removed. */
101
+ unregister(id) {
102
+ const entry = this.byId.get(id);
103
+ if (!entry)
104
+ return false;
105
+ this.byId.delete(id);
106
+ const list = this.byNsid.get(entry.nsid);
107
+ if (list) {
108
+ const next = list.filter((e) => e.id !== id);
109
+ if (next.length === 0)
110
+ this.byNsid.delete(entry.nsid);
111
+ else
112
+ this.byNsid.set(entry.nsid, next);
113
+ }
114
+ return true;
115
+ }
116
+ /* ── internal ─────────────────────────────────────────────────── */
117
+ addEntry(entry) {
118
+ this.byId.set(entry.id, entry);
119
+ const list = this.byNsid.get(entry.nsid);
120
+ if (list) {
121
+ // remove any existing entry with the same full ID, then re-insert sorted descending
122
+ const next = list.filter((e) => e.id !== entry.id);
123
+ next.push(entry);
124
+ next.sort((a, b) => compareSemver(b.semver, a.semver));
125
+ this.byNsid.set(entry.nsid, next);
126
+ }
127
+ else {
128
+ this.byNsid.set(entry.nsid, [entry]);
129
+ }
130
+ return this;
131
+ }
132
+ }
133
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Zero-dependency schema DSL + validation engine.
3
+ *
4
+ * Schemas are plain data — no class methods, no closures — so they are
5
+ * trivially serialisable and comparable. The `S` namespace provides a
6
+ * Zod-style fluent builder for ergonomic authoring.
7
+ *
8
+ * Validation is depth-first and accumulates ALL errors (not fail-fast)
9
+ * so callers can render a complete diagnostic on first attempt.
10
+ */
11
+ export type Schema = AnySchema | StringSchema | NumberSchema | BooleanSchema | LiteralSchema | EnumSchema | ArraySchema | ObjectSchema | UnionSchema | OptionalSchema | RecordSchema;
12
+ export interface AnySchema {
13
+ readonly kind: "any";
14
+ }
15
+ export type SchemaStringFormat = "did-ks" | "cid" | "iso8601" | "url" | "multibase" | "bcp47" | "iso4217" | "lexicon-id" | "nsid";
16
+ export interface StringSchema {
17
+ readonly kind: "string";
18
+ readonly minLength?: number;
19
+ readonly maxLength?: number;
20
+ readonly pattern?: RegExp;
21
+ readonly format?: SchemaStringFormat;
22
+ }
23
+ export interface NumberSchema {
24
+ readonly kind: "number";
25
+ readonly min?: number;
26
+ readonly max?: number;
27
+ readonly integer?: boolean;
28
+ }
29
+ export interface BooleanSchema {
30
+ readonly kind: "boolean";
31
+ }
32
+ export interface LiteralSchema {
33
+ readonly kind: "literal";
34
+ readonly value: string | number | boolean | null;
35
+ }
36
+ export interface EnumSchema {
37
+ readonly kind: "enum";
38
+ readonly values: readonly (string | number)[];
39
+ }
40
+ export interface ArraySchema {
41
+ readonly kind: "array";
42
+ readonly items: Schema;
43
+ readonly minItems?: number;
44
+ readonly maxItems?: number;
45
+ }
46
+ export interface ObjectSchema {
47
+ readonly kind: "object";
48
+ readonly properties: Readonly<Record<string, Schema>>;
49
+ readonly required: readonly string[];
50
+ /** When false, unknown keys cause validation failure. Default: false. */
51
+ readonly additionalProperties: boolean;
52
+ }
53
+ export interface UnionSchema {
54
+ readonly kind: "union";
55
+ readonly variants: readonly Schema[];
56
+ }
57
+ export interface OptionalSchema {
58
+ readonly kind: "optional";
59
+ readonly inner: Schema;
60
+ }
61
+ export interface RecordSchema {
62
+ readonly kind: "record";
63
+ readonly keys: StringSchema;
64
+ readonly values: Schema;
65
+ }
66
+ export declare const S: {
67
+ any(): AnySchema;
68
+ string(opts?: Omit<StringSchema, "kind">): StringSchema;
69
+ number(opts?: Omit<NumberSchema, "kind">): NumberSchema;
70
+ boolean(): BooleanSchema;
71
+ literal(value: string | number | boolean | null): LiteralSchema;
72
+ enum(...values: readonly (string | number)[]): EnumSchema;
73
+ array(items: Schema, opts?: {
74
+ readonly minItems?: number;
75
+ readonly maxItems?: number;
76
+ }): ArraySchema;
77
+ object(properties: Readonly<Record<string, Schema>>, required?: readonly string[], additionalProperties?: boolean): ObjectSchema;
78
+ union(...variants: readonly Schema[]): UnionSchema;
79
+ optional(inner: Schema): OptionalSchema;
80
+ record(values: Schema, keys?: StringSchema): RecordSchema;
81
+ };
82
+ export interface ValidationError {
83
+ readonly path: readonly (string | number)[];
84
+ readonly message: string;
85
+ readonly received?: unknown;
86
+ }
87
+ export type ValidationResult<T = unknown> = {
88
+ readonly ok: true;
89
+ readonly value: T;
90
+ } | {
91
+ readonly ok: false;
92
+ readonly errors: readonly ValidationError[];
93
+ };
94
+ /** Canonical source-of-truth for the built-in string formats.
95
+ * Exported so the JSON-Schema exporter can read `.source` without
96
+ * re-typing the regex literals. */
97
+ export declare const FORMAT_PATTERNS: Record<SchemaStringFormat, RegExp>;
98
+ export declare function validate<T = unknown>(schema: Schema, value: unknown): ValidationResult<T>;
99
+ /** Convenience type-guard. Returns true iff `value` matches `schema`. */
100
+ export declare function matches(schema: Schema, value: unknown): boolean;
101
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
package/dist/schema.js ADDED
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Zero-dependency schema DSL + validation engine.
3
+ *
4
+ * Schemas are plain data — no class methods, no closures — so they are
5
+ * trivially serialisable and comparable. The `S` namespace provides a
6
+ * Zod-style fluent builder for ergonomic authoring.
7
+ *
8
+ * Validation is depth-first and accumulates ALL errors (not fail-fast)
9
+ * so callers can render a complete diagnostic on first attempt.
10
+ */
11
+ /* ── fluent builders ────────────────────────────────────────────── */
12
+ export const S = {
13
+ any() {
14
+ return { kind: "any" };
15
+ },
16
+ string(opts) {
17
+ return { kind: "string", ...opts };
18
+ },
19
+ number(opts) {
20
+ return { kind: "number", ...opts };
21
+ },
22
+ boolean() {
23
+ return { kind: "boolean" };
24
+ },
25
+ literal(value) {
26
+ return { kind: "literal", value };
27
+ },
28
+ enum(...values) {
29
+ return { kind: "enum", values };
30
+ },
31
+ array(items, opts) {
32
+ return { kind: "array", items, ...opts };
33
+ },
34
+ object(properties, required = [], additionalProperties = false) {
35
+ return { kind: "object", properties, required, additionalProperties };
36
+ },
37
+ union(...variants) {
38
+ return { kind: "union", variants };
39
+ },
40
+ optional(inner) {
41
+ return { kind: "optional", inner };
42
+ },
43
+ record(values, keys = { kind: "string" }) {
44
+ return { kind: "record", keys, values };
45
+ },
46
+ };
47
+ /* ── string format patterns ─────────────────────────────────────── */
48
+ /** Canonical source-of-truth for the built-in string formats.
49
+ * Exported so the JSON-Schema exporter can read `.source` without
50
+ * re-typing the regex literals. */
51
+ export const FORMAT_PATTERNS = {
52
+ // identity-core's DID method is `did:kash:` with a base58btc-encoded pubkey
53
+ // body. Ed25519 pubkeys (32 bytes) round-trip to 43-44 chars in base58btc.
54
+ // The format-id stays `did-ks` (schema-internal name) for backward
55
+ // compatibility; the regex now matches what `@kashscript/identity-core`
56
+ // emits via `deriveDid()`.
57
+ "did-ks": /^did:kash:[1-9A-HJ-NP-Za-km-z]{32,48}$/,
58
+ "cid": /^bafy[a-z2-7]{52,}$/,
59
+ "iso8601": /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/,
60
+ "url": /^https?:\/\/[^\s]+$/,
61
+ "multibase": /^z[1-9A-HJ-NP-Za-km-z]+$/,
62
+ "bcp47": /^[a-z]{2,3}(-[A-Z]{2})?$/,
63
+ "iso4217": /^[A-Z]{3}$/,
64
+ "lexicon-id": /^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)+@\d+\.\d+\.\d+$/,
65
+ "nsid": /^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)+$/,
66
+ };
67
+ /* ── public entry point ─────────────────────────────────────────── */
68
+ export function validate(schema, value) {
69
+ const errors = [];
70
+ validateRec(schema, value, [], errors);
71
+ return errors.length === 0
72
+ ? { ok: true, value: value }
73
+ : { ok: false, errors };
74
+ }
75
+ /** Convenience type-guard. Returns true iff `value` matches `schema`. */
76
+ export function matches(schema, value) {
77
+ const errors = [];
78
+ validateRec(schema, value, [], errors);
79
+ return errors.length === 0;
80
+ }
81
+ /* ── recursive validator ────────────────────────────────────────── */
82
+ function validateRec(schema, value, path, errors) {
83
+ switch (schema.kind) {
84
+ case "any":
85
+ return;
86
+ case "string":
87
+ validateString(schema, value, path, errors);
88
+ return;
89
+ case "number":
90
+ validateNumber(schema, value, path, errors);
91
+ return;
92
+ case "boolean":
93
+ if (typeof value !== "boolean")
94
+ errors.push(err(path, "expected boolean", value));
95
+ return;
96
+ case "literal":
97
+ if (value !== schema.value) {
98
+ errors.push(err(path, `expected literal ${JSON.stringify(schema.value)}`, value));
99
+ }
100
+ return;
101
+ case "enum":
102
+ if (typeof value !== "string" && typeof value !== "number") {
103
+ errors.push(err(path, "expected string|number for enum", value));
104
+ return;
105
+ }
106
+ if (!schema.values.includes(value)) {
107
+ errors.push(err(path, `expected one of ${JSON.stringify(schema.values)}`, value));
108
+ }
109
+ return;
110
+ case "array":
111
+ validateArray(schema, value, path, errors);
112
+ return;
113
+ case "object":
114
+ validateObject(schema, value, path, errors);
115
+ return;
116
+ case "union":
117
+ validateUnion(schema, value, path, errors);
118
+ return;
119
+ case "optional":
120
+ if (value === undefined)
121
+ return;
122
+ validateRec(schema.inner, value, path, errors);
123
+ return;
124
+ case "record":
125
+ validateRecord(schema, value, path, errors);
126
+ return;
127
+ }
128
+ }
129
+ function err(path, message, received) {
130
+ return { path, message, received };
131
+ }
132
+ function validateString(s, value, path, errors) {
133
+ if (typeof value !== "string") {
134
+ errors.push(err(path, "expected string", value));
135
+ return;
136
+ }
137
+ if (s.minLength !== undefined && value.length < s.minLength) {
138
+ errors.push(err(path, `string too short (min ${s.minLength}, got ${value.length})`, value));
139
+ }
140
+ if (s.maxLength !== undefined && value.length > s.maxLength) {
141
+ errors.push(err(path, `string too long (max ${s.maxLength}, got ${value.length})`, value));
142
+ }
143
+ if (s.pattern && !s.pattern.test(value)) {
144
+ errors.push(err(path, `does not match pattern ${s.pattern.toString()}`, value));
145
+ }
146
+ if (s.format && !FORMAT_PATTERNS[s.format].test(value)) {
147
+ errors.push(err(path, `does not match format "${s.format}"`, value));
148
+ }
149
+ }
150
+ function validateNumber(s, value, path, errors) {
151
+ if (typeof value !== "number" || Number.isNaN(value)) {
152
+ errors.push(err(path, "expected number", value));
153
+ return;
154
+ }
155
+ if (s.integer && !Number.isInteger(value)) {
156
+ errors.push(err(path, "expected integer", value));
157
+ }
158
+ if (s.min !== undefined && value < s.min) {
159
+ errors.push(err(path, `below minimum ${s.min}`, value));
160
+ }
161
+ if (s.max !== undefined && value > s.max) {
162
+ errors.push(err(path, `above maximum ${s.max}`, value));
163
+ }
164
+ }
165
+ function validateArray(s, value, path, errors) {
166
+ if (!Array.isArray(value)) {
167
+ errors.push(err(path, "expected array", value));
168
+ return;
169
+ }
170
+ if (s.minItems !== undefined && value.length < s.minItems) {
171
+ errors.push(err(path, `array too short (min ${s.minItems}, got ${value.length})`, value));
172
+ }
173
+ if (s.maxItems !== undefined && value.length > s.maxItems) {
174
+ errors.push(err(path, `array too long (max ${s.maxItems}, got ${value.length})`, value));
175
+ }
176
+ for (let i = 0; i < value.length; i++) {
177
+ validateRec(s.items, value[i], [...path, i], errors);
178
+ }
179
+ }
180
+ function validateObject(s, value, path, errors) {
181
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
182
+ errors.push(err(path, "expected object", value));
183
+ return;
184
+ }
185
+ const obj = value;
186
+ for (const k of s.required) {
187
+ if (!(k in obj)) {
188
+ errors.push(err([...path, k], "missing required field", undefined));
189
+ }
190
+ }
191
+ for (const k of Object.keys(s.properties)) {
192
+ if (k in obj) {
193
+ const subSchema = s.properties[k];
194
+ validateRec(subSchema, obj[k], [...path, k], errors);
195
+ }
196
+ }
197
+ if (!s.additionalProperties) {
198
+ for (const k of Object.keys(obj)) {
199
+ if (!(k in s.properties)) {
200
+ errors.push(err([...path, k], "unknown field", obj[k]));
201
+ }
202
+ }
203
+ }
204
+ }
205
+ function validateUnion(s, value, path, errors) {
206
+ for (const variant of s.variants) {
207
+ const subErrors = [];
208
+ validateRec(variant, value, path, subErrors);
209
+ if (subErrors.length === 0)
210
+ return;
211
+ }
212
+ errors.push(err(path, `value matched none of ${s.variants.length} union variants`, value));
213
+ }
214
+ function validateRecord(s, value, path, errors) {
215
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
216
+ errors.push(err(path, "expected object (record)", value));
217
+ return;
218
+ }
219
+ for (const [k, v] of Object.entries(value)) {
220
+ validateRec(s.keys, k, [...path, k], errors);
221
+ validateRec(s.values, v, [...path, k], errors);
222
+ }
223
+ }
224
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Semver parsing and forward-compat resolution for Lexicon IDs.
3
+ * Lexicon ID syntax: <nsid>@<major>.<minor>.<patch> — e.g., "kash.id.profile@1.2.0".
4
+ */
5
+ import type { LexiconId } from "./types";
6
+ export interface Semver {
7
+ readonly major: number;
8
+ readonly minor: number;
9
+ readonly patch: number;
10
+ }
11
+ export interface ParsedLexiconId {
12
+ readonly nsid: string;
13
+ readonly semver: Semver;
14
+ }
15
+ /** Parse a Lexicon ID. Returns null on malformed input. */
16
+ export declare function parseLexiconId(id: string): ParsedLexiconId | null;
17
+ /** Build a Lexicon ID string from parts. */
18
+ export declare function formatLexiconId(nsid: string, semver: Semver): LexiconId;
19
+ /** Lexicographic compare. Returns negative/zero/positive (like Array.sort). */
20
+ export declare function compareSemver(a: Semver, b: Semver): number;
21
+ /**
22
+ * Is the `record` semver forward-compatible with the `consumer` semver?
23
+ *
24
+ * v1.0 evolution rule: any record minted under <nsid>@X.Y.Z is acceptable to
25
+ * a consumer that knows <nsid>@X.*. Cross-major requires an explicit migrator
26
+ * (out of scope for this layer — handled by the consumer at a higher level).
27
+ */
28
+ export declare function isForwardCompatible(consumer: Semver, record: Semver): boolean;
29
+ //# sourceMappingURL=semver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver.d.ts","sourceRoot":"","sources":["../src/semver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAID,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAWjE;AAED,4CAA4C;AAC5C,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAEvE;AAED,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAI1D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAE7E"}
package/dist/semver.js ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Semver parsing and forward-compat resolution for Lexicon IDs.
3
+ * Lexicon ID syntax: <nsid>@<major>.<minor>.<patch> — e.g., "kash.id.profile@1.2.0".
4
+ */
5
+ const LEXICON_ID_RE = /^([a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+)@(\d+)\.(\d+)\.(\d+)$/;
6
+ /** Parse a Lexicon ID. Returns null on malformed input. */
7
+ export function parseLexiconId(id) {
8
+ const m = LEXICON_ID_RE.exec(id);
9
+ if (!m)
10
+ return null;
11
+ return {
12
+ nsid: m[1],
13
+ semver: {
14
+ major: Number.parseInt(m[2], 10),
15
+ minor: Number.parseInt(m[3], 10),
16
+ patch: Number.parseInt(m[4], 10),
17
+ },
18
+ };
19
+ }
20
+ /** Build a Lexicon ID string from parts. */
21
+ export function formatLexiconId(nsid, semver) {
22
+ return `${nsid}@${semver.major}.${semver.minor}.${semver.patch}`;
23
+ }
24
+ /** Lexicographic compare. Returns negative/zero/positive (like Array.sort). */
25
+ export function compareSemver(a, b) {
26
+ if (a.major !== b.major)
27
+ return a.major - b.major;
28
+ if (a.minor !== b.minor)
29
+ return a.minor - b.minor;
30
+ return a.patch - b.patch;
31
+ }
32
+ /**
33
+ * Is the `record` semver forward-compatible with the `consumer` semver?
34
+ *
35
+ * v1.0 evolution rule: any record minted under <nsid>@X.Y.Z is acceptable to
36
+ * a consumer that knows <nsid>@X.*. Cross-major requires an explicit migrator
37
+ * (out of scope for this layer — handled by the consumer at a higher level).
38
+ */
39
+ export function isForwardCompatible(consumer, record) {
40
+ return consumer.major === record.major;
41
+ }
42
+ //# sourceMappingURL=semver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver.js","sourceRoot":"","sources":["../src/semver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAeH,MAAM,aAAa,GAAG,+DAA+D,CAAC;AAEtF,2DAA2D;AAC3D,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,MAAM,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,CAAC,CAAE;QACX,MAAM,EAAE;YACN,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC;YACjC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC;YACjC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC;SAClC;KACF,CAAC;AACJ,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,MAAc;IAC1D,OAAO,GAAG,IAAI,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,EAAe,CAAC;AAChF,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,aAAa,CAAC,CAAS,EAAE,CAAS;IAChD,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK;QAAE,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;IAClD,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK;QAAE,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;IAClD,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;AAC3B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,MAAc;IAClE,OAAO,QAAQ,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC;AACzC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Shared brand types used across the lexicon framework.
3
+ * Phase-3 may re-export these from @kashscript/identity once that package
4
+ * publishes its own brand types.
5
+ */
6
+ /** W3C DID restricted to the did:kash method emitted by `@kashscript/identity-core`. */
7
+ export type DID = `did:kash:${string}`;
8
+ /** CIDv1 multibase, base32, "bafy" prefix. */
9
+ export type CID = `bafy${string}`;
10
+ /** Lexicon ID — <nsid>@<semver>, e.g., "kash.id.profile@1.0.0". */
11
+ export type LexiconId = `${string}@${number}.${number}.${number}`;
12
+ /** Multibase-encoded byte string ("z"-prefixed base58-btc). */
13
+ export type Multibase = `z${string}`;
14
+ /** ISO-8601 timestamp with offset, e.g. "2026-05-09T12:34:56Z". */
15
+ export type Iso8601 = string;
16
+ /** Signature algorithm identifier. Phase-4 adds "es256"; Phase-5 adds "bls12-381-g2". */
17
+ export type SignatureAlgorithm = "ed25519" | "es256" | "bls12-381-g2";
18
+ /** Domain-Separation Tag for record-tier signatures (Identity Protocol §5.5). */
19
+ export declare const KASH_RECORD_DST: "kash-record-v1\n";
20
+ export type KashRecordDST = typeof KASH_RECORD_DST;
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wFAAwF;AACxF,MAAM,MAAM,GAAG,GAAG,YAAY,MAAM,EAAE,CAAC;AAEvC,8CAA8C;AAC9C,MAAM,MAAM,GAAG,GAAG,OAAO,MAAM,EAAE,CAAC;AAElC,mEAAmE;AACnE,MAAM,MAAM,SAAS,GAAG,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;AAElE,+DAA+D;AAC/D,MAAM,MAAM,SAAS,GAAG,IAAI,MAAM,EAAE,CAAC;AAErC,mEAAmE;AACnE,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B,yFAAyF;AACzF,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,GAAG,cAAc,CAAC;AAEtE,iFAAiF;AACjF,eAAO,MAAM,eAAe,EAAG,kBAA2B,CAAC;AAC3D,MAAM,MAAM,aAAa,GAAG,OAAO,eAAe,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Shared brand types used across the lexicon framework.
3
+ * Phase-3 may re-export these from @kashscript/identity once that package
4
+ * publishes its own brand types.
5
+ */
6
+ /** Domain-Separation Tag for record-tier signatures (Identity Protocol §5.5). */
7
+ export const KASH_RECORD_DST = "kash-record-v1\n";
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH,iFAAiF;AACjF,MAAM,CAAC,MAAM,eAAe,GAAG,kBAA2B,CAAC"}