@peac/cli 0.11.1 → 0.11.2

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/dist/index.cjs CHANGED
@@ -597,7 +597,8 @@ function computeCanonicalDigest(input) {
597
597
  const canonical = crypto.canonicalize(input);
598
598
  return { alg: "sha-256+jcs", value: sha256(canonical) };
599
599
  } catch {
600
- return { alg: "sha-256+json", value: sha256(JSON.stringify(input)) };
600
+ const serialized = JSON.stringify(input) ?? "null";
601
+ return { alg: "sha-256+json", value: sha256(serialized) };
601
602
  }
602
603
  }
603
604
  var VECTORS_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".json", ".txt", ".jwks", ".pem", ".zip"]);
@@ -748,6 +749,18 @@ var PROFILE_CAPABILITIES = {
748
749
  level: "shape",
749
750
  validator: "structural-check",
750
751
  notes: "Structure-only; no offer/receipt verification or term matching"
752
+ },
753
+ errors: {
754
+ profile: "errors.hints",
755
+ level: "semantic",
756
+ validator: "validateErrorHintsInput",
757
+ notes: "Validates next_action hint table shape and vocabulary (DD-132, DD-133)"
758
+ },
759
+ "content-usage": {
760
+ profile: "content-usage.parse",
761
+ level: "shape",
762
+ validator: "validateContentUsageInput",
763
+ notes: "Validates Content-Usage fixture input type; full parsing tested in dedicated suite"
751
764
  }
752
765
  };
753
766
  function getCategoryCapability(category) {
@@ -1034,6 +1047,68 @@ function validateIssueInput(input) {
1034
1047
  }
1035
1048
  return { valid: true };
1036
1049
  }
1050
+ var VALID_NEXT_ACTIONS = /* @__PURE__ */ new Set([
1051
+ "retry_after_delay",
1052
+ "retry_with_different_key",
1053
+ "retry_with_different_input",
1054
+ "refresh_attestation",
1055
+ "contact_issuer",
1056
+ "abort",
1057
+ "none"
1058
+ ]);
1059
+ function validateErrorHintsInput(input) {
1060
+ if (typeof input !== "object" || input === null) {
1061
+ return {
1062
+ valid: false,
1063
+ error_code: "E_INVALID_ERROR_HINTS",
1064
+ error_message: "Error hints input must be an object"
1065
+ };
1066
+ }
1067
+ const obj = input;
1068
+ if (!obj.hints || typeof obj.hints !== "object") {
1069
+ return {
1070
+ valid: false,
1071
+ error_code: "E_MISSING_HINTS",
1072
+ error_message: "Error hints missing required hints object"
1073
+ };
1074
+ }
1075
+ const hints = obj.hints;
1076
+ for (const [code, hint] of Object.entries(hints)) {
1077
+ if (typeof hint !== "object" || hint === null) {
1078
+ return {
1079
+ valid: false,
1080
+ error_code: "E_INVALID_HINT",
1081
+ error_message: `Hint for ${code} must be an object`
1082
+ };
1083
+ }
1084
+ const h = hint;
1085
+ if (!VALID_NEXT_ACTIONS.has(h.next_action)) {
1086
+ return {
1087
+ valid: false,
1088
+ error_code: "E_INVALID_NEXT_ACTION",
1089
+ error_message: `Hint for ${code} has invalid next_action: ${String(h.next_action)}`
1090
+ };
1091
+ }
1092
+ if (typeof h.retryable !== "boolean") {
1093
+ return {
1094
+ valid: false,
1095
+ error_code: "E_INVALID_RETRYABLE",
1096
+ error_message: `Hint for ${code} has non-boolean retryable: ${String(h.retryable)}`
1097
+ };
1098
+ }
1099
+ }
1100
+ return { valid: true };
1101
+ }
1102
+ function validateContentUsageInput(input) {
1103
+ if (typeof input === "string") {
1104
+ return { valid: true };
1105
+ }
1106
+ return {
1107
+ valid: false,
1108
+ error_code: "E_INVALID_CONTENT_USAGE",
1109
+ error_message: "Content-Usage input must be a string (HTTP header value)"
1110
+ };
1111
+ }
1037
1112
  var CATEGORY_VALIDATORS = {
1038
1113
  // Receipt claim validation
1039
1114
  valid: (input) => {
@@ -1070,7 +1145,9 @@ var CATEGORY_VALIDATORS = {
1070
1145
  return validateReceiptPayload(obj.payload ?? obj.claims ?? input);
1071
1146
  },
1072
1147
  workflow: validateWorkflowInput,
1073
- x402: validateX402Input
1148
+ x402: validateX402Input,
1149
+ errors: validateErrorHintsInput,
1150
+ "content-usage": validateContentUsageInput
1074
1151
  };
1075
1152
  function getValidator(category) {
1076
1153
  return CATEGORY_VALIDATORS[category] ?? ((input) => {
@@ -1169,8 +1246,22 @@ function runConformance(options, callbacks) {
1169
1246
  const f = pack.fixtures[i];
1170
1247
  const fixtureName = f.name ?? `fixture_${i}`;
1171
1248
  const testId = `${baseTestId}.${fixtureName.replace(/\s+/g, "_")}`;
1172
- const inputDigest = computeCanonicalDigest(f.input);
1173
1249
  callbacks?.onTestStart?.(testId);
1250
+ if (!f.expected || typeof f.expected.valid !== "boolean") {
1251
+ skipped++;
1252
+ const result2 = {
1253
+ id: testId,
1254
+ category: profile,
1255
+ status: "skip",
1256
+ diagnostics: {
1257
+ skip_reason: "Non-standard fixture format (domain-specific test suite)"
1258
+ }
1259
+ };
1260
+ results.push(result2);
1261
+ callbacks?.onTestComplete?.(result2);
1262
+ continue;
1263
+ }
1264
+ const inputDigest = computeCanonicalDigest(f.input);
1174
1265
  if (typeof f.input === "object" && f.input !== null) {
1175
1266
  const inputObj = f.input;
1176
1267
  if (inputObj.claims !== void 0 && inputObj.payload !== void 0) {