@callcium/sdk 0.1.0 → 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Provencraft
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # @callcium/sdk
2
+
3
+ TypeScript implementation of the Callcium policy engine.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ bun add @callcium/sdk
9
+ ```
10
+
11
+ ## Documentation
12
+
13
+ Full documentation at [callcium.dev/docs/sdk](https://callcium.dev/docs/sdk).
14
+
15
+ ## License
16
+
17
+ MIT License. See [LICENSE](LICENSE).
package/dist/index.d.ts CHANGED
@@ -29,17 +29,110 @@ type EnforceResult = {
29
29
  ok: false;
30
30
  violations: Violation[];
31
31
  };
32
- /** Machine-readable reason code for an enforcement violation. */
33
- type ViolationCode = "VALUE_MISMATCH" | "SELECTOR_MISMATCH" | "MISSING_SELECTOR" | "CALLDATA_OUT_OF_BOUNDS" | "ARRAY_INDEX_OUT_OF_BOUNDS" | "MISSING_CONTEXT" | "QUANTIFIER_LIMIT_EXCEEDED" | "QUANTIFIER_EMPTY_ARRAY";
34
- /** Details of a single rule failure during enforcement. */
35
- type Violation = {
36
- /** Group index that failed. Absent for pre-group failures (e.g. selector mismatch). */group?: number; /** Rule index within the group. Absent for pre-rule failures. */
37
- rule?: number;
38
- code: ViolationCode;
39
- message: string; /** Rule path that was being evaluated when the violation occurred. */
40
- path?: Hex; /** The actual value found in calldata or context, for diagnostic display. */
32
+ /** Subset of violation codes emitted by reader/navigation primitives. */
33
+ type NavigationViolationCode = "CALLDATA_OUT_OF_BOUNDS" | "ARRAY_INDEX_OUT_OF_BOUNDS";
34
+ /** Calldata is shorter than the policy's selector slot. */
35
+ type MissingSelectorViolation = {
36
+ code: "MISSING_SELECTOR";
37
+ };
38
+ /** Calldata selector does not match the policy's expected selector. */
39
+ type SelectorMismatchViolation = {
40
+ code: "SELECTOR_MISMATCH"; /** Selector declared by the policy. */
41
+ expectedValue: Hex; /** Selector observed in the calldata. */
42
+ resolvedValue: Hex;
43
+ };
44
+ /**
45
+ * A context-scoped rule referenced a property not supplied in the execution context.
46
+ *
47
+ * `opCode` and `operandData` may be added in future versions as diagnostic context
48
+ * without breaking the contract; consumers should tolerate their presence.
49
+ */
50
+ type MissingContextViolation = {
51
+ code: "MISSING_CONTEXT";
52
+ group: number;
53
+ rule: number;
54
+ scope: number;
55
+ path: Hex; /** Declared type of the missing context property. */
56
+ typeCode: number;
57
+ opCode?: number;
58
+ operandData?: Hex;
59
+ };
60
+ /**
61
+ * A rule's operator returned false against the loaded value.
62
+ *
63
+ * Field combinations:
64
+ * - `resolvedValue` present, `elementIndex` absent — scalar leaf or context value that failed the operator.
65
+ * - `resolvedValue` present, `elementIndex` present — universal-quantifier per-element failure.
66
+ * - `resolvedValue` absent, `elementIndex` absent — existential-aggregate failure (no element satisfied).
67
+ * - `resolvedValue` absent, `elementIndex` present — per-element failure where the leaf could not be loaded.
68
+ *
69
+ * For length operations (`isLengthOp(opCode)`), `resolvedValue` is a hex-encoded count
70
+ * rather than a 32-byte ABI word.
71
+ */
72
+ type ValueMismatchViolation = {
73
+ code: "VALUE_MISMATCH";
74
+ group: number;
75
+ rule: number;
76
+ scope: number;
77
+ path: Hex; /** Operator code with the `Op.NOT` bit intact. */
78
+ opCode: number; /** Full untruncated operand bytes declared by the rule. */
79
+ operandData: Hex; /** Type code of the failing value's leaf. */
80
+ typeCode: number;
41
81
  resolvedValue?: Hex;
82
+ elementIndex?: number;
83
+ };
84
+ /**
85
+ * Single-code shape for a calldata-navigation failure. Internal helper for de-duplication.
86
+ * @internal
87
+ */
88
+ type CalldataNavigationVariant<C extends NavigationViolationCode> = {
89
+ code: C;
90
+ group: number;
91
+ rule: number;
92
+ scope: number;
93
+ path: Hex;
94
+ opCode?: number;
95
+ operandData?: Hex;
96
+ typeCode?: number;
97
+ elementIndex?: number;
98
+ };
99
+ /**
100
+ * Calldata structure prevented the rule from being evaluated.
101
+ *
102
+ * The operator was never applied; `opCode`, `operandData`, `typeCode`, and `elementIndex`
103
+ * are diagnostic context describing the failing site, not a constraint claim. Renderers
104
+ * must not summarise these as "constraint violated".
105
+ *
106
+ * Encoded as a union of per-code variants so consumers can narrow on a single code via
107
+ * `Extract<Violation, { code: "..." }>`.
108
+ */
109
+ type CalldataNavigationViolation = CalldataNavigationVariant<"CALLDATA_OUT_OF_BOUNDS"> | CalldataNavigationVariant<"ARRAY_INDEX_OUT_OF_BOUNDS">;
110
+ /** A quantified array exceeded `Limits.MAX_QUANTIFIED_ARRAY_LENGTH`. */
111
+ type QuantifierLimitExceededViolation = {
112
+ code: "QUANTIFIER_LIMIT_EXCEEDED";
113
+ group: number;
114
+ rule: number;
115
+ scope: number;
116
+ path: Hex; /** Hex-encoded element count of the offending array. */
117
+ resolvedValue: Hex;
42
118
  };
119
+ /** A quantifier (`ANY` or `ALL`) was applied to an empty array. */
120
+ type QuantifierEmptyArrayViolation = {
121
+ code: "QUANTIFIER_EMPTY_ARRAY";
122
+ group: number;
123
+ rule: number;
124
+ scope: number;
125
+ path: Hex;
126
+ };
127
+ /**
128
+ * Structured details of a single rule failure during enforcement.
129
+ *
130
+ * Carries semantic data only — message strings are the consumer's responsibility.
131
+ * Discriminate on `code` to narrow to the matching variant.
132
+ */
133
+ type Violation = MissingSelectorViolation | SelectorMismatchViolation | MissingContextViolation | ValueMismatchViolation | CalldataNavigationViolation | QuantifierLimitExceededViolation | QuantifierEmptyArrayViolation;
134
+ /** Machine-readable reason code for an enforcement violation. Derived from `Violation` to prevent drift. */
135
+ type ViolationCode = Violation["code"];
43
136
  /** Canonical structured representation of a policy. */
44
137
  type PolicyData = {
45
138
  isSelectorless: boolean;
@@ -673,6 +766,10 @@ type TypeCodeInfo = TypeClassInfo & {
673
766
  */
674
767
  declare function lookupTypeCode(code: number): TypeCodeInfo;
675
768
  //#endregion
769
+ //#region src/operators.d.ts
770
+ /** Return true when the operator code (with or without NOT flag) is a LENGTH_* variant. */
771
+ declare function isLengthOp(opCode: number): boolean;
772
+ //#endregion
676
773
  //#region src/errors.d.ts
677
774
  /** Machine-readable error code for structural decoding and validation failures. */
678
775
  type CallciumErrorCode = "UNSUPPORTED_VERSION" | "MALFORMED_HEADER" | "UNEXPECTED_END" | "NODE_OVERFLOW" | "UNKNOWN_TYPE_CODE" | "INVALID_OPERATOR" | "INVALID_ARRAY_LENGTH" | "INVALID_TUPLE_FIELD_COUNT" | "PARAM_COUNT_MISMATCH" | "EMPTY_POLICY" | "EMPTY_GROUP" | "EMPTY_PATH" | "INVALID_CONTEXT_PATH" | "INVALID_CONTEXT_PROPERTY" | "INVALID_QUANTIFIER" | "INVALID_SCOPE" | "RULE_SIZE_MISMATCH" | "GROUP_SIZE_MISMATCH" | "GROUP_OVERFLOW" | "RULE_OVERFLOW" | "TRAILING_BYTES" | "INTERNAL_ERROR" | "INVALID_SIGNATURE" | "INVALID_TYPE_STRING" | "UNKNOWN_TYPE" | "DESCRIPTOR_TOO_LARGE" | "INVALID_PATH" | "DUPLICATE_PATH" | "INVALID_CONSTRAINT" | "INVALID_OPERATOR_DATA" | "EMPTY_SET" | "SET_TOO_LARGE" | "INVALID_RANGE" | "GROUP_COUNT_OVERFLOW" | "RULE_COUNT_OVERFLOW" | "RULE_SIZE_OVERFLOW" | "DESC_LENGTH_OVERFLOW" | "INVALID_HEX" | "VALIDATION_ERROR";
@@ -690,12 +787,16 @@ declare class CallciumError extends Error {
690
787
  * Thrown by `PolicyEnforcer.enforce` when calldata fails policy enforcement.
691
788
  * Distinct from `CallciumError("VALIDATION_ERROR")`, which signals static
692
789
  * issues in the policy itself.
693
- * Carries the full list of violations (one per failed group).
790
+ *
791
+ * Carries the full list of structured violations (one per failed group). The
792
+ * `Error.message` is a minimal non-lossy diagnostic summary built from the
793
+ * first violation's structured fields — not a presentation contract. Consumers
794
+ * rendering violations to users should iterate `violations` directly.
694
795
  */
695
796
  declare class PolicyViolationError extends Error {
696
797
  readonly violations: Violation[];
697
798
  constructor(violations: Violation[]);
698
799
  }
699
800
  //#endregion
700
- export { type Address, CallciumError, type CallciumErrorCode, type Constraint, type ConstraintBuilder, type Context, ContextProperty, type ContextPropertyInfo, type DecodedGroup, type DecodedParam, type DecodedPolicy, type DecodedRule, Descriptor, DescriptorCoder, type EnforceResult, type Field, type Hex, type Issue, type IssueCategory, type IssueSeverity, Limits, Op, type OpInfo, type Operands, PolicyBuilder, PolicyCoder, type PolicyData, PolicyEnforcer, PolicyValidator, PolicyViolationError, Quantifier, type QuantifierInfo, type ScalarValue, Scope, type ScopeInfo, type Span, type TypeClass, type TypeClassInfo, TypeCode, type TypeCodeInfo, type TypeInfo, type Violation, type ViolationCode, arg, blockNumber, blockTimestamp, bytesToHex, chainId, hexToBytes, isOpAllowed, isQuantifier, lookupContextProperty, lookupOp, lookupQuantifier, lookupScope, lookupTypeCode, msgSender, msgValue, parsePathSteps, toAddress, txOrigin };
801
+ export { type Address, CallciumError, type CallciumErrorCode, type CalldataNavigationViolation, type Constraint, type ConstraintBuilder, type Context, ContextProperty, type ContextPropertyInfo, type DecodedGroup, type DecodedParam, type DecodedPolicy, type DecodedRule, Descriptor, DescriptorCoder, type EnforceResult, type Field, type Hex, type Issue, type IssueCategory, type IssueSeverity, Limits, type MissingContextViolation, type MissingSelectorViolation, type NavigationViolationCode, Op, type OpInfo, type Operands, PolicyBuilder, PolicyCoder, type PolicyData, PolicyEnforcer, PolicyValidator, PolicyViolationError, Quantifier, type QuantifierEmptyArrayViolation, type QuantifierInfo, type QuantifierLimitExceededViolation, type ScalarValue, Scope, type ScopeInfo, type SelectorMismatchViolation, type Span, type TypeClass, type TypeClassInfo, TypeCode, type TypeCodeInfo, type TypeInfo, type ValueMismatchViolation, type Violation, type ViolationCode, arg, blockNumber, blockTimestamp, bytesToHex, chainId, hexToBytes, isLengthOp, isOpAllowed, isQuantifier, lookupContextProperty, lookupOp, lookupQuantifier, lookupScope, lookupTypeCode, msgSender, msgValue, parsePathSteps, toAddress, txOrigin };
701
802
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/constraint.ts","../src/policy-builder.ts","../src/policy-coder.ts","../src/descriptor.ts","../src/policy-validator.ts","../src/policy-enforcer.ts","../src/bytes.ts","../src/descriptor-coder.ts","../src/constants.ts","../src/errors.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/constraint.ts","../src/policy-builder.ts","../src/policy-coder.ts","../src/descriptor.ts","../src/policy-validator.ts","../src/policy-enforcer.ts","../src/bytes.ts","../src/descriptor-coder.ts","../src/constants.ts","../src/operators.ts","../src/errors.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -20,19 +20,27 @@ var CallciumError = class CallciumError extends Error {
20
20
  * Thrown by `PolicyEnforcer.enforce` when calldata fails policy enforcement.
21
21
  * Distinct from `CallciumError("VALIDATION_ERROR")`, which signals static
22
22
  * issues in the policy itself.
23
- * Carries the full list of violations (one per failed group).
23
+ *
24
+ * Carries the full list of structured violations (one per failed group). The
25
+ * `Error.message` is a minimal non-lossy diagnostic summary built from the
26
+ * first violation's structured fields — not a presentation contract. Consumers
27
+ * rendering violations to users should iterate `violations` directly.
24
28
  */
25
29
  var PolicyViolationError = class PolicyViolationError extends Error {
26
30
  violations;
27
31
  constructor(violations) {
28
- const first = violations[0];
29
- const msg = first ? `Policy violation: ${first.message}` : "Policy violation";
30
- super(msg);
32
+ super(formatDiagnostic(violations[0]));
31
33
  this.name = "PolicyViolationError";
32
34
  this.violations = violations;
33
35
  Object.setPrototypeOf(this, PolicyViolationError.prototype);
34
36
  }
35
37
  };
38
+ /** Build a stack-trace-friendly diagnostic line from a violation's code and coordinates. */
39
+ function formatDiagnostic(violation) {
40
+ if (!violation) return "Policy violation";
41
+ const location = "group" in violation ? ` at group ${violation.group} rule ${violation.rule}` : "";
42
+ return `Policy violation: ${violation.code}${location}`;
43
+ }
36
44
  //#endregion
37
45
  //#region src/bytes.ts
38
46
  /** Regex that matches a valid hex body (even number of hex chars). */
@@ -2707,11 +2715,11 @@ function locate(tree, callData, pathBytes, baseOffset) {
2707
2715
  for (let i = 0; i < paramIndex; i++) head += headContribution(tree[i]);
2708
2716
  let base = baseOffset;
2709
2717
  let node = tree[paramIndex];
2710
- for (let s = 1; s < stepCount; s++) {
2711
- const step = readStep(pathBytes, s);
2718
+ for (let stepIndex = 1; stepIndex < stepCount; stepIndex++) {
2719
+ const step = readStep(pathBytes, stepIndex);
2712
2720
  if (isQuantifier(step)) {
2713
- const remaining = pathBytes.subarray((s + 1) * 2);
2714
- for (let r = 0; r < remaining.length / 2; r++) if (isQuantifier(readStep(remaining, r))) throw new CallciumError("INVALID_QUANTIFIER", "Nested quantifiers are not supported.");
2721
+ const remaining = pathBytes.subarray((stepIndex + 1) * 2);
2722
+ for (let remainingStepIndex = 0; remainingStepIndex < remaining.length / 2; remainingStepIndex++) if (isQuantifier(readStep(remaining, remainingStepIndex))) throw new CallciumError("INVALID_QUANTIFIER", "Nested quantifiers are not supported.");
2715
2723
  return {
2716
2724
  ok: true,
2717
2725
  type: "quantifier",
@@ -2887,8 +2895,8 @@ function loadSlice(callData, location) {
2887
2895
  function descendPath(callData, location, pathBytes) {
2888
2896
  const stepCount = pathBytes.length / 2;
2889
2897
  let { head, base, node } = location;
2890
- for (let s = 0; s < stepCount; s++) {
2891
- const step = readStep(pathBytes, s);
2898
+ for (let stepIndex = 0; stepIndex < stepCount; stepIndex++) {
2899
+ const step = readStep(pathBytes, stepIndex);
2892
2900
  const result = descend(node, callData, head, base, step);
2893
2901
  if (result.type === "violation") return {
2894
2902
  ok: false,
@@ -2916,38 +2924,27 @@ function addressToBigInt(hex) {
2916
2924
  padded.set(bytes, 32 - bytes.length);
2917
2925
  return toBigInt(padded, 0);
2918
2926
  }
2919
- /** Format a bigint as a compact hex string without leading-zero padding. */
2920
- function compactHex(value) {
2921
- if (value === 0n) return "0x0";
2922
- return `0x${value.toString(16)}`;
2923
- }
2924
- /** Truncate a hex string to at most maxChars characters, adding ellipsis if needed. */
2925
- function truncateHexForMessage(hex, maxChars = 66) {
2926
- if (hex.length <= maxChars) return hex;
2927
- return `${hex.slice(0, maxChars - 1)}…`;
2928
- }
2929
- /** Format a decoded operand as decimal for length ops, otherwise compact hex. */
2930
- function formatOperandValue(value, opCode) {
2931
- return isLengthOp(opCode) ? value.toString(10) : compactHex(value);
2932
- }
2933
- /** Format the constraint (operator + operands) from a single lookupOp call. */
2934
- function formatConstraint(opCode, operandData) {
2935
- const negated = (opCode & Op.NOT) !== 0;
2936
- const { label, operands } = lookupOp(opCode);
2937
- const op = negated ? `not ${label}` : label;
2938
- let formattedOperands;
2939
- if (operands === "variadic") formattedOperands = `(${operandData.length / 32} values)`;
2940
- else if (operands === "range") {
2941
- const min = toBigInt(operandData, 0);
2942
- const max = toBigInt(operandData, 32);
2943
- formattedOperands = `[${formatOperandValue(min, opCode)}, ${formatOperandValue(max, opCode)}]`;
2944
- } else formattedOperands = formatOperandValue(toBigInt(operandData, 0), opCode);
2945
- return `${op} ${formattedOperands}`;
2946
- }
2947
- /** Build a self-contained VALUE_MISMATCH message for a scalar or length comparison. */
2948
- function mismatchMessage(opCode, actual, operandData) {
2949
- const display = typeof actual === "number" ? String(actual) : truncateHexForMessage(compactHex(actual));
2950
- return `constraint ${formatConstraint(opCode, operandData)} violated by ${display}`;
2927
+ /**
2928
+ * Walk a descriptor subtree through path steps and return the terminal leaf type code.
2929
+ *
2930
+ * Used only for violation metadata. Valid policies have structurally valid
2931
+ * quantifier suffixes (enforced by `PolicyValidator`); if a hand-crafted blob
2932
+ * violates that invariant, return the last resolvable node's type code as
2933
+ * best-effort diagnostic context.
2934
+ */
2935
+ function resolveLeafTypeCode(elementNode, remainingPath) {
2936
+ let node = elementNode;
2937
+ const stepCount = remainingPath.length / 2;
2938
+ for (let step = 0; step < stepCount; step++) {
2939
+ const childIndex = readU16(remainingPath, step * 2);
2940
+ if (node.type === "tuple") {
2941
+ const field = node.fields[childIndex];
2942
+ if (!field) break;
2943
+ node = field;
2944
+ } else if (node.type === "staticArray" || node.type === "dynamicArray") node = node.element;
2945
+ else break;
2946
+ }
2947
+ return node.typeCode;
2951
2948
  }
2952
2949
  /**
2953
2950
  * Check a policy against ABI-encoded call data without throwing on violations.
@@ -2963,10 +2960,7 @@ function check(policy, callData, context) {
2963
2960
  if (!decoded.isSelectorless) {
2964
2961
  if (callDataBytes.length < 4) return {
2965
2962
  ok: false,
2966
- violations: [{
2967
- code: "MISSING_SELECTOR",
2968
- message: "Calldata too short to contain a selector"
2969
- }]
2963
+ violations: [{ code: "MISSING_SELECTOR" }]
2970
2964
  };
2971
2965
  const expectedSelector = decoded.selector.value;
2972
2966
  const actualSelector = bytesToHex(callDataBytes.subarray(0, 4));
@@ -2974,8 +2968,8 @@ function check(policy, callData, context) {
2974
2968
  ok: false,
2975
2969
  violations: [{
2976
2970
  code: "SELECTOR_MISMATCH",
2977
- message: `Expected selector ${expectedSelector}, got ${actualSelector}`,
2978
- resolvedValue: actualSelector
2971
+ resolvedValue: actualSelector,
2972
+ expectedValue: expectedSelector
2979
2973
  }]
2980
2974
  };
2981
2975
  }
@@ -3028,8 +3022,10 @@ function evaluateRule(rule, tree, callDataBytes, baseOffset, groupIndex, ruleInd
3028
3022
  group: groupIndex,
3029
3023
  rule: ruleIndex,
3030
3024
  code: locResult.code,
3031
- message: `Navigation failed: ${locResult.code}`,
3032
- path: rule.path.value
3025
+ scope: Scope.CALLDATA,
3026
+ path: rule.path.value,
3027
+ opCode,
3028
+ operandData: rule.data.value
3033
3029
  };
3034
3030
  if (locResult.type === "quantifier") return evaluateQuantifier(locResult.quantifier, callDataBytes, opCode, operandData, groupIndex, ruleIndex, rule.path.value);
3035
3031
  return evaluateLeaf(locResult.location, callDataBytes, opCode, operandData, groupIndex, ruleIndex, rule.path.value);
@@ -3044,23 +3040,33 @@ function evaluateContextRule(pathBytes, opCode, operandData, groupIndex, ruleInd
3044
3040
  group: groupIndex,
3045
3041
  rule: ruleIndex,
3046
3042
  code: "MISSING_CONTEXT",
3047
- message: `Context property ${propInfo.label} not provided`,
3048
- path: pathHex
3043
+ scope: Scope.CONTEXT,
3044
+ path: pathHex,
3045
+ typeCode: propInfo.typeCode
3049
3046
  };
3050
3047
  let value;
3051
3048
  if (typeof contextValue === "string") value = addressToBigInt(contextValue);
3052
3049
  else value = contextValue;
3053
- if (!applyOperator(opCode, value, 32, operandData, TypeCode.UINT_MAX)) return {
3050
+ if (!applyOperator(opCode, value, 32, operandData, propInfo.typeCode)) return {
3054
3051
  group: groupIndex,
3055
3052
  rule: ruleIndex,
3056
3053
  code: "VALUE_MISMATCH",
3057
- message: mismatchMessage(opCode, value, operandData),
3054
+ scope: Scope.CONTEXT,
3058
3055
  path: pathHex,
3056
+ opCode,
3057
+ operandData: bytesToHex(operandData),
3058
+ typeCode: propInfo.typeCode,
3059
3059
  resolvedValue: bigintToHex(value)
3060
3060
  };
3061
3061
  return null;
3062
3062
  }
3063
- /** Load a value from calldata at the given location and apply the operator. */
3063
+ /**
3064
+ * Load a value from calldata at the given location and apply the operator.
3065
+ *
3066
+ * `resolvedValue` is normalised at the decision point: length operators encode
3067
+ * the byte/element count as a hex bigint; scalar operators preserve the full
3068
+ * 32-byte ABI word so downstream rendering can decode left-aligned `bytesN` faithfully.
3069
+ */
3064
3070
  function applyLeafOperator(callDataBytes, location, opCode, operandData) {
3065
3071
  const { node } = location;
3066
3072
  if (isLengthOp(opCode)) {
@@ -3072,61 +3078,68 @@ function applyLeafOperator(callDataBytes, location, opCode, operandData) {
3072
3078
  } else valueLength = node.staticSize;
3073
3079
  return {
3074
3080
  passed: applyOperator(opCode, 0n, valueLength, operandData, node.typeCode),
3075
- length: valueLength
3081
+ resolvedValue: bigintToHex(BigInt(valueLength))
3076
3082
  };
3077
3083
  }
3078
3084
  const result = loadScalar(callDataBytes, location);
3079
3085
  if (!result.ok) return { error: result.code };
3080
- const value = toBigInt(result.value, 0);
3081
3086
  return {
3082
- passed: applyOperator(opCode, value, 32, operandData, node.typeCode),
3083
- value
3087
+ passed: applyOperator(opCode, toBigInt(result.value, 0), 32, operandData, node.typeCode),
3088
+ resolvedValue: bytesToHex(result.value)
3084
3089
  };
3085
3090
  }
3086
3091
  /** Evaluate a leaf rule, producing a violation on failure or null on pass. */
3087
3092
  function evaluateLeaf(location, callDataBytes, opCode, operandData, groupIndex, ruleIndex, pathHex) {
3088
3093
  const result = applyLeafOperator(callDataBytes, location, opCode, operandData);
3089
- if ("error" in result) {
3090
- const message = isLengthOp(opCode) ? `Failed to read length: ${result.error}` : `Failed to load value: ${result.error}`;
3091
- return {
3092
- group: groupIndex,
3093
- rule: ruleIndex,
3094
- code: result.error,
3095
- message,
3096
- path: pathHex
3097
- };
3098
- }
3099
- if (!result.passed) {
3100
- const actual = result.value !== void 0 ? result.value : result.length ?? 0;
3101
- return {
3102
- group: groupIndex,
3103
- rule: ruleIndex,
3104
- code: "VALUE_MISMATCH",
3105
- message: mismatchMessage(opCode, actual, operandData),
3106
- path: pathHex,
3107
- resolvedValue: bigintToHex(typeof actual === "number" ? BigInt(actual) : actual)
3108
- };
3109
- }
3094
+ const typeCode = location.node.typeCode;
3095
+ if ("error" in result) return {
3096
+ group: groupIndex,
3097
+ rule: ruleIndex,
3098
+ code: result.error,
3099
+ scope: Scope.CALLDATA,
3100
+ path: pathHex,
3101
+ opCode,
3102
+ operandData: bytesToHex(operandData),
3103
+ typeCode
3104
+ };
3105
+ if (!result.passed) return {
3106
+ group: groupIndex,
3107
+ rule: ruleIndex,
3108
+ code: "VALUE_MISMATCH",
3109
+ scope: Scope.CALLDATA,
3110
+ path: pathHex,
3111
+ opCode,
3112
+ operandData: bytesToHex(operandData),
3113
+ typeCode,
3114
+ resolvedValue: result.resolvedValue
3115
+ };
3110
3116
  return null;
3111
3117
  }
3112
3118
  /** Evaluate a quantified rule by iterating over array elements with ALL/ANY semantics. */
3113
3119
  function evaluateQuantifier(qResult, callDataBytes, opCode, operandData, groupIndex, ruleIndex, pathHex) {
3114
3120
  const { quantifier, location: arrayLocation, remainingPath } = qResult;
3121
+ const operandHex = bytesToHex(operandData);
3122
+ const arrayNode = arrayLocation.node;
3123
+ const leafTypeCode = resolveLeafTypeCode(arrayNode.type === "staticArray" || arrayNode.type === "dynamicArray" ? arrayNode.element : arrayNode, remainingPath);
3115
3124
  const shapeResult = arrayShape(callDataBytes, arrayLocation);
3116
3125
  if (!shapeResult.ok) return {
3117
3126
  group: groupIndex,
3118
3127
  rule: ruleIndex,
3119
3128
  code: shapeResult.code,
3120
- message: `Failed to read array shape: ${shapeResult.code}`,
3121
- path: pathHex
3129
+ scope: Scope.CALLDATA,
3130
+ path: pathHex,
3131
+ opCode,
3132
+ operandData: operandHex,
3133
+ typeCode: leafTypeCode
3122
3134
  };
3123
3135
  const shape = shapeResult.shape;
3124
3136
  if (shape.length > Limits.MAX_QUANTIFIED_ARRAY_LENGTH) return {
3125
3137
  group: groupIndex,
3126
3138
  rule: ruleIndex,
3127
3139
  code: "QUANTIFIER_LIMIT_EXCEEDED",
3128
- message: `Array length ${shape.length} exceeds maximum ${Limits.MAX_QUANTIFIED_ARRAY_LENGTH}`,
3129
- path: pathHex
3140
+ scope: Scope.CALLDATA,
3141
+ path: pathHex,
3142
+ resolvedValue: bigintToHex(BigInt(shape.length))
3130
3143
  };
3131
3144
  if (shape.length === 0) {
3132
3145
  if (quantifier === Quantifier.ALL_OR_EMPTY) return null;
@@ -3134,7 +3147,7 @@ function evaluateQuantifier(qResult, callDataBytes, opCode, operandData, groupIn
3134
3147
  group: groupIndex,
3135
3148
  rule: ruleIndex,
3136
3149
  code: "QUANTIFIER_EMPTY_ARRAY",
3137
- message: "Quantifier applied to empty array",
3150
+ scope: Scope.CALLDATA,
3138
3151
  path: pathHex
3139
3152
  };
3140
3153
  }
@@ -3147,70 +3160,82 @@ function evaluateQuantifier(qResult, callDataBytes, opCode, operandData, groupIn
3147
3160
  group: groupIndex,
3148
3161
  rule: ruleIndex,
3149
3162
  code: elemResult.code,
3150
- message: `Quantifier element ${elemIndex}: ${elemResult.code}`,
3151
- path: pathHex
3163
+ scope: Scope.CALLDATA,
3164
+ path: pathHex,
3165
+ opCode,
3166
+ operandData: operandHex,
3167
+ typeCode: leafTypeCode,
3168
+ elementIndex: elemIndex
3152
3169
  };
3153
3170
  continue;
3154
3171
  }
3155
3172
  const elemLocation = elemResult.location;
3156
- let elemPassed;
3173
+ let leafLocation;
3157
3174
  if (hasSuffix) {
3158
- const leafResult = descendPath(callDataBytes, elemLocation, remainingPath);
3159
- if (!leafResult.ok) {
3160
- if (isUniversal) return {
3161
- group: groupIndex,
3162
- rule: ruleIndex,
3163
- code: leafResult.code,
3164
- message: `Quantifier element ${elemIndex} navigation failed: ${leafResult.code}`,
3165
- path: pathHex
3166
- };
3167
- continue;
3168
- }
3169
- elemPassed = evaluateLeafValue(leafResult.location, callDataBytes, opCode, operandData);
3170
- } else {
3171
- const leafResult = applyLeafOperator(callDataBytes, elemLocation, opCode, operandData);
3172
- if ("error" in leafResult) {
3175
+ const navResult = descendPath(callDataBytes, elemLocation, remainingPath);
3176
+ if (!navResult.ok) {
3173
3177
  if (isUniversal) return {
3174
3178
  group: groupIndex,
3175
3179
  rule: ruleIndex,
3176
- code: leafResult.error,
3177
- message: `Quantifier element ${elemIndex}: ${leafResult.error}`,
3178
- path: pathHex
3180
+ code: navResult.code,
3181
+ scope: Scope.CALLDATA,
3182
+ path: pathHex,
3183
+ opCode,
3184
+ operandData: operandHex,
3185
+ typeCode: leafTypeCode,
3186
+ elementIndex: elemIndex
3179
3187
  };
3180
3188
  continue;
3181
3189
  }
3182
- elemPassed = leafResult.passed;
3190
+ leafLocation = navResult.location;
3191
+ } else leafLocation = elemLocation;
3192
+ const applied = applyLeafOperator(callDataBytes, leafLocation, opCode, operandData);
3193
+ if ("error" in applied) {
3194
+ if (isUniversal) return {
3195
+ group: groupIndex,
3196
+ rule: ruleIndex,
3197
+ code: applied.error,
3198
+ scope: Scope.CALLDATA,
3199
+ path: pathHex,
3200
+ opCode,
3201
+ operandData: operandHex,
3202
+ typeCode: leafTypeCode,
3203
+ elementIndex: elemIndex
3204
+ };
3205
+ continue;
3183
3206
  }
3184
- if (isUniversal && !elemPassed) return {
3207
+ if (isUniversal && !applied.passed) return {
3185
3208
  group: groupIndex,
3186
3209
  rule: ruleIndex,
3187
3210
  code: "VALUE_MISMATCH",
3188
- message: `constraint ${formatConstraint(opCode, operandData)} violated at element ${elemIndex}`,
3189
- path: pathHex
3211
+ scope: Scope.CALLDATA,
3212
+ path: pathHex,
3213
+ opCode,
3214
+ operandData: operandHex,
3215
+ typeCode: leafTypeCode,
3216
+ resolvedValue: applied.resolvedValue,
3217
+ elementIndex: elemIndex
3190
3218
  };
3191
- if (!isUniversal && elemPassed) return null;
3219
+ if (!isUniversal && applied.passed) return null;
3192
3220
  }
3193
3221
  if (isUniversal) return null;
3194
3222
  return {
3195
3223
  group: groupIndex,
3196
3224
  rule: ruleIndex,
3197
3225
  code: "VALUE_MISMATCH",
3198
- message: `constraint ${formatConstraint(opCode, operandData)} violated by all elements`,
3199
- path: pathHex
3226
+ scope: Scope.CALLDATA,
3227
+ path: pathHex,
3228
+ opCode,
3229
+ operandData: operandHex,
3230
+ typeCode: leafTypeCode
3200
3231
  };
3201
3232
  }
3202
- /** Apply a leaf operator and return a boolean. Returns false on calldata read failure. */
3203
- function evaluateLeafValue(location, callDataBytes, opCode, operandData) {
3204
- const result = applyLeafOperator(callDataBytes, location, opCode, operandData);
3205
- if ("error" in result) return false;
3206
- return result.passed;
3207
- }
3208
3233
  /** Check and enforce policies against ABI-encoded call data. */
3209
3234
  const PolicyEnforcer = {
3210
3235
  check,
3211
3236
  enforce
3212
3237
  };
3213
3238
  //#endregion
3214
- export { CallciumError, ContextProperty, Descriptor, DescriptorCoder, Limits, Op, PolicyBuilder, PolicyCoder, PolicyEnforcer, PolicyValidator, PolicyViolationError, Quantifier, Scope, TypeCode, arg, blockNumber, blockTimestamp, bytesToHex, chainId, hexToBytes, isOpAllowed, isQuantifier, lookupContextProperty, lookupOp, lookupQuantifier, lookupScope, lookupTypeCode, msgSender, msgValue, parsePathSteps, toAddress, txOrigin };
3239
+ export { CallciumError, ContextProperty, Descriptor, DescriptorCoder, Limits, Op, PolicyBuilder, PolicyCoder, PolicyEnforcer, PolicyValidator, PolicyViolationError, Quantifier, Scope, TypeCode, arg, blockNumber, blockTimestamp, bytesToHex, chainId, hexToBytes, isLengthOp, isOpAllowed, isQuantifier, lookupContextProperty, lookupOp, lookupQuantifier, lookupScope, lookupTypeCode, msgSender, msgValue, parsePathSteps, toAddress, txOrigin };
3215
3240
 
3216
3241
  //# sourceMappingURL=index.js.map