@peac/cli 0.11.0 → 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.mjs CHANGED
@@ -576,7 +576,8 @@ function computeCanonicalDigest(input) {
576
576
  const canonical = canonicalize(input);
577
577
  return { alg: "sha-256+jcs", value: sha256(canonical) };
578
578
  } catch {
579
- return { alg: "sha-256+json", value: sha256(JSON.stringify(input)) };
579
+ const serialized = JSON.stringify(input) ?? "null";
580
+ return { alg: "sha-256+json", value: sha256(serialized) };
580
581
  }
581
582
  }
582
583
  var VECTORS_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".json", ".txt", ".jwks", ".pem", ".zip"]);
@@ -727,6 +728,18 @@ var PROFILE_CAPABILITIES = {
727
728
  level: "shape",
728
729
  validator: "structural-check",
729
730
  notes: "Structure-only; no offer/receipt verification or term matching"
731
+ },
732
+ errors: {
733
+ profile: "errors.hints",
734
+ level: "semantic",
735
+ validator: "validateErrorHintsInput",
736
+ notes: "Validates next_action hint table shape and vocabulary (DD-132, DD-133)"
737
+ },
738
+ "content-usage": {
739
+ profile: "content-usage.parse",
740
+ level: "shape",
741
+ validator: "validateContentUsageInput",
742
+ notes: "Validates Content-Usage fixture input type; full parsing tested in dedicated suite"
730
743
  }
731
744
  };
732
745
  function getCategoryCapability(category) {
@@ -1013,6 +1026,68 @@ function validateIssueInput(input) {
1013
1026
  }
1014
1027
  return { valid: true };
1015
1028
  }
1029
+ var VALID_NEXT_ACTIONS = /* @__PURE__ */ new Set([
1030
+ "retry_after_delay",
1031
+ "retry_with_different_key",
1032
+ "retry_with_different_input",
1033
+ "refresh_attestation",
1034
+ "contact_issuer",
1035
+ "abort",
1036
+ "none"
1037
+ ]);
1038
+ function validateErrorHintsInput(input) {
1039
+ if (typeof input !== "object" || input === null) {
1040
+ return {
1041
+ valid: false,
1042
+ error_code: "E_INVALID_ERROR_HINTS",
1043
+ error_message: "Error hints input must be an object"
1044
+ };
1045
+ }
1046
+ const obj = input;
1047
+ if (!obj.hints || typeof obj.hints !== "object") {
1048
+ return {
1049
+ valid: false,
1050
+ error_code: "E_MISSING_HINTS",
1051
+ error_message: "Error hints missing required hints object"
1052
+ };
1053
+ }
1054
+ const hints = obj.hints;
1055
+ for (const [code, hint] of Object.entries(hints)) {
1056
+ if (typeof hint !== "object" || hint === null) {
1057
+ return {
1058
+ valid: false,
1059
+ error_code: "E_INVALID_HINT",
1060
+ error_message: `Hint for ${code} must be an object`
1061
+ };
1062
+ }
1063
+ const h = hint;
1064
+ if (!VALID_NEXT_ACTIONS.has(h.next_action)) {
1065
+ return {
1066
+ valid: false,
1067
+ error_code: "E_INVALID_NEXT_ACTION",
1068
+ error_message: `Hint for ${code} has invalid next_action: ${String(h.next_action)}`
1069
+ };
1070
+ }
1071
+ if (typeof h.retryable !== "boolean") {
1072
+ return {
1073
+ valid: false,
1074
+ error_code: "E_INVALID_RETRYABLE",
1075
+ error_message: `Hint for ${code} has non-boolean retryable: ${String(h.retryable)}`
1076
+ };
1077
+ }
1078
+ }
1079
+ return { valid: true };
1080
+ }
1081
+ function validateContentUsageInput(input) {
1082
+ if (typeof input === "string") {
1083
+ return { valid: true };
1084
+ }
1085
+ return {
1086
+ valid: false,
1087
+ error_code: "E_INVALID_CONTENT_USAGE",
1088
+ error_message: "Content-Usage input must be a string (HTTP header value)"
1089
+ };
1090
+ }
1016
1091
  var CATEGORY_VALIDATORS = {
1017
1092
  // Receipt claim validation
1018
1093
  valid: (input) => {
@@ -1049,7 +1124,9 @@ var CATEGORY_VALIDATORS = {
1049
1124
  return validateReceiptPayload(obj.payload ?? obj.claims ?? input);
1050
1125
  },
1051
1126
  workflow: validateWorkflowInput,
1052
- x402: validateX402Input
1127
+ x402: validateX402Input,
1128
+ errors: validateErrorHintsInput,
1129
+ "content-usage": validateContentUsageInput
1053
1130
  };
1054
1131
  function getValidator(category) {
1055
1132
  return CATEGORY_VALIDATORS[category] ?? ((input) => {
@@ -1148,8 +1225,22 @@ function runConformance(options, callbacks) {
1148
1225
  const f = pack.fixtures[i];
1149
1226
  const fixtureName = f.name ?? `fixture_${i}`;
1150
1227
  const testId = `${baseTestId}.${fixtureName.replace(/\s+/g, "_")}`;
1151
- const inputDigest = computeCanonicalDigest(f.input);
1152
1228
  callbacks?.onTestStart?.(testId);
1229
+ if (!f.expected || typeof f.expected.valid !== "boolean") {
1230
+ skipped++;
1231
+ const result2 = {
1232
+ id: testId,
1233
+ category: profile,
1234
+ status: "skip",
1235
+ diagnostics: {
1236
+ skip_reason: "Non-standard fixture format (domain-specific test suite)"
1237
+ }
1238
+ };
1239
+ results.push(result2);
1240
+ callbacks?.onTestComplete?.(result2);
1241
+ continue;
1242
+ }
1243
+ const inputDigest = computeCanonicalDigest(f.input);
1153
1244
  if (typeof f.input === "object" && f.input !== null) {
1154
1245
  const inputObj = f.input;
1155
1246
  if (inputObj.claims !== void 0 && inputObj.payload !== void 0) {