@peac/protocol 0.12.0-preview.2 → 0.12.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/README.md +25 -13
- package/dist/index.cjs +7 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +7 -4
- package/dist/index.mjs.map +1 -1
- package/dist/issue.d.ts +36 -12
- package/dist/issue.d.ts.map +1 -1
- package/dist/verify-local.cjs +1 -1
- package/dist/verify-local.cjs.map +1 -1
- package/dist/verify-local.d.ts +1 -1
- package/dist/verify-local.mjs +1 -1
- package/dist/verify-local.mjs.map +1 -1
- package/dist/verify.d.ts +11 -4
- package/dist/verify.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/issue.d.ts
CHANGED
|
@@ -6,9 +6,12 @@ import type { JsonValue, EvidencePillar, PolicyBlock } from '@peac/kernel';
|
|
|
6
6
|
import { PEACReceiptClaims, SubjectProfileSnapshot, type PEACError, type PurposeToken, type CanonicalPurpose, type PurposeReason, type WorkflowContext } from '@peac/schema';
|
|
7
7
|
import { type TelemetryHook } from './telemetry.js';
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Wire 0.1 receipt options (frozen legacy).
|
|
10
|
+
*
|
|
11
|
+
* @deprecated Use {@link IssueWire02Options} (or the {@link IssueOptions} alias)
|
|
12
|
+
* for current stable issuance.
|
|
10
13
|
*/
|
|
11
|
-
export interface
|
|
14
|
+
export interface IssueWire01Options {
|
|
12
15
|
/** Issuer URL (https://) */
|
|
13
16
|
iss: string;
|
|
14
17
|
/** Audience / resource URL (https://) */
|
|
@@ -99,24 +102,35 @@ export declare class IssueError extends Error {
|
|
|
99
102
|
/**
|
|
100
103
|
* Issue a Wire 0.1 PEAC receipt.
|
|
101
104
|
*
|
|
102
|
-
* @deprecated
|
|
103
|
-
*
|
|
105
|
+
* @deprecated Wire 0.1 issuance is frozen legacy. Use {@link issue} (current stable format)
|
|
106
|
+
* or {@link issueWire02} (explicit wire-pinned API) for Wire 0.2 receipts.
|
|
104
107
|
*
|
|
105
|
-
* @param options -
|
|
108
|
+
* @param options - Wire 0.1 receipt options
|
|
106
109
|
* @returns Issue result with JWS and optional subject_snapshot
|
|
107
110
|
* @throws IssueError if evidence contains non-JSON-safe values
|
|
108
111
|
*/
|
|
109
|
-
export declare function
|
|
112
|
+
export declare function issueWire01(options: IssueWire01Options): Promise<IssueResult>;
|
|
110
113
|
/**
|
|
111
|
-
* Issue a PEAC receipt and return just the JWS string
|
|
114
|
+
* Issue a Wire 0.1 PEAC receipt and return just the JWS string
|
|
112
115
|
*
|
|
113
|
-
*
|
|
114
|
-
* For access to validated subject_snapshot, use issue() instead.
|
|
116
|
+
* @deprecated Wire 0.1 issuance is frozen legacy. Use {@link issue} for the current stable format.
|
|
115
117
|
*
|
|
116
|
-
* @param options -
|
|
118
|
+
* @param options - Wire 0.1 receipt options
|
|
117
119
|
* @returns JWS compact serialization
|
|
118
120
|
*/
|
|
119
|
-
export declare function issueJws(options:
|
|
121
|
+
export declare function issueJws(options: IssueWire01Options): Promise<string>;
|
|
122
|
+
/**
|
|
123
|
+
* Issue a PEAC receipt in the current stable public format.
|
|
124
|
+
*
|
|
125
|
+
* This is the canonical public issuance API. It issues Wire 0.2 receipts
|
|
126
|
+
* (`typ: interaction-record+jwt`). For an explicit wire-pinned API, use
|
|
127
|
+
* {@link issueWire02} directly.
|
|
128
|
+
*
|
|
129
|
+
* @param options - Receipt options (same as {@link IssueWire02Options})
|
|
130
|
+
* @returns Issue result with JWS
|
|
131
|
+
* @throws IssueError if iss is not canonical or schema validation fails
|
|
132
|
+
*/
|
|
133
|
+
export declare function issue(options: IssueWire02Options): Promise<IssueResult>;
|
|
120
134
|
/**
|
|
121
135
|
* Options for issuing a Wire 0.2 receipt
|
|
122
136
|
*/
|
|
@@ -166,7 +180,17 @@ export interface IssueWire02Options {
|
|
|
166
180
|
extensions?: Record<string, unknown>;
|
|
167
181
|
}
|
|
168
182
|
/**
|
|
169
|
-
*
|
|
183
|
+
* Canonical issuance options type.
|
|
184
|
+
*
|
|
185
|
+
* Alias for {@link IssueWire02Options}: the current stable receipt format.
|
|
186
|
+
*/
|
|
187
|
+
export type IssueOptions = IssueWire02Options;
|
|
188
|
+
/**
|
|
189
|
+
* Issue a Wire 0.2 receipt (explicit wire-pinned API).
|
|
190
|
+
*
|
|
191
|
+
* Most callers should use {@link issue} instead, which delegates here.
|
|
192
|
+
* Use `issueWire02` directly for conformance tests, benchmarks, and
|
|
193
|
+
* callers that need explicit wire version pinning.
|
|
170
194
|
*
|
|
171
195
|
* Validates the iss canonical form and Wire02ClaimsSchema before signing.
|
|
172
196
|
* Always sets typ to 'interaction-record+jwt' (WIRE_02_JWS_TYP).
|
package/dist/issue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../src/issue.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3E,OAAO,EACL,iBAAiB,EAEjB,sBAAsB,EAOtB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAKlB,KAAK,eAAe,EAQrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAkC,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpF
|
|
1
|
+
{"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../src/issue.ts"],"names":[],"mappings":"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"}
|
package/dist/verify-local.cjs
CHANGED
|
@@ -165,7 +165,7 @@ async function verifyLocal(jws, publicKey, options = {}) {
|
|
|
165
165
|
return {
|
|
166
166
|
valid: false,
|
|
167
167
|
code: "E_UNSUPPORTED_WIRE_VERSION",
|
|
168
|
-
message: "Wire 0.1 receipts are not supported. Re-issue as Wire 0.2 using
|
|
168
|
+
message: "Wire 0.1 receipts are not supported. Re-issue as Wire 0.2 using issue()."
|
|
169
169
|
};
|
|
170
170
|
} catch (err) {
|
|
171
171
|
if (isCryptoError(err)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/verify-local.ts"],"names":["jwsVerify","WARNING_TYP_MISSING","validateKernelConstraints","parseReceiptClaims","checkOccurredAtSkew","REGISTERED_RECEIPT_TYPES","WARNING_TYPE_UNREGISTERED","REGISTERED_EXTENSION_GROUP_KEYS","isValidExtensionKey","WARNING_UNKNOWN_EXTENSION","HASH","verifyPolicyBinding","sortWarnings"],"mappings":"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","file":"verify-local.cjs","sourcesContent":["/**\n * Local receipt verification with schema validation\n *\n * Use this for verifying receipts when you have the public key locally,\n * without JWKS discovery.\n */\n\nimport { verify as jwsVerify } from '@peac/crypto';\nimport { type VerificationStrictness, type VerificationWarning, HASH } from '@peac/kernel';\nimport {\n parseReceiptClaims,\n validateKernelConstraints,\n type Wire02Claims,\n checkOccurredAtSkew,\n sortWarnings,\n WARNING_TYP_MISSING,\n WARNING_TYPE_UNREGISTERED,\n WARNING_UNKNOWN_EXTENSION,\n REGISTERED_RECEIPT_TYPES,\n REGISTERED_EXTENSION_GROUP_KEYS,\n isValidExtensionKey,\n verifyPolicyBinding,\n} from '@peac/schema';\nimport type { PolicyBindingStatus } from './verifier-types';\n\n/**\n * Structural type for CryptoError\n * Used instead of instanceof for robustness across ESM/CJS boundaries\n */\ninterface CryptoErrorLike {\n name: 'CryptoError';\n code: string;\n message: string;\n}\n\n/**\n * Structural check for CryptoError\n * More robust than instanceof across module boundaries (ESM/CJS, duplicate packages)\n */\nfunction isCryptoError(err: unknown): err is CryptoErrorLike {\n return (\n err !== null &&\n typeof err === 'object' &&\n 'name' in err &&\n err.name === 'CryptoError' &&\n 'code' in err &&\n typeof err.code === 'string' &&\n err.code.startsWith('CRYPTO_') &&\n 'message' in err &&\n typeof err.message === 'string'\n );\n}\n\n/**\n * Canonical error codes for local verification\n *\n * These map to E_* codes in specs/kernel/errors.json.\n * JOSE hardening codes (E_JWS_*) are distinct from generic E_INVALID_FORMAT\n * so callers can distinguish key-injection, compression, and crit attacks from\n * ordinary format errors (v0.12.0-preview.1, DD-156).\n */\nexport type VerifyLocalErrorCode =\n | 'E_INVALID_SIGNATURE'\n | 'E_INVALID_FORMAT'\n | 'E_CONSTRAINT_VIOLATION'\n | 'E_EXPIRED'\n | 'E_NOT_YET_VALID'\n | 'E_INVALID_ISSUER'\n | 'E_INVALID_AUDIENCE'\n | 'E_INVALID_SUBJECT'\n | 'E_INVALID_RECEIPT_ID'\n | 'E_MISSING_EXP'\n | 'E_WIRE_VERSION_MISMATCH'\n | 'E_UNSUPPORTED_WIRE_VERSION'\n | 'E_OCCURRED_AT_FUTURE'\n // JOSE hardening codes (Wire 0.2, v0.12.0-preview.1, DD-156)\n | 'E_JWS_EMBEDDED_KEY'\n | 'E_JWS_CRIT_REJECTED'\n | 'E_JWS_MISSING_KID'\n | 'E_JWS_B64_REJECTED'\n | 'E_JWS_ZIP_REJECTED'\n // Policy binding (Wire 0.2, v0.12.0-preview.1, DD-151)\n | 'E_POLICY_BINDING_FAILED'\n | 'E_INTERNAL';\n\n/**\n * Options for local verification\n */\nexport interface VerifyLocalOptions {\n /**\n * Expected issuer URL\n *\n * If provided, verification fails if receipt.iss does not match.\n */\n issuer?: string;\n\n /**\n * @deprecated Wire 0.2 does not have an `aud` claim. This option is ignored.\n * Retained for source compatibility during migration; will be removed in v1.0.\n */\n audience?: string;\n\n /**\n * Expected subject URI\n *\n * If provided, verification fails if receipt.sub does not match.\n * Binds the receipt to a specific resource/interaction target.\n */\n subjectUri?: string;\n\n /**\n * @deprecated Wire 0.2 does not have a `rid` claim. Use `jti` for receipt identification.\n * This option is ignored. Retained for source compatibility; will be removed in v1.0.\n */\n rid?: string;\n\n /**\n * @deprecated Wire 0.2 receipts do not expire (permanent evidence by design).\n * This option is ignored. Retained for source compatibility; will be removed in v1.0.\n */\n requireExp?: boolean;\n\n /**\n * Current timestamp (Unix seconds)\n *\n * Defaults to Date.now() / 1000. Override for testing.\n */\n now?: number;\n\n /**\n * Maximum clock skew tolerance (seconds)\n *\n * Allows for clock drift between issuer and verifier.\n * Defaults to 300 (5 minutes).\n */\n maxClockSkew?: number;\n\n /**\n * Verification strictness profile (v0.12.0-preview.1, DD-156).\n *\n * - 'strict' (default): missing typ is a hard error before schema validation.\n * - 'interop': missing typ emits a 'typ_missing' warning and routes by payload content.\n *\n * Strictness is EXCLUSIVELY controlled here (@peac/protocol). @peac/crypto has no strictness param.\n */\n strictness?: VerificationStrictness;\n\n /**\n * Pre-computed local policy digest for policy binding (Wire 0.2, v0.12.0-preview.1, DD-151).\n *\n * Must be in 'sha256:<64 lowercase hex>' format, computed via computePolicyDigestJcs()\n * from @peac/protocol. When provided alongside a receipt that contains a policy block\n * (policy.digest), the binding check is performed:\n * - Match: policy_binding = 'verified'\n * - Mismatch: hard fail with E_POLICY_BINDING_FAILED\n * - Either absent: policy_binding = 'unavailable'\n *\n * Always 'unavailable' for Wire 0.1 receipts regardless of this option.\n */\n policyDigest?: string;\n}\n\n/**\n * Result of successful local verification (Wire 0.2 only)\n *\n * Wire 0.1 receipts are no longer accepted by verifyLocal() and return\n * E_UNSUPPORTED_WIRE_VERSION. Re-issue as Wire 0.2 using issueWire02().\n */\nexport interface VerifyLocalSuccess {\n /** Verification succeeded */\n valid: true;\n /** Receipt variant (always 'wire-02') */\n variant: 'wire-02';\n /** Validated Wire 0.2 receipt claims */\n claims: Wire02Claims;\n /** Key ID from JWS header (for logging/indexing) */\n kid: string;\n /** Wire format version */\n wireVersion: '0.2';\n /** Verification warnings from schema parsing and strictness routing */\n warnings: VerificationWarning[];\n /**\n * Policy binding status (DD-49, DD-151).\n *\n * Three-state result:\n * - 'unavailable': either the receipt contains no policy block, or the\n * caller did not pass a policyDigest option to verifyLocal(). No check.\n * - 'verified': both digests present and match exactly.\n * - 'failed': not returned on success; verifyLocal() returns\n * E_POLICY_BINDING_FAILED (valid: false) before reaching this field.\n */\n policy_binding: PolicyBindingStatus;\n}\n\n/**\n * Result of failed local verification\n */\nexport interface VerifyLocalFailure {\n /** Verification failed */\n valid: false;\n\n /** Canonical error code (maps to specs/kernel/errors.json) */\n code: VerifyLocalErrorCode;\n\n /** Human-readable error message */\n message: string;\n\n /** Structured details for debugging (stable error code preserved in `code`) */\n details?: {\n /** Precise parse error code from unified parser (e.g. E_PARSE_COMMERCE_INVALID) */\n parse_code?: string;\n /** Zod validation issues (bounded, stable shape; non-normative, may change) */\n issues?: ReadonlyArray<{ path: string; message: string }>;\n /**\n * Policy digest from the receipt (present when code is E_POLICY_BINDING_FAILED).\n * Both are SHA-256 hashes; safe to log without leaking policy content.\n */\n receipt_policy_digest?: string;\n /** Caller-supplied policy digest (present when code is E_POLICY_BINDING_FAILED). */\n local_policy_digest?: string;\n /** policy.uri hint from the receipt (present when code is E_POLICY_BINDING_FAILED and uri set). */\n policy_uri?: string;\n };\n}\n\n/**\n * Union type for local verification result\n */\nexport type VerifyLocalResult = VerifyLocalSuccess | VerifyLocalFailure;\n\n/**\n * Internal CRYPTO_* codes that map to generic E_INVALID_FORMAT.\n * These are format/encoding errors not security-specific.\n */\nconst FORMAT_ERROR_CODES = new Set([\n 'CRYPTO_INVALID_JWS_FORMAT',\n 'CRYPTO_INVALID_TYP',\n 'CRYPTO_INVALID_ALG',\n 'CRYPTO_INVALID_KEY_LENGTH',\n]);\n\n/**\n * JOSE hardening code mapping: CRYPTO_JWS_* → specific E_JWS_* (v0.12.0-preview.1, DD-156).\n *\n * Each JOSE hazard code maps to its specific public E_JWS_* counterpart rather than\n * collapsing into the generic E_INVALID_FORMAT. This lets callers distinguish embedded-key\n * injection, crit-header abuse, and unencoded-payload attacks from ordinary format errors.\n */\nconst JOSE_CODE_MAP: Record<string, VerifyLocalErrorCode> = {\n CRYPTO_JWS_EMBEDDED_KEY: 'E_JWS_EMBEDDED_KEY',\n CRYPTO_JWS_CRIT_REJECTED: 'E_JWS_CRIT_REJECTED',\n CRYPTO_JWS_MISSING_KID: 'E_JWS_MISSING_KID',\n CRYPTO_JWS_B64_REJECTED: 'E_JWS_B64_REJECTED',\n CRYPTO_JWS_ZIP_REJECTED: 'E_JWS_ZIP_REJECTED',\n};\n\n/** Max parse issues to include in details (prevents log bloat) */\nconst MAX_PARSE_ISSUES = 25;\n\n/**\n * Sanitize Zod issues into a bounded, stable structure.\n * Avoids exposing raw Zod internals or unbounded arrays in the public API.\n */\nfunction sanitizeParseIssues(\n issues: unknown\n): ReadonlyArray<{ path: string; message: string }> | undefined {\n if (!Array.isArray(issues)) return undefined;\n return issues.slice(0, MAX_PARSE_ISSUES).map((issue) => ({\n path: Array.isArray(issue?.path) ? issue.path.join('.') : '',\n message: typeof issue?.message === 'string' ? issue.message : String(issue),\n }));\n}\n\n/**\n * Verify a Wire 0.2 PEAC receipt locally with a known public key.\n *\n * Wire 0.2 only: Wire 0.1 receipts return E_UNSUPPORTED_WIRE_VERSION.\n * Re-issue Wire 0.1 receipts as Wire 0.2 using issueWire02().\n *\n * This function:\n * 1. Verifies the Ed25519 signature and header (typ, alg)\n * 2. Applies strictness routing for missing typ (strict: hard error; interop: warning)\n * 3. Validates the receipt schema with Zod (Wire 0.2 only)\n * 4. Checks issuer/subject binding (if options provided)\n * 5. Checks time validity (iat with clock skew tolerance)\n * 6. Checks occurred_at skew and collects parse warnings\n *\n * @param jws - JWS compact serialization\n * @param publicKey - Ed25519 public key (32 bytes)\n * @param options - Optional verification options (issuer, subject, clock skew, strictness, policyDigest)\n * @returns Typed verification result\n *\n * @example\n * ```typescript\n * const result = await verifyLocal(jws, publicKey, {\n * issuer: 'https://api.example.com',\n * strictness: 'strict',\n * });\n * if (result.valid) {\n * console.log('Kind:', result.claims.kind);\n * console.log('Warnings:', result.warnings);\n * }\n * ```\n */\nexport async function verifyLocal(\n jws: string,\n publicKey: Uint8Array,\n options: VerifyLocalOptions = {}\n): Promise<VerifyLocalResult> {\n const { issuer, subjectUri, maxClockSkew = 300, strictness = 'strict', policyDigest } = options;\n const now = options.now ?? Math.floor(Date.now() / 1000);\n\n try {\n // 1. Verify signature and header (typ, alg validated by @peac/crypto)\n const result = await jwsVerify<unknown>(jws, publicKey);\n\n if (!result.valid) {\n return {\n valid: false,\n code: 'E_INVALID_SIGNATURE',\n message: 'Ed25519 signature verification failed',\n };\n }\n\n // Accumulated warnings for Wire 0.2 path\n const accumulatedWarnings: VerificationWarning[] = [];\n\n // 2. Strictness routing for missing typ (Correction 1, DD-156)\n if (result.header.typ === undefined) {\n if (strictness === 'strict') {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: 'Missing JWS typ header: strict mode requires typ to be present',\n };\n }\n // interop mode: emit warning and continue\n accumulatedWarnings.push({\n code: WARNING_TYP_MISSING,\n message: 'JWS typ header is absent; accepted in interop mode',\n });\n }\n\n // 3. Validate structural kernel constraints (DD-121, fail-closed)\n const constraintResult = validateKernelConstraints(result.payload);\n if (!constraintResult.valid) {\n const v = constraintResult.violations[0];\n return {\n valid: false,\n code: 'E_CONSTRAINT_VIOLATION',\n message: `Kernel constraint violated: ${v.constraint} (actual: ${v.actual}, limit: ${v.limit})`,\n };\n }\n\n // 4. Validate schema (unified parser supports Wire 0.1 and Wire 0.2)\n const pr = parseReceiptClaims(result.payload);\n\n if (!pr.ok) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: `Receipt schema validation failed: ${pr.error.message}`,\n details: { parse_code: pr.error.code, issues: sanitizeParseIssues(pr.error.issues) },\n };\n }\n\n // 5. Collect parser warnings (Wire 0.2 parser may emit type/extension warnings)\n if (pr.wireVersion === '0.2') {\n accumulatedWarnings.push(...pr.warnings);\n }\n\n // Wire 0.2 path\n if (pr.wireVersion === '0.2') {\n const claims = pr.claims as Wire02Claims;\n\n // Issuer check\n if (issuer !== undefined && claims.iss !== issuer) {\n return {\n valid: false,\n code: 'E_INVALID_ISSUER',\n message: `Issuer mismatch: expected \"${issuer}\", got \"${claims.iss}\"`,\n };\n }\n\n // Subject check\n if (subjectUri !== undefined && claims.sub !== subjectUri) {\n return {\n valid: false,\n code: 'E_INVALID_SUBJECT',\n message: `Subject mismatch: expected \"${subjectUri}\", got \"${claims.sub ?? 'undefined'}\"`,\n };\n }\n\n // iat: not-yet-valid check (with clock skew)\n if (claims.iat > now + maxClockSkew) {\n return {\n valid: false,\n code: 'E_NOT_YET_VALID',\n message: `Receipt not yet valid: issued at ${new Date(claims.iat * 1000).toISOString()}, now is ${new Date(now * 1000).toISOString()}`,\n };\n }\n\n // occurred_at skew check (evidence kind only)\n if (claims.kind === 'evidence') {\n const skewResult = checkOccurredAtSkew(claims.occurred_at, claims.iat, now, maxClockSkew);\n if (skewResult === 'future_error') {\n return {\n valid: false,\n code: 'E_OCCURRED_AT_FUTURE',\n message: `occurred_at is in the future beyond tolerance (${maxClockSkew}s)`,\n };\n }\n if (skewResult !== null) {\n accumulatedWarnings.push(skewResult);\n }\n }\n\n // Emit type_unregistered warning for valid-but-unregistered type values (DD-155)\n if (!REGISTERED_RECEIPT_TYPES.has(claims.type)) {\n accumulatedWarnings.push({\n code: WARNING_TYPE_UNREGISTERED,\n message: 'Receipt type is not in the recommended type registry',\n pointer: '/type',\n });\n }\n\n // Emit unknown_extension_preserved warnings for unrecognized-but-well-formed keys (DD-155)\n // Malformed keys are already hard errors (E_INVALID_EXTENSION_KEY) at schema layer.\n if (claims.extensions !== undefined) {\n for (const key of Object.keys(claims.extensions)) {\n if (!REGISTERED_EXTENSION_GROUP_KEYS.has(key) && isValidExtensionKey(key)) {\n // RFC 6901: '~' -> '~0', '/' -> '~1'\n const escapedKey = key.replace(/~/g, '~0').replace(/\\//g, '~1');\n accumulatedWarnings.push({\n code: WARNING_UNKNOWN_EXTENSION,\n message: 'Unknown extension key preserved without schema validation',\n pointer: `/extensions/${escapedKey}`,\n });\n }\n }\n }\n\n // Validate policyDigest option format (DD-151): must be sha256:<64 lowercase hex> if provided.\n if (policyDigest !== undefined && !HASH.pattern.test(policyDigest)) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: 'policyDigest option must be in sha256:<64 lowercase hex> format',\n };\n }\n\n // Policy binding check (DD-151): 3-state result.\n // 'unavailable' when either receipt has no policy block or caller omitted policyDigest.\n // 'verified' / 'failed' when both are present; 'failed' is a hard verification error.\n const receiptPolicyDigest = claims.policy?.digest;\n const bindingStatus: PolicyBindingStatus =\n receiptPolicyDigest === undefined || policyDigest === undefined\n ? 'unavailable'\n : verifyPolicyBinding(receiptPolicyDigest, policyDigest);\n if (bindingStatus === 'failed') {\n return {\n valid: false,\n code: 'E_POLICY_BINDING_FAILED',\n message: 'Policy binding check failed: receipt policy digest does not match local policy',\n details: {\n receipt_policy_digest: receiptPolicyDigest,\n local_policy_digest: policyDigest,\n ...(claims.policy?.uri !== undefined && { policy_uri: claims.policy.uri }),\n },\n };\n }\n\n return {\n valid: true,\n variant: 'wire-02',\n claims,\n kid: result.header.kid,\n wireVersion: '0.2',\n warnings: sortWarnings(accumulatedWarnings),\n policy_binding: bindingStatus,\n };\n }\n\n // Wire 0.1 receipts: reject with E_UNSUPPORTED_WIRE_VERSION.\n return {\n valid: false,\n code: 'E_UNSUPPORTED_WIRE_VERSION',\n message: 'Wire 0.1 receipts are not supported. Re-issue as Wire 0.2 using issueWire02().',\n };\n } catch (err) {\n // Handle typed CryptoError from @peac/crypto\n // Use structural check instead of instanceof for robustness across ESM/CJS boundaries\n // Map internal CRYPTO_* codes to canonical E_* codes.\n // JOSE hardening codes get specific E_JWS_* (not generic E_INVALID_FORMAT) so callers\n // can distinguish key-injection attacks from ordinary encoding errors.\n if (isCryptoError(err)) {\n // 1. JOSE hardening: specific E_JWS_* codes (checked first)\n if (Object.prototype.hasOwnProperty.call(JOSE_CODE_MAP, err.code)) {\n return {\n valid: false,\n code: JOSE_CODE_MAP[err.code]!,\n message: err.message,\n };\n }\n // 2. Generic format errors\n if (FORMAT_ERROR_CODES.has(err.code)) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: err.message,\n };\n }\n if (err.code === 'CRYPTO_INVALID_SIGNATURE') {\n return {\n valid: false,\n code: 'E_INVALID_SIGNATURE',\n message: err.message,\n };\n }\n if (err.code === 'CRYPTO_WIRE_VERSION_MISMATCH') {\n return {\n valid: false,\n code: 'E_WIRE_VERSION_MISMATCH',\n message: err.message,\n };\n }\n }\n\n // Handle JSON parse errors from malformed payloads\n // Use structural check for cross-boundary robustness (consistent with isCryptoError pattern)\n if (\n err !== null &&\n typeof err === 'object' &&\n 'name' in err &&\n (err as { name: unknown }).name === 'SyntaxError'\n ) {\n const syntaxMessage =\n 'message' in err && typeof (err as { message: unknown }).message === 'string'\n ? (err as { message: string }).message\n : 'Invalid JSON';\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: `Invalid receipt payload: ${syntaxMessage}`,\n };\n }\n\n // All other errors -> E_INTERNAL\n // No message parsing - code-based mapping only\n const message = err instanceof Error ? err.message : String(err);\n return {\n valid: false,\n code: 'E_INTERNAL',\n message: `Unexpected verification error: ${message}`,\n };\n }\n}\n\n/**\n * @deprecated Removed: verifyLocal() is Wire 0.2 only and always returns variant 'wire-02'.\n * This guard always returns false. Remove usage and use isWire02Result() instead.\n */\nexport function isCommerceResult(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n // Always false: verifyLocal() only returns variant 'wire-02'\n return false;\n}\n\n/**\n * @deprecated Removed: verifyLocal() is Wire 0.2 only and always returns variant 'wire-02'.\n * This guard always returns false. Remove usage and use isWire02Result() instead.\n */\nexport function isAttestationResult(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n // Always false: verifyLocal() only returns variant 'wire-02'\n return false;\n}\n\n/**\n * Type guard: narrows a VerifyLocalResult to a Wire 0.2 success (v0.12.0-preview.1).\n *\n * Use instead of manual `result.valid && result.variant === 'wire-02'` checks\n * to get proper claims narrowing to Wire02Claims.\n */\nexport function isWire02Result(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n return r.valid === true && r.variant === 'wire-02';\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/verify-local.ts"],"names":["jwsVerify","WARNING_TYP_MISSING","validateKernelConstraints","parseReceiptClaims","checkOccurredAtSkew","REGISTERED_RECEIPT_TYPES","WARNING_TYPE_UNREGISTERED","REGISTERED_EXTENSION_GROUP_KEYS","isValidExtensionKey","WARNING_UNKNOWN_EXTENSION","HASH","verifyPolicyBinding","sortWarnings"],"mappings":"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","file":"verify-local.cjs","sourcesContent":["/**\n * Local receipt verification with schema validation\n *\n * Use this for verifying receipts when you have the public key locally,\n * without JWKS discovery.\n */\n\nimport { verify as jwsVerify } from '@peac/crypto';\nimport { type VerificationStrictness, type VerificationWarning, HASH } from '@peac/kernel';\nimport {\n parseReceiptClaims,\n validateKernelConstraints,\n type Wire02Claims,\n checkOccurredAtSkew,\n sortWarnings,\n WARNING_TYP_MISSING,\n WARNING_TYPE_UNREGISTERED,\n WARNING_UNKNOWN_EXTENSION,\n REGISTERED_RECEIPT_TYPES,\n REGISTERED_EXTENSION_GROUP_KEYS,\n isValidExtensionKey,\n verifyPolicyBinding,\n} from '@peac/schema';\nimport type { PolicyBindingStatus } from './verifier-types';\n\n/**\n * Structural type for CryptoError\n * Used instead of instanceof for robustness across ESM/CJS boundaries\n */\ninterface CryptoErrorLike {\n name: 'CryptoError';\n code: string;\n message: string;\n}\n\n/**\n * Structural check for CryptoError\n * More robust than instanceof across module boundaries (ESM/CJS, duplicate packages)\n */\nfunction isCryptoError(err: unknown): err is CryptoErrorLike {\n return (\n err !== null &&\n typeof err === 'object' &&\n 'name' in err &&\n err.name === 'CryptoError' &&\n 'code' in err &&\n typeof err.code === 'string' &&\n err.code.startsWith('CRYPTO_') &&\n 'message' in err &&\n typeof err.message === 'string'\n );\n}\n\n/**\n * Canonical error codes for local verification\n *\n * These map to E_* codes in specs/kernel/errors.json.\n * JOSE hardening codes (E_JWS_*) are distinct from generic E_INVALID_FORMAT\n * so callers can distinguish key-injection, compression, and crit attacks from\n * ordinary format errors (v0.12.0-preview.1, DD-156).\n */\nexport type VerifyLocalErrorCode =\n | 'E_INVALID_SIGNATURE'\n | 'E_INVALID_FORMAT'\n | 'E_CONSTRAINT_VIOLATION'\n | 'E_EXPIRED'\n | 'E_NOT_YET_VALID'\n | 'E_INVALID_ISSUER'\n | 'E_INVALID_AUDIENCE'\n | 'E_INVALID_SUBJECT'\n | 'E_INVALID_RECEIPT_ID'\n | 'E_MISSING_EXP'\n | 'E_WIRE_VERSION_MISMATCH'\n | 'E_UNSUPPORTED_WIRE_VERSION'\n | 'E_OCCURRED_AT_FUTURE'\n // JOSE hardening codes (Wire 0.2, v0.12.0-preview.1, DD-156)\n | 'E_JWS_EMBEDDED_KEY'\n | 'E_JWS_CRIT_REJECTED'\n | 'E_JWS_MISSING_KID'\n | 'E_JWS_B64_REJECTED'\n | 'E_JWS_ZIP_REJECTED'\n // Policy binding (Wire 0.2, v0.12.0-preview.1, DD-151)\n | 'E_POLICY_BINDING_FAILED'\n | 'E_INTERNAL';\n\n/**\n * Options for local verification\n */\nexport interface VerifyLocalOptions {\n /**\n * Expected issuer URL\n *\n * If provided, verification fails if receipt.iss does not match.\n */\n issuer?: string;\n\n /**\n * @deprecated Wire 0.2 does not have an `aud` claim. This option is ignored.\n * Retained for source compatibility during migration; will be removed in v1.0.\n */\n audience?: string;\n\n /**\n * Expected subject URI\n *\n * If provided, verification fails if receipt.sub does not match.\n * Binds the receipt to a specific resource/interaction target.\n */\n subjectUri?: string;\n\n /**\n * @deprecated Wire 0.2 does not have a `rid` claim. Use `jti` for receipt identification.\n * This option is ignored. Retained for source compatibility; will be removed in v1.0.\n */\n rid?: string;\n\n /**\n * @deprecated Wire 0.2 receipts do not expire (permanent evidence by design).\n * This option is ignored. Retained for source compatibility; will be removed in v1.0.\n */\n requireExp?: boolean;\n\n /**\n * Current timestamp (Unix seconds)\n *\n * Defaults to Date.now() / 1000. Override for testing.\n */\n now?: number;\n\n /**\n * Maximum clock skew tolerance (seconds)\n *\n * Allows for clock drift between issuer and verifier.\n * Defaults to 300 (5 minutes).\n */\n maxClockSkew?: number;\n\n /**\n * Verification strictness profile (v0.12.0-preview.1, DD-156).\n *\n * - 'strict' (default): missing typ is a hard error before schema validation.\n * - 'interop': missing typ emits a 'typ_missing' warning and routes by payload content.\n *\n * Strictness is EXCLUSIVELY controlled here (@peac/protocol). @peac/crypto has no strictness param.\n */\n strictness?: VerificationStrictness;\n\n /**\n * Pre-computed local policy digest for policy binding (Wire 0.2, v0.12.0-preview.1, DD-151).\n *\n * Must be in 'sha256:<64 lowercase hex>' format, computed via computePolicyDigestJcs()\n * from @peac/protocol. When provided alongside a receipt that contains a policy block\n * (policy.digest), the binding check is performed:\n * - Match: policy_binding = 'verified'\n * - Mismatch: hard fail with E_POLICY_BINDING_FAILED\n * - Either absent: policy_binding = 'unavailable'\n *\n * Always 'unavailable' for Wire 0.1 receipts regardless of this option.\n */\n policyDigest?: string;\n}\n\n/**\n * Result of successful local verification (Wire 0.2 only)\n *\n * Wire 0.1 receipts are no longer accepted by verifyLocal() and return\n * E_UNSUPPORTED_WIRE_VERSION. Re-issue as Wire 0.2 using issue().\n */\nexport interface VerifyLocalSuccess {\n /** Verification succeeded */\n valid: true;\n /** Receipt variant (always 'wire-02') */\n variant: 'wire-02';\n /** Validated Wire 0.2 receipt claims */\n claims: Wire02Claims;\n /** Key ID from JWS header (for logging/indexing) */\n kid: string;\n /** Wire format version */\n wireVersion: '0.2';\n /** Verification warnings from schema parsing and strictness routing */\n warnings: VerificationWarning[];\n /**\n * Policy binding status (DD-49, DD-151).\n *\n * Three-state result:\n * - 'unavailable': either the receipt contains no policy block, or the\n * caller did not pass a policyDigest option to verifyLocal(). No check.\n * - 'verified': both digests present and match exactly.\n * - 'failed': not returned on success; verifyLocal() returns\n * E_POLICY_BINDING_FAILED (valid: false) before reaching this field.\n */\n policy_binding: PolicyBindingStatus;\n}\n\n/**\n * Result of failed local verification\n */\nexport interface VerifyLocalFailure {\n /** Verification failed */\n valid: false;\n\n /** Canonical error code (maps to specs/kernel/errors.json) */\n code: VerifyLocalErrorCode;\n\n /** Human-readable error message */\n message: string;\n\n /** Structured details for debugging (stable error code preserved in `code`) */\n details?: {\n /** Precise parse error code from unified parser (e.g. E_PARSE_COMMERCE_INVALID) */\n parse_code?: string;\n /** Zod validation issues (bounded, stable shape; non-normative, may change) */\n issues?: ReadonlyArray<{ path: string; message: string }>;\n /**\n * Policy digest from the receipt (present when code is E_POLICY_BINDING_FAILED).\n * Both are SHA-256 hashes; safe to log without leaking policy content.\n */\n receipt_policy_digest?: string;\n /** Caller-supplied policy digest (present when code is E_POLICY_BINDING_FAILED). */\n local_policy_digest?: string;\n /** policy.uri hint from the receipt (present when code is E_POLICY_BINDING_FAILED and uri set). */\n policy_uri?: string;\n };\n}\n\n/**\n * Union type for local verification result\n */\nexport type VerifyLocalResult = VerifyLocalSuccess | VerifyLocalFailure;\n\n/**\n * Internal CRYPTO_* codes that map to generic E_INVALID_FORMAT.\n * These are format/encoding errors not security-specific.\n */\nconst FORMAT_ERROR_CODES = new Set([\n 'CRYPTO_INVALID_JWS_FORMAT',\n 'CRYPTO_INVALID_TYP',\n 'CRYPTO_INVALID_ALG',\n 'CRYPTO_INVALID_KEY_LENGTH',\n]);\n\n/**\n * JOSE hardening code mapping: CRYPTO_JWS_* → specific E_JWS_* (v0.12.0-preview.1, DD-156).\n *\n * Each JOSE hazard code maps to its specific public E_JWS_* counterpart rather than\n * collapsing into the generic E_INVALID_FORMAT. This lets callers distinguish embedded-key\n * injection, crit-header abuse, and unencoded-payload attacks from ordinary format errors.\n */\nconst JOSE_CODE_MAP: Record<string, VerifyLocalErrorCode> = {\n CRYPTO_JWS_EMBEDDED_KEY: 'E_JWS_EMBEDDED_KEY',\n CRYPTO_JWS_CRIT_REJECTED: 'E_JWS_CRIT_REJECTED',\n CRYPTO_JWS_MISSING_KID: 'E_JWS_MISSING_KID',\n CRYPTO_JWS_B64_REJECTED: 'E_JWS_B64_REJECTED',\n CRYPTO_JWS_ZIP_REJECTED: 'E_JWS_ZIP_REJECTED',\n};\n\n/** Max parse issues to include in details (prevents log bloat) */\nconst MAX_PARSE_ISSUES = 25;\n\n/**\n * Sanitize Zod issues into a bounded, stable structure.\n * Avoids exposing raw Zod internals or unbounded arrays in the public API.\n */\nfunction sanitizeParseIssues(\n issues: unknown\n): ReadonlyArray<{ path: string; message: string }> | undefined {\n if (!Array.isArray(issues)) return undefined;\n return issues.slice(0, MAX_PARSE_ISSUES).map((issue) => ({\n path: Array.isArray(issue?.path) ? issue.path.join('.') : '',\n message: typeof issue?.message === 'string' ? issue.message : String(issue),\n }));\n}\n\n/**\n * Verify a Wire 0.2 PEAC receipt locally with a known public key.\n *\n * Wire 0.2 only: Wire 0.1 receipts return E_UNSUPPORTED_WIRE_VERSION.\n * Re-issue Wire 0.1 receipts as Wire 0.2 using issueWire02().\n *\n * This function:\n * 1. Verifies the Ed25519 signature and header (typ, alg)\n * 2. Applies strictness routing for missing typ (strict: hard error; interop: warning)\n * 3. Validates the receipt schema with Zod (Wire 0.2 only)\n * 4. Checks issuer/subject binding (if options provided)\n * 5. Checks time validity (iat with clock skew tolerance)\n * 6. Checks occurred_at skew and collects parse warnings\n *\n * @param jws - JWS compact serialization\n * @param publicKey - Ed25519 public key (32 bytes)\n * @param options - Optional verification options (issuer, subject, clock skew, strictness, policyDigest)\n * @returns Typed verification result\n *\n * @example\n * ```typescript\n * const result = await verifyLocal(jws, publicKey, {\n * issuer: 'https://api.example.com',\n * strictness: 'strict',\n * });\n * if (result.valid) {\n * console.log('Kind:', result.claims.kind);\n * console.log('Warnings:', result.warnings);\n * }\n * ```\n */\nexport async function verifyLocal(\n jws: string,\n publicKey: Uint8Array,\n options: VerifyLocalOptions = {}\n): Promise<VerifyLocalResult> {\n const { issuer, subjectUri, maxClockSkew = 300, strictness = 'strict', policyDigest } = options;\n const now = options.now ?? Math.floor(Date.now() / 1000);\n\n try {\n // 1. Verify signature and header (typ, alg validated by @peac/crypto)\n const result = await jwsVerify<unknown>(jws, publicKey);\n\n if (!result.valid) {\n return {\n valid: false,\n code: 'E_INVALID_SIGNATURE',\n message: 'Ed25519 signature verification failed',\n };\n }\n\n // Accumulated warnings for Wire 0.2 path\n const accumulatedWarnings: VerificationWarning[] = [];\n\n // 2. Strictness routing for missing typ (Correction 1, DD-156)\n if (result.header.typ === undefined) {\n if (strictness === 'strict') {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: 'Missing JWS typ header: strict mode requires typ to be present',\n };\n }\n // interop mode: emit warning and continue\n accumulatedWarnings.push({\n code: WARNING_TYP_MISSING,\n message: 'JWS typ header is absent; accepted in interop mode',\n });\n }\n\n // 3. Validate structural kernel constraints (DD-121, fail-closed)\n const constraintResult = validateKernelConstraints(result.payload);\n if (!constraintResult.valid) {\n const v = constraintResult.violations[0];\n return {\n valid: false,\n code: 'E_CONSTRAINT_VIOLATION',\n message: `Kernel constraint violated: ${v.constraint} (actual: ${v.actual}, limit: ${v.limit})`,\n };\n }\n\n // 4. Validate schema (unified parser supports Wire 0.1 and Wire 0.2)\n const pr = parseReceiptClaims(result.payload);\n\n if (!pr.ok) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: `Receipt schema validation failed: ${pr.error.message}`,\n details: { parse_code: pr.error.code, issues: sanitizeParseIssues(pr.error.issues) },\n };\n }\n\n // 5. Collect parser warnings (Wire 0.2 parser may emit type/extension warnings)\n if (pr.wireVersion === '0.2') {\n accumulatedWarnings.push(...pr.warnings);\n }\n\n // Wire 0.2 path\n if (pr.wireVersion === '0.2') {\n const claims = pr.claims as Wire02Claims;\n\n // Issuer check\n if (issuer !== undefined && claims.iss !== issuer) {\n return {\n valid: false,\n code: 'E_INVALID_ISSUER',\n message: `Issuer mismatch: expected \"${issuer}\", got \"${claims.iss}\"`,\n };\n }\n\n // Subject check\n if (subjectUri !== undefined && claims.sub !== subjectUri) {\n return {\n valid: false,\n code: 'E_INVALID_SUBJECT',\n message: `Subject mismatch: expected \"${subjectUri}\", got \"${claims.sub ?? 'undefined'}\"`,\n };\n }\n\n // iat: not-yet-valid check (with clock skew)\n if (claims.iat > now + maxClockSkew) {\n return {\n valid: false,\n code: 'E_NOT_YET_VALID',\n message: `Receipt not yet valid: issued at ${new Date(claims.iat * 1000).toISOString()}, now is ${new Date(now * 1000).toISOString()}`,\n };\n }\n\n // occurred_at skew check (evidence kind only)\n if (claims.kind === 'evidence') {\n const skewResult = checkOccurredAtSkew(claims.occurred_at, claims.iat, now, maxClockSkew);\n if (skewResult === 'future_error') {\n return {\n valid: false,\n code: 'E_OCCURRED_AT_FUTURE',\n message: `occurred_at is in the future beyond tolerance (${maxClockSkew}s)`,\n };\n }\n if (skewResult !== null) {\n accumulatedWarnings.push(skewResult);\n }\n }\n\n // Emit type_unregistered warning for valid-but-unregistered type values (DD-155)\n if (!REGISTERED_RECEIPT_TYPES.has(claims.type)) {\n accumulatedWarnings.push({\n code: WARNING_TYPE_UNREGISTERED,\n message: 'Receipt type is not in the recommended type registry',\n pointer: '/type',\n });\n }\n\n // Emit unknown_extension_preserved warnings for unrecognized-but-well-formed keys (DD-155)\n // Malformed keys are already hard errors (E_INVALID_EXTENSION_KEY) at schema layer.\n if (claims.extensions !== undefined) {\n for (const key of Object.keys(claims.extensions)) {\n if (!REGISTERED_EXTENSION_GROUP_KEYS.has(key) && isValidExtensionKey(key)) {\n // RFC 6901: '~' -> '~0', '/' -> '~1'\n const escapedKey = key.replace(/~/g, '~0').replace(/\\//g, '~1');\n accumulatedWarnings.push({\n code: WARNING_UNKNOWN_EXTENSION,\n message: 'Unknown extension key preserved without schema validation',\n pointer: `/extensions/${escapedKey}`,\n });\n }\n }\n }\n\n // Validate policyDigest option format (DD-151): must be sha256:<64 lowercase hex> if provided.\n if (policyDigest !== undefined && !HASH.pattern.test(policyDigest)) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: 'policyDigest option must be in sha256:<64 lowercase hex> format',\n };\n }\n\n // Policy binding check (DD-151): 3-state result.\n // 'unavailable' when either receipt has no policy block or caller omitted policyDigest.\n // 'verified' / 'failed' when both are present; 'failed' is a hard verification error.\n const receiptPolicyDigest = claims.policy?.digest;\n const bindingStatus: PolicyBindingStatus =\n receiptPolicyDigest === undefined || policyDigest === undefined\n ? 'unavailable'\n : verifyPolicyBinding(receiptPolicyDigest, policyDigest);\n if (bindingStatus === 'failed') {\n return {\n valid: false,\n code: 'E_POLICY_BINDING_FAILED',\n message: 'Policy binding check failed: receipt policy digest does not match local policy',\n details: {\n receipt_policy_digest: receiptPolicyDigest,\n local_policy_digest: policyDigest,\n ...(claims.policy?.uri !== undefined && { policy_uri: claims.policy.uri }),\n },\n };\n }\n\n return {\n valid: true,\n variant: 'wire-02',\n claims,\n kid: result.header.kid,\n wireVersion: '0.2',\n warnings: sortWarnings(accumulatedWarnings),\n policy_binding: bindingStatus,\n };\n }\n\n // Wire 0.1 receipts: reject with E_UNSUPPORTED_WIRE_VERSION.\n return {\n valid: false,\n code: 'E_UNSUPPORTED_WIRE_VERSION',\n message: 'Wire 0.1 receipts are not supported. Re-issue as Wire 0.2 using issue().',\n };\n } catch (err) {\n // Handle typed CryptoError from @peac/crypto\n // Use structural check instead of instanceof for robustness across ESM/CJS boundaries\n // Map internal CRYPTO_* codes to canonical E_* codes.\n // JOSE hardening codes get specific E_JWS_* (not generic E_INVALID_FORMAT) so callers\n // can distinguish key-injection attacks from ordinary encoding errors.\n if (isCryptoError(err)) {\n // 1. JOSE hardening: specific E_JWS_* codes (checked first)\n if (Object.prototype.hasOwnProperty.call(JOSE_CODE_MAP, err.code)) {\n return {\n valid: false,\n code: JOSE_CODE_MAP[err.code]!,\n message: err.message,\n };\n }\n // 2. Generic format errors\n if (FORMAT_ERROR_CODES.has(err.code)) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: err.message,\n };\n }\n if (err.code === 'CRYPTO_INVALID_SIGNATURE') {\n return {\n valid: false,\n code: 'E_INVALID_SIGNATURE',\n message: err.message,\n };\n }\n if (err.code === 'CRYPTO_WIRE_VERSION_MISMATCH') {\n return {\n valid: false,\n code: 'E_WIRE_VERSION_MISMATCH',\n message: err.message,\n };\n }\n }\n\n // Handle JSON parse errors from malformed payloads\n // Use structural check for cross-boundary robustness (consistent with isCryptoError pattern)\n if (\n err !== null &&\n typeof err === 'object' &&\n 'name' in err &&\n (err as { name: unknown }).name === 'SyntaxError'\n ) {\n const syntaxMessage =\n 'message' in err && typeof (err as { message: unknown }).message === 'string'\n ? (err as { message: string }).message\n : 'Invalid JSON';\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: `Invalid receipt payload: ${syntaxMessage}`,\n };\n }\n\n // All other errors -> E_INTERNAL\n // No message parsing - code-based mapping only\n const message = err instanceof Error ? err.message : String(err);\n return {\n valid: false,\n code: 'E_INTERNAL',\n message: `Unexpected verification error: ${message}`,\n };\n }\n}\n\n/**\n * @deprecated Removed: verifyLocal() is Wire 0.2 only and always returns variant 'wire-02'.\n * This guard always returns false. Remove usage and use isWire02Result() instead.\n */\nexport function isCommerceResult(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n // Always false: verifyLocal() only returns variant 'wire-02'\n return false;\n}\n\n/**\n * @deprecated Removed: verifyLocal() is Wire 0.2 only and always returns variant 'wire-02'.\n * This guard always returns false. Remove usage and use isWire02Result() instead.\n */\nexport function isAttestationResult(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n // Always false: verifyLocal() only returns variant 'wire-02'\n return false;\n}\n\n/**\n * Type guard: narrows a VerifyLocalResult to a Wire 0.2 success (v0.12.0-preview.1).\n *\n * Use instead of manual `result.valid && result.variant === 'wire-02'` checks\n * to get proper claims narrowing to Wire02Claims.\n */\nexport function isWire02Result(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n return r.valid === true && r.variant === 'wire-02';\n}\n"]}
|
package/dist/verify-local.d.ts
CHANGED
|
@@ -88,7 +88,7 @@ export interface VerifyLocalOptions {
|
|
|
88
88
|
* Result of successful local verification (Wire 0.2 only)
|
|
89
89
|
*
|
|
90
90
|
* Wire 0.1 receipts are no longer accepted by verifyLocal() and return
|
|
91
|
-
* E_UNSUPPORTED_WIRE_VERSION. Re-issue as Wire 0.2 using
|
|
91
|
+
* E_UNSUPPORTED_WIRE_VERSION. Re-issue as Wire 0.2 using issue().
|
|
92
92
|
*/
|
|
93
93
|
export interface VerifyLocalSuccess {
|
|
94
94
|
/** Verification succeeded */
|
package/dist/verify-local.mjs
CHANGED
|
@@ -163,7 +163,7 @@ async function verifyLocal(jws, publicKey, options = {}) {
|
|
|
163
163
|
return {
|
|
164
164
|
valid: false,
|
|
165
165
|
code: "E_UNSUPPORTED_WIRE_VERSION",
|
|
166
|
-
message: "Wire 0.1 receipts are not supported. Re-issue as Wire 0.2 using
|
|
166
|
+
message: "Wire 0.1 receipts are not supported. Re-issue as Wire 0.2 using issue()."
|
|
167
167
|
};
|
|
168
168
|
} catch (err) {
|
|
169
169
|
if (isCryptoError(err)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/verify-local.ts"],"names":["jwsVerify"],"mappings":";;;;;AAuCA,SAAS,cAAc,GAAA,EAAsC;AAC3D,EAAA,OACE,GAAA,KAAQ,IAAA,IACR,OAAO,GAAA,KAAQ,QAAA,IACf,UAAU,GAAA,IACV,GAAA,CAAI,IAAA,KAAS,aAAA,IACb,MAAA,IAAU,GAAA,IACV,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,IACpB,GAAA,CAAI,IAAA,CAAK,UAAA,CAAW,SAAS,CAAA,IAC7B,SAAA,IAAa,GAAA,IACb,OAAO,GAAA,CAAI,OAAA,KAAY,QAAA;AAE3B;AAuLA,IAAM,kBAAA,uBAAyB,GAAA,CAAI;AAAA,EACjC,2BAAA;AAAA,EACA,oBAAA;AAAA,EACA,oBAAA;AAAA,EACA;AACF,CAAC,CAAA;AASD,IAAM,aAAA,GAAsD;AAAA,EAC1D,uBAAA,EAAyB,oBAAA;AAAA,EACzB,wBAAA,EAA0B,qBAAA;AAAA,EAC1B,sBAAA,EAAwB,mBAAA;AAAA,EACxB,uBAAA,EAAyB,oBAAA;AAAA,EACzB,uBAAA,EAAyB;AAC3B,CAAA;AAGA,IAAM,gBAAA,GAAmB,EAAA;AAMzB,SAAS,oBACP,MAAA,EAC8D;AAC9D,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAM,GAAG,OAAO,MAAA;AACnC,EAAA,OAAO,OAAO,KAAA,CAAM,CAAA,EAAG,gBAAgB,CAAA,CAAE,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,IACvD,IAAA,EAAM,KAAA,CAAM,OAAA,CAAQ,KAAA,EAAO,IAAI,IAAI,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,GAAI,EAAA;AAAA,IAC1D,OAAA,EAAS,OAAO,KAAA,EAAO,OAAA,KAAY,WAAW,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK;AAAA,GAC5E,CAAE,CAAA;AACJ;AAiCA,eAAsB,WAAA,CACpB,GAAA,EACA,SAAA,EACA,OAAA,GAA8B,EAAC,EACH;AAC5B,EAAA,MAAM,EAAE,QAAQ,UAAA,EAAY,YAAA,GAAe,KAAK,UAAA,GAAa,QAAA,EAAU,cAAa,GAAI,OAAA;AACxF,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,IAAO,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AAEvD,EAAA,IAAI;AAEF,IAAA,MAAM,MAAA,GAAS,MAAMA,MAAA,CAAmB,GAAA,EAAK,SAAS,CAAA;AAEtD,IAAA,IAAI,CAAC,OAAO,KAAA,EAAO;AACjB,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,KAAA;AAAA,QACP,IAAA,EAAM,qBAAA;AAAA,QACN,OAAA,EAAS;AAAA,OACX;AAAA,IACF;AAGA,IAAA,MAAM,sBAA6C,EAAC;AAGpD,IAAA,IAAI,MAAA,CAAO,MAAA,CAAO,GAAA,KAAQ,KAAA,CAAA,EAAW;AACnC,MAAA,IAAI,eAAe,QAAA,EAAU;AAC3B,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,KAAA;AAAA,UACP,IAAA,EAAM,kBAAA;AAAA,UACN,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAEA,MAAA,mBAAA,CAAoB,IAAA,CAAK;AAAA,QACvB,IAAA,EAAM,mBAAA;AAAA,QACN,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH;AAGA,IAAA,MAAM,gBAAA,GAAmB,yBAAA,CAA0B,MAAA,CAAO,OAAO,CAAA;AACjE,IAAA,IAAI,CAAC,iBAAiB,KAAA,EAAO;AAC3B,MAAA,MAAM,CAAA,GAAI,gBAAA,CAAiB,UAAA,CAAW,CAAC,CAAA;AACvC,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,KAAA;AAAA,QACP,IAAA,EAAM,wBAAA;AAAA,QACN,OAAA,EAAS,+BAA+B,CAAA,CAAE,UAAU,aAAa,CAAA,CAAE,MAAM,CAAA,SAAA,EAAY,CAAA,CAAE,KAAK,CAAA,CAAA;AAAA,OAC9F;AAAA,IACF;AAGA,IAAA,MAAM,EAAA,GAAK,kBAAA,CAAmB,MAAA,CAAO,OAAO,CAAA;AAE5C,IAAA,IAAI,CAAC,GAAG,EAAA,EAAI;AACV,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,KAAA;AAAA,QACP,IAAA,EAAM,kBAAA;AAAA,QACN,OAAA,EAAS,CAAA,kCAAA,EAAqC,EAAA,CAAG,KAAA,CAAM,OAAO,CAAA,CAAA;AAAA,QAC9D,OAAA,EAAS,EAAE,UAAA,EAAY,EAAA,CAAG,KAAA,CAAM,IAAA,EAAM,MAAA,EAAQ,mBAAA,CAAoB,EAAA,CAAG,KAAA,CAAM,MAAM,CAAA;AAAE,OACrF;AAAA,IACF;AAGA,IAAA,IAAI,EAAA,CAAG,gBAAgB,KAAA,EAAO;AAC5B,MAAA,mBAAA,CAAoB,IAAA,CAAK,GAAG,EAAA,CAAG,QAAQ,CAAA;AAAA,IACzC;AAGA,IAAA,IAAI,EAAA,CAAG,gBAAgB,KAAA,EAAO;AAC5B,MAAA,MAAM,SAAS,EAAA,CAAG,MAAA;AAGlB,MAAA,IAAI,MAAA,KAAW,KAAA,CAAA,IAAa,MAAA,CAAO,GAAA,KAAQ,MAAA,EAAQ;AACjD,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,KAAA;AAAA,UACP,IAAA,EAAM,kBAAA;AAAA,UACN,OAAA,EAAS,CAAA,2BAAA,EAA8B,MAAM,CAAA,QAAA,EAAW,OAAO,GAAG,CAAA,CAAA;AAAA,SACpE;AAAA,MACF;AAGA,MAAA,IAAI,UAAA,KAAe,KAAA,CAAA,IAAa,MAAA,CAAO,GAAA,KAAQ,UAAA,EAAY;AACzD,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,KAAA;AAAA,UACP,IAAA,EAAM,mBAAA;AAAA,UACN,SAAS,CAAA,4BAAA,EAA+B,UAAU,CAAA,QAAA,EAAW,MAAA,CAAO,OAAO,WAAW,CAAA,CAAA;AAAA,SACxF;AAAA,MACF;AAGA,MAAA,IAAI,MAAA,CAAO,GAAA,GAAM,GAAA,GAAM,YAAA,EAAc;AACnC,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,KAAA;AAAA,UACP,IAAA,EAAM,iBAAA;AAAA,UACN,SAAS,CAAA,iCAAA,EAAoC,IAAI,IAAA,CAAK,MAAA,CAAO,MAAM,GAAI,CAAA,CAAE,WAAA,EAAa,YAAY,IAAI,IAAA,CAAK,MAAM,GAAI,CAAA,CAAE,aAAa,CAAA;AAAA,SACtI;AAAA,MACF;AAGA,MAAA,IAAI,MAAA,CAAO,SAAS,UAAA,EAAY;AAC9B,QAAA,MAAM,aAAa,mBAAA,CAAoB,MAAA,CAAO,aAAa,MAAA,CAAO,GAAA,EAAK,KAAK,YAAY,CAAA;AACxF,QAAA,IAAI,eAAe,cAAA,EAAgB;AACjC,UAAA,OAAO;AAAA,YACL,KAAA,EAAO,KAAA;AAAA,YACP,IAAA,EAAM,sBAAA;AAAA,YACN,OAAA,EAAS,kDAAkD,YAAY,CAAA,EAAA;AAAA,WACzE;AAAA,QACF;AACA,QAAA,IAAI,eAAe,IAAA,EAAM;AACvB,UAAA,mBAAA,CAAoB,KAAK,UAAU,CAAA;AAAA,QACrC;AAAA,MACF;AAGA,MAAA,IAAI,CAAC,wBAAA,CAAyB,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA,EAAG;AAC9C,QAAA,mBAAA,CAAoB,IAAA,CAAK;AAAA,UACvB,IAAA,EAAM,yBAAA;AAAA,UACN,OAAA,EAAS,sDAAA;AAAA,UACT,OAAA,EAAS;AAAA,SACV,CAAA;AAAA,MACH;AAIA,MAAA,IAAI,MAAA,CAAO,eAAe,KAAA,CAAA,EAAW;AACnC,QAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,EAAG;AAChD,UAAA,IAAI,CAAC,+BAAA,CAAgC,GAAA,CAAI,GAAG,CAAA,IAAK,mBAAA,CAAoB,GAAG,CAAA,EAAG;AAEzE,YAAA,MAAM,UAAA,GAAa,IAAI,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAA,CAAE,OAAA,CAAQ,OAAO,IAAI,CAAA;AAC9D,YAAA,mBAAA,CAAoB,IAAA,CAAK;AAAA,cACvB,IAAA,EAAM,yBAAA;AAAA,cACN,OAAA,EAAS,2DAAA;AAAA,cACT,OAAA,EAAS,eAAe,UAAU,CAAA;AAAA,aACnC,CAAA;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAGA,MAAA,IAAI,iBAAiB,KAAA,CAAA,IAAa,CAAC,KAAK,OAAA,CAAQ,IAAA,CAAK,YAAY,CAAA,EAAG;AAClE,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,KAAA;AAAA,UACP,IAAA,EAAM,kBAAA;AAAA,UACN,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAKA,MAAA,MAAM,mBAAA,GAAsB,OAAO,MAAA,EAAQ,MAAA;AAC3C,MAAA,MAAM,aAAA,GACJ,wBAAwB,KAAA,CAAA,IAAa,YAAA,KAAiB,SAClD,aAAA,GACA,mBAAA,CAAoB,qBAAqB,YAAY,CAAA;AAC3D,MAAA,IAAI,kBAAkB,QAAA,EAAU;AAC9B,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,KAAA;AAAA,UACP,IAAA,EAAM,yBAAA;AAAA,UACN,OAAA,EAAS,gFAAA;AAAA,UACT,OAAA,EAAS;AAAA,YACP,qBAAA,EAAuB,mBAAA;AAAA,YACvB,mBAAA,EAAqB,YAAA;AAAA,YACrB,GAAI,OAAO,MAAA,EAAQ,GAAA,KAAQ,UAAa,EAAE,UAAA,EAAY,MAAA,CAAO,MAAA,CAAO,GAAA;AAAI;AAC1E,SACF;AAAA,MACF;AAEA,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,IAAA;AAAA,QACP,OAAA,EAAS,SAAA;AAAA,QACT,MAAA;AAAA,QACA,GAAA,EAAK,OAAO,MAAA,CAAO,GAAA;AAAA,QACnB,WAAA,EAAa,KAAA;AAAA,QACb,QAAA,EAAU,aAAa,mBAAmB,CAAA;AAAA,QAC1C,cAAA,EAAgB;AAAA,OAClB;AAAA,IACF;AAGA,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,KAAA;AAAA,MACP,IAAA,EAAM,4BAAA;AAAA,MACN,OAAA,EAAS;AAAA,KACX;AAAA,EACF,SAAS,GAAA,EAAK;AAMZ,IAAA,IAAI,aAAA,CAAc,GAAG,CAAA,EAAG;AAEtB,MAAA,IAAI,OAAO,SAAA,CAAU,cAAA,CAAe,KAAK,aAAA,EAAe,GAAA,CAAI,IAAI,CAAA,EAAG;AACjE,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,KAAA;AAAA,UACP,IAAA,EAAM,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA;AAAA,UAC5B,SAAS,GAAA,CAAI;AAAA,SACf;AAAA,MACF;AAEA,MAAA,IAAI,kBAAA,CAAmB,GAAA,CAAI,GAAA,CAAI,IAAI,CAAA,EAAG;AACpC,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,KAAA;AAAA,UACP,IAAA,EAAM,kBAAA;AAAA,UACN,SAAS,GAAA,CAAI;AAAA,SACf;AAAA,MACF;AACA,MAAA,IAAI,GAAA,CAAI,SAAS,0BAAA,EAA4B;AAC3C,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,KAAA;AAAA,UACP,IAAA,EAAM,qBAAA;AAAA,UACN,SAAS,GAAA,CAAI;AAAA,SACf;AAAA,MACF;AACA,MAAA,IAAI,GAAA,CAAI,SAAS,8BAAA,EAAgC;AAC/C,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,KAAA;AAAA,UACP,IAAA,EAAM,yBAAA;AAAA,UACN,SAAS,GAAA,CAAI;AAAA,SACf;AAAA,MACF;AAAA,IACF;AAIA,IAAA,IACE,GAAA,KAAQ,QACR,OAAO,GAAA,KAAQ,YACf,MAAA,IAAU,GAAA,IACT,GAAA,CAA0B,IAAA,KAAS,aAAA,EACpC;AACA,MAAA,MAAM,aAAA,GACJ,aAAa,GAAA,IAAO,OAAQ,IAA6B,OAAA,KAAY,QAAA,GAChE,IAA4B,OAAA,GAC7B,cAAA;AACN,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,KAAA;AAAA,QACP,IAAA,EAAM,kBAAA;AAAA,QACN,OAAA,EAAS,4BAA4B,aAAa,CAAA;AAAA,OACpD;AAAA,IACF;AAIA,IAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,KAAA;AAAA,MACP,IAAA,EAAM,YAAA;AAAA,MACN,OAAA,EAAS,kCAAkC,OAAO,CAAA;AAAA,KACpD;AAAA,EACF;AACF;AAMO,SAAS,iBACd,CAAA,EACkD;AAElD,EAAA,OAAO,KAAA;AACT;AAMO,SAAS,oBACd,CAAA,EACkD;AAElD,EAAA,OAAO,KAAA;AACT;AAQO,SAAS,eACd,CAAA,EACkD;AAClD,EAAA,OAAO,CAAA,CAAE,KAAA,KAAU,IAAA,IAAQ,CAAA,CAAE,OAAA,KAAY,SAAA;AAC3C","file":"verify-local.mjs","sourcesContent":["/**\n * Local receipt verification with schema validation\n *\n * Use this for verifying receipts when you have the public key locally,\n * without JWKS discovery.\n */\n\nimport { verify as jwsVerify } from '@peac/crypto';\nimport { type VerificationStrictness, type VerificationWarning, HASH } from '@peac/kernel';\nimport {\n parseReceiptClaims,\n validateKernelConstraints,\n type Wire02Claims,\n checkOccurredAtSkew,\n sortWarnings,\n WARNING_TYP_MISSING,\n WARNING_TYPE_UNREGISTERED,\n WARNING_UNKNOWN_EXTENSION,\n REGISTERED_RECEIPT_TYPES,\n REGISTERED_EXTENSION_GROUP_KEYS,\n isValidExtensionKey,\n verifyPolicyBinding,\n} from '@peac/schema';\nimport type { PolicyBindingStatus } from './verifier-types';\n\n/**\n * Structural type for CryptoError\n * Used instead of instanceof for robustness across ESM/CJS boundaries\n */\ninterface CryptoErrorLike {\n name: 'CryptoError';\n code: string;\n message: string;\n}\n\n/**\n * Structural check for CryptoError\n * More robust than instanceof across module boundaries (ESM/CJS, duplicate packages)\n */\nfunction isCryptoError(err: unknown): err is CryptoErrorLike {\n return (\n err !== null &&\n typeof err === 'object' &&\n 'name' in err &&\n err.name === 'CryptoError' &&\n 'code' in err &&\n typeof err.code === 'string' &&\n err.code.startsWith('CRYPTO_') &&\n 'message' in err &&\n typeof err.message === 'string'\n );\n}\n\n/**\n * Canonical error codes for local verification\n *\n * These map to E_* codes in specs/kernel/errors.json.\n * JOSE hardening codes (E_JWS_*) are distinct from generic E_INVALID_FORMAT\n * so callers can distinguish key-injection, compression, and crit attacks from\n * ordinary format errors (v0.12.0-preview.1, DD-156).\n */\nexport type VerifyLocalErrorCode =\n | 'E_INVALID_SIGNATURE'\n | 'E_INVALID_FORMAT'\n | 'E_CONSTRAINT_VIOLATION'\n | 'E_EXPIRED'\n | 'E_NOT_YET_VALID'\n | 'E_INVALID_ISSUER'\n | 'E_INVALID_AUDIENCE'\n | 'E_INVALID_SUBJECT'\n | 'E_INVALID_RECEIPT_ID'\n | 'E_MISSING_EXP'\n | 'E_WIRE_VERSION_MISMATCH'\n | 'E_UNSUPPORTED_WIRE_VERSION'\n | 'E_OCCURRED_AT_FUTURE'\n // JOSE hardening codes (Wire 0.2, v0.12.0-preview.1, DD-156)\n | 'E_JWS_EMBEDDED_KEY'\n | 'E_JWS_CRIT_REJECTED'\n | 'E_JWS_MISSING_KID'\n | 'E_JWS_B64_REJECTED'\n | 'E_JWS_ZIP_REJECTED'\n // Policy binding (Wire 0.2, v0.12.0-preview.1, DD-151)\n | 'E_POLICY_BINDING_FAILED'\n | 'E_INTERNAL';\n\n/**\n * Options for local verification\n */\nexport interface VerifyLocalOptions {\n /**\n * Expected issuer URL\n *\n * If provided, verification fails if receipt.iss does not match.\n */\n issuer?: string;\n\n /**\n * @deprecated Wire 0.2 does not have an `aud` claim. This option is ignored.\n * Retained for source compatibility during migration; will be removed in v1.0.\n */\n audience?: string;\n\n /**\n * Expected subject URI\n *\n * If provided, verification fails if receipt.sub does not match.\n * Binds the receipt to a specific resource/interaction target.\n */\n subjectUri?: string;\n\n /**\n * @deprecated Wire 0.2 does not have a `rid` claim. Use `jti` for receipt identification.\n * This option is ignored. Retained for source compatibility; will be removed in v1.0.\n */\n rid?: string;\n\n /**\n * @deprecated Wire 0.2 receipts do not expire (permanent evidence by design).\n * This option is ignored. Retained for source compatibility; will be removed in v1.0.\n */\n requireExp?: boolean;\n\n /**\n * Current timestamp (Unix seconds)\n *\n * Defaults to Date.now() / 1000. Override for testing.\n */\n now?: number;\n\n /**\n * Maximum clock skew tolerance (seconds)\n *\n * Allows for clock drift between issuer and verifier.\n * Defaults to 300 (5 minutes).\n */\n maxClockSkew?: number;\n\n /**\n * Verification strictness profile (v0.12.0-preview.1, DD-156).\n *\n * - 'strict' (default): missing typ is a hard error before schema validation.\n * - 'interop': missing typ emits a 'typ_missing' warning and routes by payload content.\n *\n * Strictness is EXCLUSIVELY controlled here (@peac/protocol). @peac/crypto has no strictness param.\n */\n strictness?: VerificationStrictness;\n\n /**\n * Pre-computed local policy digest for policy binding (Wire 0.2, v0.12.0-preview.1, DD-151).\n *\n * Must be in 'sha256:<64 lowercase hex>' format, computed via computePolicyDigestJcs()\n * from @peac/protocol. When provided alongside a receipt that contains a policy block\n * (policy.digest), the binding check is performed:\n * - Match: policy_binding = 'verified'\n * - Mismatch: hard fail with E_POLICY_BINDING_FAILED\n * - Either absent: policy_binding = 'unavailable'\n *\n * Always 'unavailable' for Wire 0.1 receipts regardless of this option.\n */\n policyDigest?: string;\n}\n\n/**\n * Result of successful local verification (Wire 0.2 only)\n *\n * Wire 0.1 receipts are no longer accepted by verifyLocal() and return\n * E_UNSUPPORTED_WIRE_VERSION. Re-issue as Wire 0.2 using issueWire02().\n */\nexport interface VerifyLocalSuccess {\n /** Verification succeeded */\n valid: true;\n /** Receipt variant (always 'wire-02') */\n variant: 'wire-02';\n /** Validated Wire 0.2 receipt claims */\n claims: Wire02Claims;\n /** Key ID from JWS header (for logging/indexing) */\n kid: string;\n /** Wire format version */\n wireVersion: '0.2';\n /** Verification warnings from schema parsing and strictness routing */\n warnings: VerificationWarning[];\n /**\n * Policy binding status (DD-49, DD-151).\n *\n * Three-state result:\n * - 'unavailable': either the receipt contains no policy block, or the\n * caller did not pass a policyDigest option to verifyLocal(). No check.\n * - 'verified': both digests present and match exactly.\n * - 'failed': not returned on success; verifyLocal() returns\n * E_POLICY_BINDING_FAILED (valid: false) before reaching this field.\n */\n policy_binding: PolicyBindingStatus;\n}\n\n/**\n * Result of failed local verification\n */\nexport interface VerifyLocalFailure {\n /** Verification failed */\n valid: false;\n\n /** Canonical error code (maps to specs/kernel/errors.json) */\n code: VerifyLocalErrorCode;\n\n /** Human-readable error message */\n message: string;\n\n /** Structured details for debugging (stable error code preserved in `code`) */\n details?: {\n /** Precise parse error code from unified parser (e.g. E_PARSE_COMMERCE_INVALID) */\n parse_code?: string;\n /** Zod validation issues (bounded, stable shape; non-normative, may change) */\n issues?: ReadonlyArray<{ path: string; message: string }>;\n /**\n * Policy digest from the receipt (present when code is E_POLICY_BINDING_FAILED).\n * Both are SHA-256 hashes; safe to log without leaking policy content.\n */\n receipt_policy_digest?: string;\n /** Caller-supplied policy digest (present when code is E_POLICY_BINDING_FAILED). */\n local_policy_digest?: string;\n /** policy.uri hint from the receipt (present when code is E_POLICY_BINDING_FAILED and uri set). */\n policy_uri?: string;\n };\n}\n\n/**\n * Union type for local verification result\n */\nexport type VerifyLocalResult = VerifyLocalSuccess | VerifyLocalFailure;\n\n/**\n * Internal CRYPTO_* codes that map to generic E_INVALID_FORMAT.\n * These are format/encoding errors not security-specific.\n */\nconst FORMAT_ERROR_CODES = new Set([\n 'CRYPTO_INVALID_JWS_FORMAT',\n 'CRYPTO_INVALID_TYP',\n 'CRYPTO_INVALID_ALG',\n 'CRYPTO_INVALID_KEY_LENGTH',\n]);\n\n/**\n * JOSE hardening code mapping: CRYPTO_JWS_* → specific E_JWS_* (v0.12.0-preview.1, DD-156).\n *\n * Each JOSE hazard code maps to its specific public E_JWS_* counterpart rather than\n * collapsing into the generic E_INVALID_FORMAT. This lets callers distinguish embedded-key\n * injection, crit-header abuse, and unencoded-payload attacks from ordinary format errors.\n */\nconst JOSE_CODE_MAP: Record<string, VerifyLocalErrorCode> = {\n CRYPTO_JWS_EMBEDDED_KEY: 'E_JWS_EMBEDDED_KEY',\n CRYPTO_JWS_CRIT_REJECTED: 'E_JWS_CRIT_REJECTED',\n CRYPTO_JWS_MISSING_KID: 'E_JWS_MISSING_KID',\n CRYPTO_JWS_B64_REJECTED: 'E_JWS_B64_REJECTED',\n CRYPTO_JWS_ZIP_REJECTED: 'E_JWS_ZIP_REJECTED',\n};\n\n/** Max parse issues to include in details (prevents log bloat) */\nconst MAX_PARSE_ISSUES = 25;\n\n/**\n * Sanitize Zod issues into a bounded, stable structure.\n * Avoids exposing raw Zod internals or unbounded arrays in the public API.\n */\nfunction sanitizeParseIssues(\n issues: unknown\n): ReadonlyArray<{ path: string; message: string }> | undefined {\n if (!Array.isArray(issues)) return undefined;\n return issues.slice(0, MAX_PARSE_ISSUES).map((issue) => ({\n path: Array.isArray(issue?.path) ? issue.path.join('.') : '',\n message: typeof issue?.message === 'string' ? issue.message : String(issue),\n }));\n}\n\n/**\n * Verify a Wire 0.2 PEAC receipt locally with a known public key.\n *\n * Wire 0.2 only: Wire 0.1 receipts return E_UNSUPPORTED_WIRE_VERSION.\n * Re-issue Wire 0.1 receipts as Wire 0.2 using issueWire02().\n *\n * This function:\n * 1. Verifies the Ed25519 signature and header (typ, alg)\n * 2. Applies strictness routing for missing typ (strict: hard error; interop: warning)\n * 3. Validates the receipt schema with Zod (Wire 0.2 only)\n * 4. Checks issuer/subject binding (if options provided)\n * 5. Checks time validity (iat with clock skew tolerance)\n * 6. Checks occurred_at skew and collects parse warnings\n *\n * @param jws - JWS compact serialization\n * @param publicKey - Ed25519 public key (32 bytes)\n * @param options - Optional verification options (issuer, subject, clock skew, strictness, policyDigest)\n * @returns Typed verification result\n *\n * @example\n * ```typescript\n * const result = await verifyLocal(jws, publicKey, {\n * issuer: 'https://api.example.com',\n * strictness: 'strict',\n * });\n * if (result.valid) {\n * console.log('Kind:', result.claims.kind);\n * console.log('Warnings:', result.warnings);\n * }\n * ```\n */\nexport async function verifyLocal(\n jws: string,\n publicKey: Uint8Array,\n options: VerifyLocalOptions = {}\n): Promise<VerifyLocalResult> {\n const { issuer, subjectUri, maxClockSkew = 300, strictness = 'strict', policyDigest } = options;\n const now = options.now ?? Math.floor(Date.now() / 1000);\n\n try {\n // 1. Verify signature and header (typ, alg validated by @peac/crypto)\n const result = await jwsVerify<unknown>(jws, publicKey);\n\n if (!result.valid) {\n return {\n valid: false,\n code: 'E_INVALID_SIGNATURE',\n message: 'Ed25519 signature verification failed',\n };\n }\n\n // Accumulated warnings for Wire 0.2 path\n const accumulatedWarnings: VerificationWarning[] = [];\n\n // 2. Strictness routing for missing typ (Correction 1, DD-156)\n if (result.header.typ === undefined) {\n if (strictness === 'strict') {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: 'Missing JWS typ header: strict mode requires typ to be present',\n };\n }\n // interop mode: emit warning and continue\n accumulatedWarnings.push({\n code: WARNING_TYP_MISSING,\n message: 'JWS typ header is absent; accepted in interop mode',\n });\n }\n\n // 3. Validate structural kernel constraints (DD-121, fail-closed)\n const constraintResult = validateKernelConstraints(result.payload);\n if (!constraintResult.valid) {\n const v = constraintResult.violations[0];\n return {\n valid: false,\n code: 'E_CONSTRAINT_VIOLATION',\n message: `Kernel constraint violated: ${v.constraint} (actual: ${v.actual}, limit: ${v.limit})`,\n };\n }\n\n // 4. Validate schema (unified parser supports Wire 0.1 and Wire 0.2)\n const pr = parseReceiptClaims(result.payload);\n\n if (!pr.ok) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: `Receipt schema validation failed: ${pr.error.message}`,\n details: { parse_code: pr.error.code, issues: sanitizeParseIssues(pr.error.issues) },\n };\n }\n\n // 5. Collect parser warnings (Wire 0.2 parser may emit type/extension warnings)\n if (pr.wireVersion === '0.2') {\n accumulatedWarnings.push(...pr.warnings);\n }\n\n // Wire 0.2 path\n if (pr.wireVersion === '0.2') {\n const claims = pr.claims as Wire02Claims;\n\n // Issuer check\n if (issuer !== undefined && claims.iss !== issuer) {\n return {\n valid: false,\n code: 'E_INVALID_ISSUER',\n message: `Issuer mismatch: expected \"${issuer}\", got \"${claims.iss}\"`,\n };\n }\n\n // Subject check\n if (subjectUri !== undefined && claims.sub !== subjectUri) {\n return {\n valid: false,\n code: 'E_INVALID_SUBJECT',\n message: `Subject mismatch: expected \"${subjectUri}\", got \"${claims.sub ?? 'undefined'}\"`,\n };\n }\n\n // iat: not-yet-valid check (with clock skew)\n if (claims.iat > now + maxClockSkew) {\n return {\n valid: false,\n code: 'E_NOT_YET_VALID',\n message: `Receipt not yet valid: issued at ${new Date(claims.iat * 1000).toISOString()}, now is ${new Date(now * 1000).toISOString()}`,\n };\n }\n\n // occurred_at skew check (evidence kind only)\n if (claims.kind === 'evidence') {\n const skewResult = checkOccurredAtSkew(claims.occurred_at, claims.iat, now, maxClockSkew);\n if (skewResult === 'future_error') {\n return {\n valid: false,\n code: 'E_OCCURRED_AT_FUTURE',\n message: `occurred_at is in the future beyond tolerance (${maxClockSkew}s)`,\n };\n }\n if (skewResult !== null) {\n accumulatedWarnings.push(skewResult);\n }\n }\n\n // Emit type_unregistered warning for valid-but-unregistered type values (DD-155)\n if (!REGISTERED_RECEIPT_TYPES.has(claims.type)) {\n accumulatedWarnings.push({\n code: WARNING_TYPE_UNREGISTERED,\n message: 'Receipt type is not in the recommended type registry',\n pointer: '/type',\n });\n }\n\n // Emit unknown_extension_preserved warnings for unrecognized-but-well-formed keys (DD-155)\n // Malformed keys are already hard errors (E_INVALID_EXTENSION_KEY) at schema layer.\n if (claims.extensions !== undefined) {\n for (const key of Object.keys(claims.extensions)) {\n if (!REGISTERED_EXTENSION_GROUP_KEYS.has(key) && isValidExtensionKey(key)) {\n // RFC 6901: '~' -> '~0', '/' -> '~1'\n const escapedKey = key.replace(/~/g, '~0').replace(/\\//g, '~1');\n accumulatedWarnings.push({\n code: WARNING_UNKNOWN_EXTENSION,\n message: 'Unknown extension key preserved without schema validation',\n pointer: `/extensions/${escapedKey}`,\n });\n }\n }\n }\n\n // Validate policyDigest option format (DD-151): must be sha256:<64 lowercase hex> if provided.\n if (policyDigest !== undefined && !HASH.pattern.test(policyDigest)) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: 'policyDigest option must be in sha256:<64 lowercase hex> format',\n };\n }\n\n // Policy binding check (DD-151): 3-state result.\n // 'unavailable' when either receipt has no policy block or caller omitted policyDigest.\n // 'verified' / 'failed' when both are present; 'failed' is a hard verification error.\n const receiptPolicyDigest = claims.policy?.digest;\n const bindingStatus: PolicyBindingStatus =\n receiptPolicyDigest === undefined || policyDigest === undefined\n ? 'unavailable'\n : verifyPolicyBinding(receiptPolicyDigest, policyDigest);\n if (bindingStatus === 'failed') {\n return {\n valid: false,\n code: 'E_POLICY_BINDING_FAILED',\n message: 'Policy binding check failed: receipt policy digest does not match local policy',\n details: {\n receipt_policy_digest: receiptPolicyDigest,\n local_policy_digest: policyDigest,\n ...(claims.policy?.uri !== undefined && { policy_uri: claims.policy.uri }),\n },\n };\n }\n\n return {\n valid: true,\n variant: 'wire-02',\n claims,\n kid: result.header.kid,\n wireVersion: '0.2',\n warnings: sortWarnings(accumulatedWarnings),\n policy_binding: bindingStatus,\n };\n }\n\n // Wire 0.1 receipts: reject with E_UNSUPPORTED_WIRE_VERSION.\n return {\n valid: false,\n code: 'E_UNSUPPORTED_WIRE_VERSION',\n message: 'Wire 0.1 receipts are not supported. Re-issue as Wire 0.2 using issueWire02().',\n };\n } catch (err) {\n // Handle typed CryptoError from @peac/crypto\n // Use structural check instead of instanceof for robustness across ESM/CJS boundaries\n // Map internal CRYPTO_* codes to canonical E_* codes.\n // JOSE hardening codes get specific E_JWS_* (not generic E_INVALID_FORMAT) so callers\n // can distinguish key-injection attacks from ordinary encoding errors.\n if (isCryptoError(err)) {\n // 1. JOSE hardening: specific E_JWS_* codes (checked first)\n if (Object.prototype.hasOwnProperty.call(JOSE_CODE_MAP, err.code)) {\n return {\n valid: false,\n code: JOSE_CODE_MAP[err.code]!,\n message: err.message,\n };\n }\n // 2. Generic format errors\n if (FORMAT_ERROR_CODES.has(err.code)) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: err.message,\n };\n }\n if (err.code === 'CRYPTO_INVALID_SIGNATURE') {\n return {\n valid: false,\n code: 'E_INVALID_SIGNATURE',\n message: err.message,\n };\n }\n if (err.code === 'CRYPTO_WIRE_VERSION_MISMATCH') {\n return {\n valid: false,\n code: 'E_WIRE_VERSION_MISMATCH',\n message: err.message,\n };\n }\n }\n\n // Handle JSON parse errors from malformed payloads\n // Use structural check for cross-boundary robustness (consistent with isCryptoError pattern)\n if (\n err !== null &&\n typeof err === 'object' &&\n 'name' in err &&\n (err as { name: unknown }).name === 'SyntaxError'\n ) {\n const syntaxMessage =\n 'message' in err && typeof (err as { message: unknown }).message === 'string'\n ? (err as { message: string }).message\n : 'Invalid JSON';\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: `Invalid receipt payload: ${syntaxMessage}`,\n };\n }\n\n // All other errors -> E_INTERNAL\n // No message parsing - code-based mapping only\n const message = err instanceof Error ? err.message : String(err);\n return {\n valid: false,\n code: 'E_INTERNAL',\n message: `Unexpected verification error: ${message}`,\n };\n }\n}\n\n/**\n * @deprecated Removed: verifyLocal() is Wire 0.2 only and always returns variant 'wire-02'.\n * This guard always returns false. Remove usage and use isWire02Result() instead.\n */\nexport function isCommerceResult(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n // Always false: verifyLocal() only returns variant 'wire-02'\n return false;\n}\n\n/**\n * @deprecated Removed: verifyLocal() is Wire 0.2 only and always returns variant 'wire-02'.\n * This guard always returns false. Remove usage and use isWire02Result() instead.\n */\nexport function isAttestationResult(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n // Always false: verifyLocal() only returns variant 'wire-02'\n return false;\n}\n\n/**\n * Type guard: narrows a VerifyLocalResult to a Wire 0.2 success (v0.12.0-preview.1).\n *\n * Use instead of manual `result.valid && result.variant === 'wire-02'` checks\n * to get proper claims narrowing to Wire02Claims.\n */\nexport function isWire02Result(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n return r.valid === true && r.variant === 'wire-02';\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/verify-local.ts"],"names":["jwsVerify"],"mappings":"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","file":"verify-local.mjs","sourcesContent":["/**\n * Local receipt verification with schema validation\n *\n * Use this for verifying receipts when you have the public key locally,\n * without JWKS discovery.\n */\n\nimport { verify as jwsVerify } from '@peac/crypto';\nimport { type VerificationStrictness, type VerificationWarning, HASH } from '@peac/kernel';\nimport {\n parseReceiptClaims,\n validateKernelConstraints,\n type Wire02Claims,\n checkOccurredAtSkew,\n sortWarnings,\n WARNING_TYP_MISSING,\n WARNING_TYPE_UNREGISTERED,\n WARNING_UNKNOWN_EXTENSION,\n REGISTERED_RECEIPT_TYPES,\n REGISTERED_EXTENSION_GROUP_KEYS,\n isValidExtensionKey,\n verifyPolicyBinding,\n} from '@peac/schema';\nimport type { PolicyBindingStatus } from './verifier-types';\n\n/**\n * Structural type for CryptoError\n * Used instead of instanceof for robustness across ESM/CJS boundaries\n */\ninterface CryptoErrorLike {\n name: 'CryptoError';\n code: string;\n message: string;\n}\n\n/**\n * Structural check for CryptoError\n * More robust than instanceof across module boundaries (ESM/CJS, duplicate packages)\n */\nfunction isCryptoError(err: unknown): err is CryptoErrorLike {\n return (\n err !== null &&\n typeof err === 'object' &&\n 'name' in err &&\n err.name === 'CryptoError' &&\n 'code' in err &&\n typeof err.code === 'string' &&\n err.code.startsWith('CRYPTO_') &&\n 'message' in err &&\n typeof err.message === 'string'\n );\n}\n\n/**\n * Canonical error codes for local verification\n *\n * These map to E_* codes in specs/kernel/errors.json.\n * JOSE hardening codes (E_JWS_*) are distinct from generic E_INVALID_FORMAT\n * so callers can distinguish key-injection, compression, and crit attacks from\n * ordinary format errors (v0.12.0-preview.1, DD-156).\n */\nexport type VerifyLocalErrorCode =\n | 'E_INVALID_SIGNATURE'\n | 'E_INVALID_FORMAT'\n | 'E_CONSTRAINT_VIOLATION'\n | 'E_EXPIRED'\n | 'E_NOT_YET_VALID'\n | 'E_INVALID_ISSUER'\n | 'E_INVALID_AUDIENCE'\n | 'E_INVALID_SUBJECT'\n | 'E_INVALID_RECEIPT_ID'\n | 'E_MISSING_EXP'\n | 'E_WIRE_VERSION_MISMATCH'\n | 'E_UNSUPPORTED_WIRE_VERSION'\n | 'E_OCCURRED_AT_FUTURE'\n // JOSE hardening codes (Wire 0.2, v0.12.0-preview.1, DD-156)\n | 'E_JWS_EMBEDDED_KEY'\n | 'E_JWS_CRIT_REJECTED'\n | 'E_JWS_MISSING_KID'\n | 'E_JWS_B64_REJECTED'\n | 'E_JWS_ZIP_REJECTED'\n // Policy binding (Wire 0.2, v0.12.0-preview.1, DD-151)\n | 'E_POLICY_BINDING_FAILED'\n | 'E_INTERNAL';\n\n/**\n * Options for local verification\n */\nexport interface VerifyLocalOptions {\n /**\n * Expected issuer URL\n *\n * If provided, verification fails if receipt.iss does not match.\n */\n issuer?: string;\n\n /**\n * @deprecated Wire 0.2 does not have an `aud` claim. This option is ignored.\n * Retained for source compatibility during migration; will be removed in v1.0.\n */\n audience?: string;\n\n /**\n * Expected subject URI\n *\n * If provided, verification fails if receipt.sub does not match.\n * Binds the receipt to a specific resource/interaction target.\n */\n subjectUri?: string;\n\n /**\n * @deprecated Wire 0.2 does not have a `rid` claim. Use `jti` for receipt identification.\n * This option is ignored. Retained for source compatibility; will be removed in v1.0.\n */\n rid?: string;\n\n /**\n * @deprecated Wire 0.2 receipts do not expire (permanent evidence by design).\n * This option is ignored. Retained for source compatibility; will be removed in v1.0.\n */\n requireExp?: boolean;\n\n /**\n * Current timestamp (Unix seconds)\n *\n * Defaults to Date.now() / 1000. Override for testing.\n */\n now?: number;\n\n /**\n * Maximum clock skew tolerance (seconds)\n *\n * Allows for clock drift between issuer and verifier.\n * Defaults to 300 (5 minutes).\n */\n maxClockSkew?: number;\n\n /**\n * Verification strictness profile (v0.12.0-preview.1, DD-156).\n *\n * - 'strict' (default): missing typ is a hard error before schema validation.\n * - 'interop': missing typ emits a 'typ_missing' warning and routes by payload content.\n *\n * Strictness is EXCLUSIVELY controlled here (@peac/protocol). @peac/crypto has no strictness param.\n */\n strictness?: VerificationStrictness;\n\n /**\n * Pre-computed local policy digest for policy binding (Wire 0.2, v0.12.0-preview.1, DD-151).\n *\n * Must be in 'sha256:<64 lowercase hex>' format, computed via computePolicyDigestJcs()\n * from @peac/protocol. When provided alongside a receipt that contains a policy block\n * (policy.digest), the binding check is performed:\n * - Match: policy_binding = 'verified'\n * - Mismatch: hard fail with E_POLICY_BINDING_FAILED\n * - Either absent: policy_binding = 'unavailable'\n *\n * Always 'unavailable' for Wire 0.1 receipts regardless of this option.\n */\n policyDigest?: string;\n}\n\n/**\n * Result of successful local verification (Wire 0.2 only)\n *\n * Wire 0.1 receipts are no longer accepted by verifyLocal() and return\n * E_UNSUPPORTED_WIRE_VERSION. Re-issue as Wire 0.2 using issue().\n */\nexport interface VerifyLocalSuccess {\n /** Verification succeeded */\n valid: true;\n /** Receipt variant (always 'wire-02') */\n variant: 'wire-02';\n /** Validated Wire 0.2 receipt claims */\n claims: Wire02Claims;\n /** Key ID from JWS header (for logging/indexing) */\n kid: string;\n /** Wire format version */\n wireVersion: '0.2';\n /** Verification warnings from schema parsing and strictness routing */\n warnings: VerificationWarning[];\n /**\n * Policy binding status (DD-49, DD-151).\n *\n * Three-state result:\n * - 'unavailable': either the receipt contains no policy block, or the\n * caller did not pass a policyDigest option to verifyLocal(). No check.\n * - 'verified': both digests present and match exactly.\n * - 'failed': not returned on success; verifyLocal() returns\n * E_POLICY_BINDING_FAILED (valid: false) before reaching this field.\n */\n policy_binding: PolicyBindingStatus;\n}\n\n/**\n * Result of failed local verification\n */\nexport interface VerifyLocalFailure {\n /** Verification failed */\n valid: false;\n\n /** Canonical error code (maps to specs/kernel/errors.json) */\n code: VerifyLocalErrorCode;\n\n /** Human-readable error message */\n message: string;\n\n /** Structured details for debugging (stable error code preserved in `code`) */\n details?: {\n /** Precise parse error code from unified parser (e.g. E_PARSE_COMMERCE_INVALID) */\n parse_code?: string;\n /** Zod validation issues (bounded, stable shape; non-normative, may change) */\n issues?: ReadonlyArray<{ path: string; message: string }>;\n /**\n * Policy digest from the receipt (present when code is E_POLICY_BINDING_FAILED).\n * Both are SHA-256 hashes; safe to log without leaking policy content.\n */\n receipt_policy_digest?: string;\n /** Caller-supplied policy digest (present when code is E_POLICY_BINDING_FAILED). */\n local_policy_digest?: string;\n /** policy.uri hint from the receipt (present when code is E_POLICY_BINDING_FAILED and uri set). */\n policy_uri?: string;\n };\n}\n\n/**\n * Union type for local verification result\n */\nexport type VerifyLocalResult = VerifyLocalSuccess | VerifyLocalFailure;\n\n/**\n * Internal CRYPTO_* codes that map to generic E_INVALID_FORMAT.\n * These are format/encoding errors not security-specific.\n */\nconst FORMAT_ERROR_CODES = new Set([\n 'CRYPTO_INVALID_JWS_FORMAT',\n 'CRYPTO_INVALID_TYP',\n 'CRYPTO_INVALID_ALG',\n 'CRYPTO_INVALID_KEY_LENGTH',\n]);\n\n/**\n * JOSE hardening code mapping: CRYPTO_JWS_* → specific E_JWS_* (v0.12.0-preview.1, DD-156).\n *\n * Each JOSE hazard code maps to its specific public E_JWS_* counterpart rather than\n * collapsing into the generic E_INVALID_FORMAT. This lets callers distinguish embedded-key\n * injection, crit-header abuse, and unencoded-payload attacks from ordinary format errors.\n */\nconst JOSE_CODE_MAP: Record<string, VerifyLocalErrorCode> = {\n CRYPTO_JWS_EMBEDDED_KEY: 'E_JWS_EMBEDDED_KEY',\n CRYPTO_JWS_CRIT_REJECTED: 'E_JWS_CRIT_REJECTED',\n CRYPTO_JWS_MISSING_KID: 'E_JWS_MISSING_KID',\n CRYPTO_JWS_B64_REJECTED: 'E_JWS_B64_REJECTED',\n CRYPTO_JWS_ZIP_REJECTED: 'E_JWS_ZIP_REJECTED',\n};\n\n/** Max parse issues to include in details (prevents log bloat) */\nconst MAX_PARSE_ISSUES = 25;\n\n/**\n * Sanitize Zod issues into a bounded, stable structure.\n * Avoids exposing raw Zod internals or unbounded arrays in the public API.\n */\nfunction sanitizeParseIssues(\n issues: unknown\n): ReadonlyArray<{ path: string; message: string }> | undefined {\n if (!Array.isArray(issues)) return undefined;\n return issues.slice(0, MAX_PARSE_ISSUES).map((issue) => ({\n path: Array.isArray(issue?.path) ? issue.path.join('.') : '',\n message: typeof issue?.message === 'string' ? issue.message : String(issue),\n }));\n}\n\n/**\n * Verify a Wire 0.2 PEAC receipt locally with a known public key.\n *\n * Wire 0.2 only: Wire 0.1 receipts return E_UNSUPPORTED_WIRE_VERSION.\n * Re-issue Wire 0.1 receipts as Wire 0.2 using issueWire02().\n *\n * This function:\n * 1. Verifies the Ed25519 signature and header (typ, alg)\n * 2. Applies strictness routing for missing typ (strict: hard error; interop: warning)\n * 3. Validates the receipt schema with Zod (Wire 0.2 only)\n * 4. Checks issuer/subject binding (if options provided)\n * 5. Checks time validity (iat with clock skew tolerance)\n * 6. Checks occurred_at skew and collects parse warnings\n *\n * @param jws - JWS compact serialization\n * @param publicKey - Ed25519 public key (32 bytes)\n * @param options - Optional verification options (issuer, subject, clock skew, strictness, policyDigest)\n * @returns Typed verification result\n *\n * @example\n * ```typescript\n * const result = await verifyLocal(jws, publicKey, {\n * issuer: 'https://api.example.com',\n * strictness: 'strict',\n * });\n * if (result.valid) {\n * console.log('Kind:', result.claims.kind);\n * console.log('Warnings:', result.warnings);\n * }\n * ```\n */\nexport async function verifyLocal(\n jws: string,\n publicKey: Uint8Array,\n options: VerifyLocalOptions = {}\n): Promise<VerifyLocalResult> {\n const { issuer, subjectUri, maxClockSkew = 300, strictness = 'strict', policyDigest } = options;\n const now = options.now ?? Math.floor(Date.now() / 1000);\n\n try {\n // 1. Verify signature and header (typ, alg validated by @peac/crypto)\n const result = await jwsVerify<unknown>(jws, publicKey);\n\n if (!result.valid) {\n return {\n valid: false,\n code: 'E_INVALID_SIGNATURE',\n message: 'Ed25519 signature verification failed',\n };\n }\n\n // Accumulated warnings for Wire 0.2 path\n const accumulatedWarnings: VerificationWarning[] = [];\n\n // 2. Strictness routing for missing typ (Correction 1, DD-156)\n if (result.header.typ === undefined) {\n if (strictness === 'strict') {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: 'Missing JWS typ header: strict mode requires typ to be present',\n };\n }\n // interop mode: emit warning and continue\n accumulatedWarnings.push({\n code: WARNING_TYP_MISSING,\n message: 'JWS typ header is absent; accepted in interop mode',\n });\n }\n\n // 3. Validate structural kernel constraints (DD-121, fail-closed)\n const constraintResult = validateKernelConstraints(result.payload);\n if (!constraintResult.valid) {\n const v = constraintResult.violations[0];\n return {\n valid: false,\n code: 'E_CONSTRAINT_VIOLATION',\n message: `Kernel constraint violated: ${v.constraint} (actual: ${v.actual}, limit: ${v.limit})`,\n };\n }\n\n // 4. Validate schema (unified parser supports Wire 0.1 and Wire 0.2)\n const pr = parseReceiptClaims(result.payload);\n\n if (!pr.ok) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: `Receipt schema validation failed: ${pr.error.message}`,\n details: { parse_code: pr.error.code, issues: sanitizeParseIssues(pr.error.issues) },\n };\n }\n\n // 5. Collect parser warnings (Wire 0.2 parser may emit type/extension warnings)\n if (pr.wireVersion === '0.2') {\n accumulatedWarnings.push(...pr.warnings);\n }\n\n // Wire 0.2 path\n if (pr.wireVersion === '0.2') {\n const claims = pr.claims as Wire02Claims;\n\n // Issuer check\n if (issuer !== undefined && claims.iss !== issuer) {\n return {\n valid: false,\n code: 'E_INVALID_ISSUER',\n message: `Issuer mismatch: expected \"${issuer}\", got \"${claims.iss}\"`,\n };\n }\n\n // Subject check\n if (subjectUri !== undefined && claims.sub !== subjectUri) {\n return {\n valid: false,\n code: 'E_INVALID_SUBJECT',\n message: `Subject mismatch: expected \"${subjectUri}\", got \"${claims.sub ?? 'undefined'}\"`,\n };\n }\n\n // iat: not-yet-valid check (with clock skew)\n if (claims.iat > now + maxClockSkew) {\n return {\n valid: false,\n code: 'E_NOT_YET_VALID',\n message: `Receipt not yet valid: issued at ${new Date(claims.iat * 1000).toISOString()}, now is ${new Date(now * 1000).toISOString()}`,\n };\n }\n\n // occurred_at skew check (evidence kind only)\n if (claims.kind === 'evidence') {\n const skewResult = checkOccurredAtSkew(claims.occurred_at, claims.iat, now, maxClockSkew);\n if (skewResult === 'future_error') {\n return {\n valid: false,\n code: 'E_OCCURRED_AT_FUTURE',\n message: `occurred_at is in the future beyond tolerance (${maxClockSkew}s)`,\n };\n }\n if (skewResult !== null) {\n accumulatedWarnings.push(skewResult);\n }\n }\n\n // Emit type_unregistered warning for valid-but-unregistered type values (DD-155)\n if (!REGISTERED_RECEIPT_TYPES.has(claims.type)) {\n accumulatedWarnings.push({\n code: WARNING_TYPE_UNREGISTERED,\n message: 'Receipt type is not in the recommended type registry',\n pointer: '/type',\n });\n }\n\n // Emit unknown_extension_preserved warnings for unrecognized-but-well-formed keys (DD-155)\n // Malformed keys are already hard errors (E_INVALID_EXTENSION_KEY) at schema layer.\n if (claims.extensions !== undefined) {\n for (const key of Object.keys(claims.extensions)) {\n if (!REGISTERED_EXTENSION_GROUP_KEYS.has(key) && isValidExtensionKey(key)) {\n // RFC 6901: '~' -> '~0', '/' -> '~1'\n const escapedKey = key.replace(/~/g, '~0').replace(/\\//g, '~1');\n accumulatedWarnings.push({\n code: WARNING_UNKNOWN_EXTENSION,\n message: 'Unknown extension key preserved without schema validation',\n pointer: `/extensions/${escapedKey}`,\n });\n }\n }\n }\n\n // Validate policyDigest option format (DD-151): must be sha256:<64 lowercase hex> if provided.\n if (policyDigest !== undefined && !HASH.pattern.test(policyDigest)) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: 'policyDigest option must be in sha256:<64 lowercase hex> format',\n };\n }\n\n // Policy binding check (DD-151): 3-state result.\n // 'unavailable' when either receipt has no policy block or caller omitted policyDigest.\n // 'verified' / 'failed' when both are present; 'failed' is a hard verification error.\n const receiptPolicyDigest = claims.policy?.digest;\n const bindingStatus: PolicyBindingStatus =\n receiptPolicyDigest === undefined || policyDigest === undefined\n ? 'unavailable'\n : verifyPolicyBinding(receiptPolicyDigest, policyDigest);\n if (bindingStatus === 'failed') {\n return {\n valid: false,\n code: 'E_POLICY_BINDING_FAILED',\n message: 'Policy binding check failed: receipt policy digest does not match local policy',\n details: {\n receipt_policy_digest: receiptPolicyDigest,\n local_policy_digest: policyDigest,\n ...(claims.policy?.uri !== undefined && { policy_uri: claims.policy.uri }),\n },\n };\n }\n\n return {\n valid: true,\n variant: 'wire-02',\n claims,\n kid: result.header.kid,\n wireVersion: '0.2',\n warnings: sortWarnings(accumulatedWarnings),\n policy_binding: bindingStatus,\n };\n }\n\n // Wire 0.1 receipts: reject with E_UNSUPPORTED_WIRE_VERSION.\n return {\n valid: false,\n code: 'E_UNSUPPORTED_WIRE_VERSION',\n message: 'Wire 0.1 receipts are not supported. Re-issue as Wire 0.2 using issue().',\n };\n } catch (err) {\n // Handle typed CryptoError from @peac/crypto\n // Use structural check instead of instanceof for robustness across ESM/CJS boundaries\n // Map internal CRYPTO_* codes to canonical E_* codes.\n // JOSE hardening codes get specific E_JWS_* (not generic E_INVALID_FORMAT) so callers\n // can distinguish key-injection attacks from ordinary encoding errors.\n if (isCryptoError(err)) {\n // 1. JOSE hardening: specific E_JWS_* codes (checked first)\n if (Object.prototype.hasOwnProperty.call(JOSE_CODE_MAP, err.code)) {\n return {\n valid: false,\n code: JOSE_CODE_MAP[err.code]!,\n message: err.message,\n };\n }\n // 2. Generic format errors\n if (FORMAT_ERROR_CODES.has(err.code)) {\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: err.message,\n };\n }\n if (err.code === 'CRYPTO_INVALID_SIGNATURE') {\n return {\n valid: false,\n code: 'E_INVALID_SIGNATURE',\n message: err.message,\n };\n }\n if (err.code === 'CRYPTO_WIRE_VERSION_MISMATCH') {\n return {\n valid: false,\n code: 'E_WIRE_VERSION_MISMATCH',\n message: err.message,\n };\n }\n }\n\n // Handle JSON parse errors from malformed payloads\n // Use structural check for cross-boundary robustness (consistent with isCryptoError pattern)\n if (\n err !== null &&\n typeof err === 'object' &&\n 'name' in err &&\n (err as { name: unknown }).name === 'SyntaxError'\n ) {\n const syntaxMessage =\n 'message' in err && typeof (err as { message: unknown }).message === 'string'\n ? (err as { message: string }).message\n : 'Invalid JSON';\n return {\n valid: false,\n code: 'E_INVALID_FORMAT',\n message: `Invalid receipt payload: ${syntaxMessage}`,\n };\n }\n\n // All other errors -> E_INTERNAL\n // No message parsing - code-based mapping only\n const message = err instanceof Error ? err.message : String(err);\n return {\n valid: false,\n code: 'E_INTERNAL',\n message: `Unexpected verification error: ${message}`,\n };\n }\n}\n\n/**\n * @deprecated Removed: verifyLocal() is Wire 0.2 only and always returns variant 'wire-02'.\n * This guard always returns false. Remove usage and use isWire02Result() instead.\n */\nexport function isCommerceResult(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n // Always false: verifyLocal() only returns variant 'wire-02'\n return false;\n}\n\n/**\n * @deprecated Removed: verifyLocal() is Wire 0.2 only and always returns variant 'wire-02'.\n * This guard always returns false. Remove usage and use isWire02Result() instead.\n */\nexport function isAttestationResult(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n // Always false: verifyLocal() only returns variant 'wire-02'\n return false;\n}\n\n/**\n * Type guard: narrows a VerifyLocalResult to a Wire 0.2 success (v0.12.0-preview.1).\n *\n * Use instead of manual `result.valid && result.variant === 'wire-02'` checks\n * to get proper claims narrowing to Wire02Claims.\n */\nexport function isWire02Result(\n r: VerifyLocalResult\n): r is VerifyLocalSuccess & { variant: 'wire-02' } {\n return r.valid === true && r.variant === 'wire-02';\n}\n"]}
|
package/dist/verify.d.ts
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
import { PEACReceiptClaims, SubjectProfileSnapshot } from '@peac/schema';
|
|
9
9
|
import { type TelemetryHook } from './telemetry.js';
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Wire 0.1 verification result.
|
|
12
|
+
* @deprecated Wire 0.1 is frozen legacy. Use {@link verifyLocal} (from `verify-local.ts`)
|
|
13
|
+
* for the current stable format.
|
|
12
14
|
*/
|
|
13
15
|
export interface VerifyResult {
|
|
14
16
|
/** Verification succeeded */
|
|
@@ -24,7 +26,8 @@ export interface VerifyResult {
|
|
|
24
26
|
};
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
|
-
*
|
|
29
|
+
* Wire 0.1 verification failure.
|
|
30
|
+
* @deprecated Wire 0.1 is frozen legacy. Use {@link verifyLocal} for the current stable format.
|
|
28
31
|
*/
|
|
29
32
|
export interface VerifyFailure {
|
|
30
33
|
/** Verification failed */
|
|
@@ -35,7 +38,8 @@ export interface VerifyFailure {
|
|
|
35
38
|
details?: string;
|
|
36
39
|
}
|
|
37
40
|
/**
|
|
38
|
-
*
|
|
41
|
+
* Wire 0.1 verification options.
|
|
42
|
+
* @deprecated Wire 0.1 is frozen legacy. Use {@link verifyLocal} for the current stable format.
|
|
39
43
|
*/
|
|
40
44
|
export interface VerifyOptions {
|
|
41
45
|
/** JWS compact serialization */
|
|
@@ -46,11 +50,14 @@ export interface VerifyOptions {
|
|
|
46
50
|
telemetry?: TelemetryHook;
|
|
47
51
|
}
|
|
48
52
|
/**
|
|
49
|
-
* Verify a PEAC receipt JWS
|
|
53
|
+
* Verify a Wire 0.1 PEAC receipt JWS via issuer-config discovery.
|
|
50
54
|
*
|
|
51
55
|
* Uses strict issuer-config discovery: peac-issuer.json -> jwks_uri -> JWKS.
|
|
52
56
|
* No fallback to peac.txt or direct JWKS endpoints.
|
|
53
57
|
*
|
|
58
|
+
* @deprecated Wire 0.1 is frozen legacy. Use {@link verifyLocal} for the current stable
|
|
59
|
+
* format (Interaction Record format, `interaction-record+jwt`).
|
|
60
|
+
*
|
|
54
61
|
* @param optionsOrJws - Verify options or JWS compact serialization (for backwards compatibility)
|
|
55
62
|
* @returns Verification result or failure
|
|
56
63
|
*/
|
package/dist/verify.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,iBAAiB,EAEjB,sBAAsB,EAGvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAkC,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAmBpF
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,iBAAiB,EAEjB,sBAAsB,EAGvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAkC,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAmBpF;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,EAAE,EAAE,IAAI,CAAC;IAET,qBAAqB;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAE1B,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAE1C,0BAA0B;IAC1B,IAAI,CAAC,EAAE;QACL,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,EAAE,EAAE,KAAK,CAAC;IAEV,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAC;IAEf,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IAEnB,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAE1C,iDAAiD;IACjD,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CACjC,YAAY,EAAE,MAAM,GAAG,aAAa,GACnC,OAAO,CAAC,YAAY,GAAG,aAAa,CAAC,CAkKvC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peac/protocol",
|
|
3
|
-
"version": "0.12.0
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "PEAC protocol implementation - receipt issuance and verification",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"uuidv7": "^0.6.3",
|
|
41
41
|
"zod": "^4.3.6",
|
|
42
|
-
"@peac/kernel": "0.12.0
|
|
43
|
-
"@peac/
|
|
44
|
-
"@peac/
|
|
42
|
+
"@peac/kernel": "0.12.0",
|
|
43
|
+
"@peac/schema": "0.12.0",
|
|
44
|
+
"@peac/crypto": "0.12.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^22.19.11",
|