@lemmaoracle/agent 0.0.23

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.
@@ -0,0 +1,19 @@
1
+ import type { CredentialOptions, ValidationError, ValidationResult } from "./types.js";
2
+ /** Validate required identity fields are non-empty. */
3
+ export declare const validateRequiredFields: (input: Record<string, unknown>) => ReadonlyArray<ValidationError>;
4
+ /** Validate financial.spendLimit is within bounds and is an integer. */
5
+ export declare const validateSpendLimit: (input: Record<string, unknown>) => ReadonlyArray<ValidationError>;
6
+ /** Validate financial.currency is 3-letter uppercase when present. */
7
+ export declare const validateCurrency: (input: Record<string, unknown>) => ReadonlyArray<ValidationError>;
8
+ /** Validate lifecycle timestamps (issuedAt and expiresAt). */
9
+ export declare const validateTimestamps: (input: Record<string, unknown>) => ReadonlyArray<ValidationError>;
10
+ /** Validate provenance fields. */
11
+ export declare const validateProvenance: (_input: Record<string, unknown>) => ReadonlyArray<ValidationError>;
12
+ /**
13
+ * Validate an Agent Credential against schema rules.
14
+ *
15
+ * Pure, synchronous, does not throw.
16
+ * Returns a `ValidationResult` discriminated union.
17
+ */
18
+ export declare const validate: (input: unknown, options?: CredentialOptions) => ValidationResult;
19
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAEV,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAmBpB,uDAAuD;AACvD,eAAO,MAAM,sBAAsB,GACjC,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,aAAa,CAAC,eAAe,CAgB/B,CAAC;AAEF,wEAAwE;AACxE,eAAO,MAAM,kBAAkB,GAC7B,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,aAAa,CAAC,eAAe,CAoB/B,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,GAC3B,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,aAAa,CAAC,eAAe,CAO/B,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,kBAAkB,GAC7B,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,aAAa,CAAC,eAAe,CAwC/B,CAAC;AAEF,kCAAkC;AAClC,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,aAAa,CAAC,eAAe,CAE5B,CAAC;AAmBL;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GACnB,OAAO,OAAO,EACd,UAAU,iBAAiB,KAC1B,gBAeF,CAAC"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Pure validation functions for Agent Credentials.
3
+ *
4
+ * Mirrors the normalize WASM's validation rules as a client-side pre-flight
5
+ * check. The WASM remains the authoritative validator.
6
+ *
7
+ * Uses Ramda for branching (R.cond, R.when) — no if/switch statements.
8
+ */
9
+ import * as R from "ramda";
10
+ const DEFAULT_SCHEMA_ID = "agent-identity-authority-v1";
11
+ const MAX_SPEND_LIMIT = 1_000_000_000_000;
12
+ const MAX_EXPIRES_AT = 4102444800;
13
+ const err = (kind, message) => ({ kind, message });
14
+ const push = (errors, condition, error) => condition ? [...errors, error] : errors;
15
+ // ── Individual validators ───────────────────────────────────────────────
16
+ /** Validate required identity fields are non-empty. */
17
+ export const validateRequiredFields = (input) => {
18
+ const identity = R.pathOr({}, ["identity"], input);
19
+ const authority = R.pathOr({}, ["authority"], input);
20
+ const provenance = R.pathOr({}, ["provenance"], input);
21
+ const agentId = R.pathOr("", ["agentId"], identity);
22
+ const subjectId = R.pathOr("", ["subjectId"], identity);
23
+ const roles = R.pathOr([], ["roles"], authority);
24
+ const issuerId = R.pathOr("", ["issuerId"], provenance);
25
+ return [
26
+ ...R.isEmpty(agentId) ? [err("EmptyAgentId", "identity.agentId must not be empty")] : [],
27
+ ...R.isEmpty(subjectId) ? [err("EmptySubjectId", "identity.subjectId must not be empty")] : [],
28
+ ...R.isEmpty(roles) ? [err("EmptyRoles", "authority.roles must not be empty")] : [],
29
+ ...R.isEmpty(issuerId) ? [err("EmptyIssuerId", "provenance.issuerId must not be empty")] : [],
30
+ ];
31
+ };
32
+ /** Validate financial.spendLimit is within bounds and is an integer. */
33
+ export const validateSpendLimit = (input) => {
34
+ const spendLimit = R.path(["financial", "spendLimit"], input);
35
+ const isEmpty = spendLimit === undefined || spendLimit === null
36
+ ? []
37
+ : [];
38
+ const isInvalid = spendLimit !== undefined && spendLimit !== null &&
39
+ (typeof spendLimit !== "number" || !Number.isInteger(spendLimit) || spendLimit < 0)
40
+ ? [err("SpendLimitExceeded", "financial.spendLimit must be a non-negative integer")]
41
+ : [];
42
+ const isTooLarge = typeof spendLimit === "number" && Number.isInteger(spendLimit) && spendLimit >= 0 && spendLimit > MAX_SPEND_LIMIT
43
+ ? [err("SpendLimitExceeded", `financial.spendLimit must not exceed ${MAX_SPEND_LIMIT}`)]
44
+ : [];
45
+ return [...isEmpty, ...isInvalid, ...isTooLarge];
46
+ };
47
+ /** Validate financial.currency is 3-letter uppercase when present. */
48
+ export const validateCurrency = (input) => {
49
+ const currency = R.path(["financial", "currency"], input);
50
+ return currency !== undefined && currency !== null &&
51
+ (typeof currency !== "string" || currency.length !== 3 || !/^[A-Z]{3}$/.test(currency))
52
+ ? [err("InvalidCurrency", "financial.currency must be a 3-letter uppercase ISO 4217 code")]
53
+ : [];
54
+ };
55
+ /** Validate lifecycle timestamps (issuedAt and expiresAt). */
56
+ export const validateTimestamps = (input) => {
57
+ const issuedAt = R.path(["lifecycle", "issuedAt"], input);
58
+ const expiresAt = R.path(["lifecycle", "expiresAt"], input);
59
+ const chainId = R.path(["provenance", "chainContext", "chainId"], input);
60
+ const isInvalidU64 = (val) => val === null ||
61
+ val === undefined ||
62
+ typeof val !== "number" ||
63
+ !Number.isInteger(val) ||
64
+ val < 0;
65
+ let errors = [];
66
+ // issuedAt must be a non-negative integer
67
+ errors = push(errors, isInvalidU64(issuedAt), err("InvalidTimestamp", "lifecycle.issuedAt must be a non-negative integer"));
68
+ // expiresAt: when present, must be a non-negative integer
69
+ errors = push(errors, expiresAt !== undefined && expiresAt !== null && isInvalidU64(expiresAt), err("InvalidTimestamp", "lifecycle.expiresAt must be a non-negative integer when present"));
70
+ // expiresAt must be > issuedAt when both are valid numbers
71
+ errors = push(errors, typeof expiresAt === "number" && Number.isInteger(expiresAt) &&
72
+ typeof issuedAt === "number" && Number.isInteger(issuedAt) &&
73
+ expiresAt <= issuedAt, err("InvalidTimestamp", "lifecycle.expiresAt must be greater than lifecycle.issuedAt"));
74
+ // expiresAt must be ≤ 4102444800
75
+ errors = push(errors, typeof expiresAt === "number" && Number.isInteger(expiresAt) && expiresAt > MAX_EXPIRES_AT, err("InvalidTimestamp", `lifecycle.expiresAt must not exceed ${MAX_EXPIRES_AT}`));
76
+ // chainId must be a non-negative integer when present
77
+ errors = push(errors, chainId !== undefined && chainId !== null && isInvalidU64(chainId), err("InvalidTimestamp", "provenance.chainContext.chainId must be a non-negative integer when present"));
78
+ return errors;
79
+ };
80
+ /** Validate provenance fields. */
81
+ export const validateProvenance = (_input) =>
82
+ // provenance.issuerId is validated in validateRequiredFields
83
+ [];
84
+ // ── Schema validation ───────────────────────────────────────────────────
85
+ /** Validate the schema field matches the expected value. */
86
+ const validateSchema = (input, options) => {
87
+ const expectedSchema = options?.schemaId ?? DEFAULT_SCHEMA_ID;
88
+ const actualSchema = R.prop("schema", input);
89
+ return actualSchema === expectedSchema
90
+ ? []
91
+ : [err("InvalidSchema", `schema must be "${expectedSchema}"`)];
92
+ };
93
+ // ── Composed validate ───────────────────────────────────────────────────
94
+ /**
95
+ * Validate an Agent Credential against schema rules.
96
+ *
97
+ * Pure, synchronous, does not throw.
98
+ * Returns a `ValidationResult` discriminated union.
99
+ */
100
+ export const validate = (input, options) => {
101
+ const record = input;
102
+ const allErrors = [
103
+ ...validateSchema(record, options),
104
+ ...validateRequiredFields(record),
105
+ ...validateSpendLimit(record),
106
+ ...validateCurrency(record),
107
+ ...validateTimestamps(record),
108
+ ...validateProvenance(record),
109
+ ];
110
+ return R.isEmpty(allErrors)
111
+ ? { valid: true, credential: record }
112
+ : { valid: false, errors: allErrors };
113
+ };
114
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,CAAC,MAAM,OAAO,CAAC;AAQ3B,MAAM,iBAAiB,GAAG,6BAA6B,CAAC;AACxD,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAC1C,MAAM,cAAc,GAAG,UAAU,CAAC;AAElC,MAAM,GAAG,GACP,CAAC,IAA6B,EAAE,OAAe,EAAmB,EAAE,CAClE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAExB,MAAM,IAAI,GAAG,CACX,MAAsC,EACtC,SAAkB,EAClB,KAAsB,EACU,EAAE,CAClC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAE1C,2EAA2E;AAE3E,uDAAuD;AACvD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,KAA8B,EACE,EAAE;IAClC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAA0B,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAA0B,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAA0B,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,CAAC;IAEhF,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAW,CAAC;IAC9D,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAW,CAAC;IAClE,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,SAAS,CAAc,CAAC;IAC9D,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,UAAU,CAAW,CAAC;IAElE,OAAO;QACL,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,EAAE,oCAAoC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;QACxF,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,sCAAsC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;QAC9F,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,EAAE,mCAAmC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;QACnF,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,uCAAuC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;KAC9F,CAAC;AACJ,CAAC,CAAC;AAEF,wEAAwE;AACxE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,KAA8B,EACE,EAAE;IAClC,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE,KAAK,CAAC,CAAC;IAE9D,MAAM,OAAO,GACX,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,IAAI;QAC7C,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,EAAE,CAAC;IAET,MAAM,SAAS,GACb,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,IAAI;QAC/C,CAAC,OAAO,UAAU,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,CAAC;QACjF,CAAC,CAAC,CAAC,GAAG,CAAC,oBAAoB,EAAE,qDAAqD,CAAC,CAAC;QACpF,CAAC,CAAC,EAAE,CAAC;IAET,MAAM,UAAU,GACd,OAAO,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC,IAAI,UAAU,GAAG,eAAe;QAC/G,CAAC,CAAC,CAAC,GAAG,CAAC,oBAAoB,EAAE,wCAAwC,eAAe,EAAE,CAAC,CAAC;QACxF,CAAC,CAAC,EAAE,CAAC;IAET,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,SAAS,EAAE,GAAG,UAAU,CAAC,CAAC;AACnD,CAAC,CAAC;AAEF,sEAAsE;AACtE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAA8B,EACE,EAAE;IAClC,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC;IAE1D,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI;QAChD,CAAC,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvF,CAAC,CAAC,CAAC,GAAG,CAAC,iBAAiB,EAAE,+DAA+D,CAAC,CAAC;QAC3F,CAAC,CAAC,EAAE,CAAC;AACT,CAAC,CAAC;AAEF,8DAA8D;AAC9D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,KAA8B,EACE,EAAE;IAClC,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,KAAK,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;IAEzE,MAAM,YAAY,GAAG,CAAC,GAAY,EAAW,EAAE,CAC7C,GAAG,KAAK,IAAI;QACZ,GAAG,KAAK,SAAS;QACjB,OAAO,GAAG,KAAK,QAAQ;QACvB,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC;QACtB,GAAG,GAAG,CAAC,CAAC;IAEV,IAAI,MAAM,GAAmC,EAAE,CAAC;IAEhD,0CAA0C;IAC1C,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,EAC1C,GAAG,CAAC,kBAAkB,EAAE,mDAAmD,CAAC,CAAC,CAAC;IAEhF,0DAA0D;IAC1D,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,IAAI,IAAI,YAAY,CAAC,SAAS,CAAC,EAC5F,GAAG,CAAC,kBAAkB,EAAE,iEAAiE,CAAC,CAAC,CAAC;IAE9F,2DAA2D;IAC3D,MAAM,GAAG,IAAI,CAAC,MAAM,EAClB,OAAO,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;QAC5D,OAAO,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;QAC1D,SAAS,IAAI,QAAQ,EACrB,GAAG,CAAC,kBAAkB,EAAE,6DAA6D,CAAC,CAAC,CAAC;IAE1F,iCAAiC;IACjC,MAAM,GAAG,IAAI,CAAC,MAAM,EAClB,OAAO,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,cAAc,EAC1F,GAAG,CAAC,kBAAkB,EAAE,uCAAuC,cAAc,EAAE,CAAC,CAAC,CAAC;IAEpF,sDAAsD;IACtD,MAAM,GAAG,IAAI,CAAC,MAAM,EAClB,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,IAAI,YAAY,CAAC,OAAO,CAAC,EAClE,GAAG,CAAC,kBAAkB,EAAE,6EAA6E,CAAC,CAAC,CAAC;IAE1G,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,kCAAkC;AAClC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,MAA+B,EACC,EAAE;AAClC,6DAA6D;AAC7D,EAAE,CAAC;AAEL,2EAA2E;AAE3E,4DAA4D;AAC5D,MAAM,cAAc,GAAG,CACrB,KAA8B,EAC9B,OAA2B,EACK,EAAE;IAClC,MAAM,cAAc,GAAG,OAAO,EAAE,QAAQ,IAAI,iBAAiB,CAAC;IAC9D,MAAM,YAAY,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAY,CAAC;IAExD,OAAO,YAAY,KAAK,cAAc;QACpC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,mBAAmB,cAAc,GAAG,CAAC,CAAC,CAAC;AACnE,CAAC,CAAC;AAEF,2EAA2E;AAE3E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,KAAc,EACd,OAA2B,EACT,EAAE;IACpB,MAAM,MAAM,GAAG,KAAgC,CAAC;IAEhD,MAAM,SAAS,GAAmC;QAChD,GAAG,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC;QAClC,GAAG,sBAAsB,CAAC,MAAM,CAAC;QACjC,GAAG,kBAAkB,CAAC,MAAM,CAAC;QAC7B,GAAG,gBAAgB,CAAC,MAAM,CAAC;QAC3B,GAAG,kBAAkB,CAAC,MAAM,CAAC;QAC7B,GAAG,kBAAkB,CAAC,MAAM,CAAC;KAC9B,CAAC;IAEF,OAAO,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;QACzB,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAoC,EAAE;QACnE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC1C,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ [package]
2
+ name = "lemma-agent"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ authors = ["Lemma Oracle"]
6
+ description = "Agent Identity + Authority Credential schema WASM for Lemma circuits"
7
+ license = "MIT"
8
+ repository = "https://github.com/lemmaoracle/lemma"
9
+
10
+ [lib]
11
+ crate-type = ["cdylib", "lib"]
12
+
13
+ [dependencies]
14
+ wasm-bindgen = "0.2"
15
+ js-sys = "0.3"
16
+ serde = { version = "1", features = ["derive"] }
17
+ serde_json = "1"
18
+
19
+ [profile.release]
20
+ opt-level = "s"
21
+ lto = true
22
+ codegen-units = 1