@peac/protocol 0.10.7 → 0.10.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crypto-utils.d.ts +9 -0
- package/dist/crypto-utils.d.ts.map +1 -0
- package/dist/crypto-utils.js +21 -0
- package/dist/crypto-utils.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/pointer-fetch.d.ts +86 -0
- package/dist/pointer-fetch.d.ts.map +1 -0
- package/dist/pointer-fetch.js +305 -0
- package/dist/pointer-fetch.js.map +1 -0
- package/dist/ssrf-safe-fetch.d.ts +205 -0
- package/dist/ssrf-safe-fetch.d.ts.map +1 -0
- package/dist/ssrf-safe-fetch.js +671 -0
- package/dist/ssrf-safe-fetch.js.map +1 -0
- package/dist/transport-profiles.d.ts +115 -0
- package/dist/transport-profiles.d.ts.map +1 -0
- package/dist/transport-profiles.js +424 -0
- package/dist/transport-profiles.js.map +1 -0
- package/dist/verification-report.d.ts +135 -0
- package/dist/verification-report.d.ts.map +1 -0
- package/dist/verification-report.js +322 -0
- package/dist/verification-report.js.map +1 -0
- package/dist/verifier-core.d.ts +62 -0
- package/dist/verifier-core.d.ts.map +1 -0
- package/dist/verifier-core.js +578 -0
- package/dist/verifier-core.js.map +1 -0
- package/dist/verifier-types.d.ts +328 -0
- package/dist/verifier-types.d.ts.map +1 -0
- package/dist/verifier-types.js +161 -0
- package/dist/verifier-types.js.map +1 -0
- package/package.json +17 -5
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cryptographic utilities for PEAC verifiers
|
|
3
|
+
*
|
|
4
|
+
* @deprecated Use @peac/crypto directly instead. This re-export exists for backwards compatibility.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
export { base64urlDecode, base64urlEncode, bytesToHex, computeJwkThumbprint, hexToBytes, jwkToPublicKeyBytes, sha256Bytes, sha256Hex, } from '@peac/crypto';
|
|
9
|
+
//# sourceMappingURL=crypto-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-utils.d.ts","sourceRoot":"","sources":["../src/crypto-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,eAAe,EACf,eAAe,EACf,UAAU,EACV,oBAAoB,EACpB,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,SAAS,GACV,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cryptographic utilities for PEAC verifiers
|
|
4
|
+
*
|
|
5
|
+
* @deprecated Use @peac/crypto directly instead. This re-export exists for backwards compatibility.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.sha256Hex = exports.sha256Bytes = exports.jwkToPublicKeyBytes = exports.hexToBytes = exports.computeJwkThumbprint = exports.bytesToHex = exports.base64urlEncode = exports.base64urlDecode = void 0;
|
|
11
|
+
// Re-export all crypto utilities from @peac/crypto for backwards compatibility
|
|
12
|
+
var crypto_1 = require("@peac/crypto");
|
|
13
|
+
Object.defineProperty(exports, "base64urlDecode", { enumerable: true, get: function () { return crypto_1.base64urlDecode; } });
|
|
14
|
+
Object.defineProperty(exports, "base64urlEncode", { enumerable: true, get: function () { return crypto_1.base64urlEncode; } });
|
|
15
|
+
Object.defineProperty(exports, "bytesToHex", { enumerable: true, get: function () { return crypto_1.bytesToHex; } });
|
|
16
|
+
Object.defineProperty(exports, "computeJwkThumbprint", { enumerable: true, get: function () { return crypto_1.computeJwkThumbprint; } });
|
|
17
|
+
Object.defineProperty(exports, "hexToBytes", { enumerable: true, get: function () { return crypto_1.hexToBytes; } });
|
|
18
|
+
Object.defineProperty(exports, "jwkToPublicKeyBytes", { enumerable: true, get: function () { return crypto_1.jwkToPublicKeyBytes; } });
|
|
19
|
+
Object.defineProperty(exports, "sha256Bytes", { enumerable: true, get: function () { return crypto_1.sha256Bytes; } });
|
|
20
|
+
Object.defineProperty(exports, "sha256Hex", { enumerable: true, get: function () { return crypto_1.sha256Hex; } });
|
|
21
|
+
//# sourceMappingURL=crypto-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-utils.js","sourceRoot":"","sources":["../src/crypto-utils.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,+EAA+E;AAC/E,uCASsB;AARpB,yGAAA,eAAe,OAAA;AACf,yGAAA,eAAe,OAAA;AACf,oGAAA,UAAU,OAAA;AACV,8GAAA,oBAAoB,OAAA;AACpB,oGAAA,UAAU,OAAA;AACV,6GAAA,mBAAmB,OAAA;AACnB,qGAAA,WAAW,OAAA;AACX,mGAAA,SAAS,OAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,5 +7,11 @@ export * from './verify';
|
|
|
7
7
|
export * from './verify-local';
|
|
8
8
|
export * from './headers';
|
|
9
9
|
export * from './discovery';
|
|
10
|
-
export
|
|
10
|
+
export * from './verifier-types';
|
|
11
|
+
export * from './verifier-core';
|
|
12
|
+
export * from './verification-report';
|
|
13
|
+
export * from './ssrf-safe-fetch';
|
|
14
|
+
export * from './transport-profiles';
|
|
15
|
+
export * from './pointer-fetch';
|
|
16
|
+
export { base64urlDecode, base64urlEncode, computeJwkThumbprint, generateKeypair, jwkToPublicKeyBytes, sha256Bytes, sha256Hex, verify, } from '@peac/crypto';
|
|
11
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAG5B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAG5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAGhC,OAAO,EACL,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,SAAS,EACT,MAAM,GACP,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -18,14 +18,27 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
18
18
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.verify = exports.generateKeypair = void 0;
|
|
21
|
+
exports.verify = exports.sha256Hex = exports.sha256Bytes = exports.jwkToPublicKeyBytes = exports.generateKeypair = exports.computeJwkThumbprint = exports.base64urlEncode = exports.base64urlDecode = void 0;
|
|
22
22
|
__exportStar(require("./issue"), exports);
|
|
23
23
|
__exportStar(require("./verify"), exports);
|
|
24
24
|
__exportStar(require("./verify-local"), exports);
|
|
25
25
|
__exportStar(require("./headers"), exports);
|
|
26
26
|
__exportStar(require("./discovery"), exports);
|
|
27
|
+
// Verifier core (v0.10.8+)
|
|
28
|
+
__exportStar(require("./verifier-types"), exports);
|
|
29
|
+
__exportStar(require("./verifier-core"), exports);
|
|
30
|
+
__exportStar(require("./verification-report"), exports);
|
|
31
|
+
__exportStar(require("./ssrf-safe-fetch"), exports);
|
|
32
|
+
__exportStar(require("./transport-profiles"), exports);
|
|
33
|
+
__exportStar(require("./pointer-fetch"), exports);
|
|
27
34
|
// Re-export crypto utilities for single-package quickstart
|
|
28
35
|
var crypto_1 = require("@peac/crypto");
|
|
36
|
+
Object.defineProperty(exports, "base64urlDecode", { enumerable: true, get: function () { return crypto_1.base64urlDecode; } });
|
|
37
|
+
Object.defineProperty(exports, "base64urlEncode", { enumerable: true, get: function () { return crypto_1.base64urlEncode; } });
|
|
38
|
+
Object.defineProperty(exports, "computeJwkThumbprint", { enumerable: true, get: function () { return crypto_1.computeJwkThumbprint; } });
|
|
29
39
|
Object.defineProperty(exports, "generateKeypair", { enumerable: true, get: function () { return crypto_1.generateKeypair; } });
|
|
40
|
+
Object.defineProperty(exports, "jwkToPublicKeyBytes", { enumerable: true, get: function () { return crypto_1.jwkToPublicKeyBytes; } });
|
|
41
|
+
Object.defineProperty(exports, "sha256Bytes", { enumerable: true, get: function () { return crypto_1.sha256Bytes; } });
|
|
42
|
+
Object.defineProperty(exports, "sha256Hex", { enumerable: true, get: function () { return crypto_1.sha256Hex; } });
|
|
30
43
|
Object.defineProperty(exports, "verify", { enumerable: true, get: function () { return crypto_1.verify; } });
|
|
31
44
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,0CAAwB;AACxB,2CAAyB;AACzB,iDAA+B;AAC/B,4CAA0B;AAC1B,8CAA4B;AAE5B,2DAA2D;AAC3D,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,0CAAwB;AACxB,2CAAyB;AACzB,iDAA+B;AAC/B,4CAA0B;AAC1B,8CAA4B;AAE5B,2BAA2B;AAC3B,mDAAiC;AACjC,kDAAgC;AAChC,wDAAsC;AACtC,oDAAkC;AAClC,uDAAqC;AACrC,kDAAgC;AAEhC,2DAA2D;AAC3D,uCASsB;AARpB,yGAAA,eAAe,OAAA;AACf,yGAAA,eAAe,OAAA;AACf,8GAAA,oBAAoB,OAAA;AACpB,yGAAA,eAAe,OAAA;AACf,6GAAA,mBAAmB,OAAA;AACnB,qGAAA,WAAW,OAAA;AACX,mGAAA,SAAS,OAAA;AACT,gGAAA,MAAM,OAAA"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PEAC Pointer Fetch with Digest Verification
|
|
3
|
+
*
|
|
4
|
+
* Implements secure receipt fetching via pointers per TRANSPORT-PROFILES.md:
|
|
5
|
+
* - SSRF-safe fetch
|
|
6
|
+
* - SHA-256 digest verification
|
|
7
|
+
* - Size limits
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
import { type SSRFFetchOptions } from './ssrf-safe-fetch.js';
|
|
12
|
+
/**
|
|
13
|
+
* Pointer fetch options
|
|
14
|
+
*/
|
|
15
|
+
export interface PointerFetchOptions {
|
|
16
|
+
/** URL to fetch the receipt from */
|
|
17
|
+
url: string;
|
|
18
|
+
/** Expected SHA-256 digest (lowercase hex, 64 chars) */
|
|
19
|
+
expectedDigest: string;
|
|
20
|
+
/** Optional SSRF fetch options */
|
|
21
|
+
fetchOptions?: Omit<SSRFFetchOptions, 'maxBytes'>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Successful pointer fetch result
|
|
25
|
+
*/
|
|
26
|
+
export interface PointerFetchSuccess {
|
|
27
|
+
ok: true;
|
|
28
|
+
/** Fetched receipt (JWS compact serialization) */
|
|
29
|
+
receipt: string;
|
|
30
|
+
/** Actual SHA-256 digest of fetched content */
|
|
31
|
+
actualDigest: string;
|
|
32
|
+
/** Whether digest matched expected */
|
|
33
|
+
digestMatched: true;
|
|
34
|
+
/** Content-Type header (if present) */
|
|
35
|
+
contentType?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Warning about unexpected Content-Type.
|
|
38
|
+
* Present when Content-Type is not application/jose, application/json, or text/plain.
|
|
39
|
+
* Does not cause rejection (for interoperability) but callers may want to log.
|
|
40
|
+
*/
|
|
41
|
+
contentTypeWarning?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Failed pointer fetch result
|
|
45
|
+
*/
|
|
46
|
+
export interface PointerFetchError {
|
|
47
|
+
ok: false;
|
|
48
|
+
/** Error reason */
|
|
49
|
+
reason: 'pointer_fetch_blocked' | 'pointer_fetch_failed' | 'pointer_fetch_timeout' | 'pointer_fetch_too_large' | 'pointer_digest_mismatch' | 'malformed_receipt';
|
|
50
|
+
/** Error code for reports */
|
|
51
|
+
errorCode: string;
|
|
52
|
+
/** Human-readable error message */
|
|
53
|
+
message: string;
|
|
54
|
+
/** Actual digest if computed (for mismatch errors) */
|
|
55
|
+
actualDigest?: string;
|
|
56
|
+
/** Expected digest */
|
|
57
|
+
expectedDigest?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Pointer fetch result
|
|
61
|
+
*/
|
|
62
|
+
export type PointerFetchResult = PointerFetchSuccess | PointerFetchError;
|
|
63
|
+
/**
|
|
64
|
+
* Fetch a receipt via pointer with digest verification
|
|
65
|
+
*
|
|
66
|
+
* Per TRANSPORT-PROFILES.md:
|
|
67
|
+
* - Fetch the URL using SSRF-safe fetch
|
|
68
|
+
* - Compute SHA-256 digest of response
|
|
69
|
+
* - Verify digest matches expected value from header
|
|
70
|
+
* - Return receipt only if digest matches
|
|
71
|
+
*
|
|
72
|
+
* @param options - Pointer fetch options
|
|
73
|
+
* @returns Fetch result
|
|
74
|
+
*/
|
|
75
|
+
export declare function fetchPointerWithDigest(options: PointerFetchOptions): Promise<PointerFetchResult>;
|
|
76
|
+
/**
|
|
77
|
+
* Verify a pointer header and fetch the receipt
|
|
78
|
+
*
|
|
79
|
+
* Combines parsing and fetching in a single operation.
|
|
80
|
+
*
|
|
81
|
+
* @param pointerHeader - PEAC-Receipt-Pointer header value
|
|
82
|
+
* @param fetchOptions - Optional SSRF fetch options
|
|
83
|
+
* @returns Fetch result
|
|
84
|
+
*/
|
|
85
|
+
export declare function verifyAndFetchPointer(pointerHeader: string, fetchOptions?: Omit<SSRFFetchOptions, 'maxBytes'>): Promise<PointerFetchResult>;
|
|
86
|
+
//# sourceMappingURL=pointer-fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer-fetch.d.ts","sourceRoot":"","sources":["../src/pointer-fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAiB,KAAK,gBAAgB,EAAuB,MAAM,sBAAsB,CAAC;AAMjG;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,wDAAwD;IACxD,cAAc,EAAE,MAAM,CAAC;IACvB,kCAAkC;IAClC,YAAY,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,IAAI,CAAC;IACT,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,aAAa,EAAE,IAAI,CAAC;IACpB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,KAAK,CAAC;IACV,mBAAmB;IACnB,MAAM,EACF,uBAAuB,GACvB,sBAAsB,GACtB,uBAAuB,GACvB,yBAAyB,GACzB,yBAAyB,GACzB,mBAAmB,CAAC;IACxB,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,GAAG,iBAAiB,CAAC;AAwDzE;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CA4G7B;AAyGD;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,MAAM,EACrB,YAAY,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,GAChD,OAAO,CAAC,kBAAkB,CAAC,CA6B7B"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PEAC Pointer Fetch with Digest Verification
|
|
4
|
+
*
|
|
5
|
+
* Implements secure receipt fetching via pointers per TRANSPORT-PROFILES.md:
|
|
6
|
+
* - SSRF-safe fetch
|
|
7
|
+
* - SHA-256 digest verification
|
|
8
|
+
* - Size limits
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.fetchPointerWithDigest = fetchPointerWithDigest;
|
|
14
|
+
exports.verifyAndFetchPointer = verifyAndFetchPointer;
|
|
15
|
+
const crypto_1 = require("@peac/crypto");
|
|
16
|
+
const kernel_1 = require("@peac/kernel");
|
|
17
|
+
const ssrf_safe_fetch_js_1 = require("./ssrf-safe-fetch.js");
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Error Mapping
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
/**
|
|
22
|
+
* Map SSRF error reason to pointer error reason
|
|
23
|
+
*/
|
|
24
|
+
function mapSsrfError(ssrfError) {
|
|
25
|
+
const reason = ssrfError.reason;
|
|
26
|
+
switch (reason) {
|
|
27
|
+
case 'not_https':
|
|
28
|
+
case 'private_ip':
|
|
29
|
+
case 'loopback':
|
|
30
|
+
case 'link_local':
|
|
31
|
+
case 'dns_failure':
|
|
32
|
+
case 'cross_origin_redirect':
|
|
33
|
+
return {
|
|
34
|
+
ok: false,
|
|
35
|
+
reason: 'pointer_fetch_blocked',
|
|
36
|
+
errorCode: 'E_VERIFY_POINTER_FETCH_BLOCKED',
|
|
37
|
+
message: ssrfError.message,
|
|
38
|
+
};
|
|
39
|
+
case 'timeout':
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
reason: 'pointer_fetch_timeout',
|
|
43
|
+
errorCode: 'E_VERIFY_POINTER_FETCH_TIMEOUT',
|
|
44
|
+
message: ssrfError.message,
|
|
45
|
+
};
|
|
46
|
+
case 'response_too_large':
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
reason: 'pointer_fetch_too_large',
|
|
50
|
+
errorCode: 'E_VERIFY_POINTER_FETCH_TOO_LARGE',
|
|
51
|
+
message: ssrfError.message,
|
|
52
|
+
};
|
|
53
|
+
default:
|
|
54
|
+
return {
|
|
55
|
+
ok: false,
|
|
56
|
+
reason: 'pointer_fetch_failed',
|
|
57
|
+
errorCode: 'E_VERIFY_POINTER_FETCH_FAILED',
|
|
58
|
+
message: ssrfError.message,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// Pointer Fetch
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
/**
|
|
66
|
+
* Fetch a receipt via pointer with digest verification
|
|
67
|
+
*
|
|
68
|
+
* Per TRANSPORT-PROFILES.md:
|
|
69
|
+
* - Fetch the URL using SSRF-safe fetch
|
|
70
|
+
* - Compute SHA-256 digest of response
|
|
71
|
+
* - Verify digest matches expected value from header
|
|
72
|
+
* - Return receipt only if digest matches
|
|
73
|
+
*
|
|
74
|
+
* @param options - Pointer fetch options
|
|
75
|
+
* @returns Fetch result
|
|
76
|
+
*/
|
|
77
|
+
async function fetchPointerWithDigest(options) {
|
|
78
|
+
const { url, expectedDigest, fetchOptions = {} } = options;
|
|
79
|
+
// Validate expected digest format
|
|
80
|
+
const hexRegex = /^[0-9a-f]{64}$/;
|
|
81
|
+
if (!hexRegex.test(expectedDigest)) {
|
|
82
|
+
return {
|
|
83
|
+
ok: false,
|
|
84
|
+
reason: 'pointer_fetch_failed',
|
|
85
|
+
errorCode: 'E_VERIFY_POINTER_FETCH_FAILED',
|
|
86
|
+
message: 'Invalid expected digest: must be 64 lowercase hex characters',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// Validate URL is HTTPS (pre-check before fetch)
|
|
90
|
+
try {
|
|
91
|
+
const parsedUrl = new URL(url);
|
|
92
|
+
if (parsedUrl.protocol !== 'https:') {
|
|
93
|
+
return {
|
|
94
|
+
ok: false,
|
|
95
|
+
reason: 'pointer_fetch_blocked',
|
|
96
|
+
errorCode: 'E_VERIFY_POINTER_FETCH_BLOCKED',
|
|
97
|
+
message: 'Pointer URL must use HTTPS',
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return {
|
|
103
|
+
ok: false,
|
|
104
|
+
reason: 'pointer_fetch_failed',
|
|
105
|
+
errorCode: 'E_VERIFY_POINTER_FETCH_FAILED',
|
|
106
|
+
message: 'Invalid pointer URL',
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// Fetch with SSRF protection and DoS bounds
|
|
110
|
+
// - Size cap: maxReceiptBytes (prevents memory exhaustion)
|
|
111
|
+
// - No redirects: prevents redirect-based SSRF (pointer URL must be direct)
|
|
112
|
+
// - Timeout: prevents slow-loris style attacks
|
|
113
|
+
const fetchResult = await (0, ssrf_safe_fetch_js_1.ssrfSafeFetch)(url, {
|
|
114
|
+
...fetchOptions,
|
|
115
|
+
maxBytes: kernel_1.VERIFIER_LIMITS.maxReceiptBytes,
|
|
116
|
+
allowRedirects: false, // Pointer URL must be direct - no redirects
|
|
117
|
+
timeoutMs: fetchOptions?.timeoutMs ?? kernel_1.VERIFIER_LIMITS.fetchTimeoutMs,
|
|
118
|
+
headers: {
|
|
119
|
+
Accept: 'application/jose, application/json, text/plain',
|
|
120
|
+
...fetchOptions.headers,
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
if (!fetchResult.ok) {
|
|
124
|
+
return mapSsrfError(fetchResult);
|
|
125
|
+
}
|
|
126
|
+
const receipt = fetchResult.body;
|
|
127
|
+
// Validate Content-Type if present (warn but don't reject for interoperability)
|
|
128
|
+
// Expected: application/jose, application/json, or text/plain
|
|
129
|
+
const contentType = fetchResult.contentType;
|
|
130
|
+
const expectedContentTypes = ['application/jose', 'application/json', 'text/plain'];
|
|
131
|
+
const contentTypeWarning = contentType && !expectedContentTypes.some((expected) => contentType.startsWith(expected))
|
|
132
|
+
? `Unexpected Content-Type: ${contentType}; expected application/jose, application/json, or text/plain`
|
|
133
|
+
: undefined;
|
|
134
|
+
// Validate: reject empty body
|
|
135
|
+
if (!receipt || receipt.trim().length === 0) {
|
|
136
|
+
return {
|
|
137
|
+
ok: false,
|
|
138
|
+
reason: 'malformed_receipt',
|
|
139
|
+
errorCode: 'E_VERIFY_MALFORMED_RECEIPT',
|
|
140
|
+
message: 'Pointer target returned empty content',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
// Validate: content must look like JWS compact serialization (3 dot-separated segments)
|
|
144
|
+
const jwsValidation = validateJwsCompactStructure(receipt);
|
|
145
|
+
if (!jwsValidation.valid) {
|
|
146
|
+
return {
|
|
147
|
+
ok: false,
|
|
148
|
+
reason: 'malformed_receipt',
|
|
149
|
+
errorCode: 'E_VERIFY_MALFORMED_RECEIPT',
|
|
150
|
+
message: jwsValidation.message,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// Compute digest of fetched content (hash the raw string bytes)
|
|
154
|
+
const actualDigest = await (0, crypto_1.sha256Hex)(receipt);
|
|
155
|
+
// Verify digest matches
|
|
156
|
+
if (actualDigest !== expectedDigest) {
|
|
157
|
+
return {
|
|
158
|
+
ok: false,
|
|
159
|
+
reason: 'pointer_digest_mismatch',
|
|
160
|
+
errorCode: 'E_VERIFY_POINTER_DIGEST_MISMATCH',
|
|
161
|
+
message: 'Fetched receipt digest does not match expected digest',
|
|
162
|
+
actualDigest,
|
|
163
|
+
expectedDigest,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
ok: true,
|
|
168
|
+
receipt,
|
|
169
|
+
actualDigest,
|
|
170
|
+
digestMatched: true,
|
|
171
|
+
contentType: fetchResult.contentType,
|
|
172
|
+
...(contentTypeWarning && { contentTypeWarning }),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Validate that a string looks like JWS compact serialization
|
|
177
|
+
*
|
|
178
|
+
* A valid JWS compact has exactly 3 dot-separated base64url segments.
|
|
179
|
+
*
|
|
180
|
+
* @param value - String to validate
|
|
181
|
+
* @returns Validation result
|
|
182
|
+
*/
|
|
183
|
+
function validateJwsCompactStructure(value) {
|
|
184
|
+
const segments = value.split('.');
|
|
185
|
+
if (segments.length !== 3) {
|
|
186
|
+
return {
|
|
187
|
+
valid: false,
|
|
188
|
+
message: `Invalid JWS compact serialization: expected 3 segments, got ${segments.length}`,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// All segments must be non-empty and contain only base64url characters
|
|
192
|
+
const base64urlRegex = /^[A-Za-z0-9_-]+$/;
|
|
193
|
+
for (let i = 0; i < segments.length; i++) {
|
|
194
|
+
const segment = segments[i];
|
|
195
|
+
if (segment.length === 0) {
|
|
196
|
+
return {
|
|
197
|
+
valid: false,
|
|
198
|
+
message: `Invalid JWS compact serialization: segment ${i + 1} is empty`,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
if (!base64urlRegex.test(segment)) {
|
|
202
|
+
return {
|
|
203
|
+
valid: false,
|
|
204
|
+
message: `Invalid JWS compact serialization: segment ${i + 1} contains invalid characters`,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return { valid: true };
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Parse pointer header key=value pairs (ReDoS-safe)
|
|
212
|
+
*
|
|
213
|
+
* Handles both quoted and unquoted values without complex regex alternation.
|
|
214
|
+
*/
|
|
215
|
+
function parsePointerHeader(input) {
|
|
216
|
+
const params = {};
|
|
217
|
+
let i = 0;
|
|
218
|
+
const len = input.length;
|
|
219
|
+
while (i < len) {
|
|
220
|
+
// Skip whitespace and commas
|
|
221
|
+
while (i < len && (input[i] === ' ' || input[i] === ',' || input[i] === '\t')) {
|
|
222
|
+
i++;
|
|
223
|
+
}
|
|
224
|
+
if (i >= len)
|
|
225
|
+
break;
|
|
226
|
+
// Parse key (word characters only)
|
|
227
|
+
const keyStart = i;
|
|
228
|
+
while (i < len && /\w/.test(input[i])) {
|
|
229
|
+
i++;
|
|
230
|
+
}
|
|
231
|
+
const key = input.slice(keyStart, i);
|
|
232
|
+
if (!key)
|
|
233
|
+
break;
|
|
234
|
+
// Skip whitespace before '='
|
|
235
|
+
while (i < len && input[i] === ' ')
|
|
236
|
+
i++;
|
|
237
|
+
// Expect '='
|
|
238
|
+
if (i >= len || input[i] !== '=')
|
|
239
|
+
break;
|
|
240
|
+
i++; // skip '='
|
|
241
|
+
// Skip whitespace after '='
|
|
242
|
+
while (i < len && input[i] === ' ')
|
|
243
|
+
i++;
|
|
244
|
+
// Parse value (quoted or unquoted)
|
|
245
|
+
let value;
|
|
246
|
+
if (input[i] === '"') {
|
|
247
|
+
// Quoted value - find closing quote
|
|
248
|
+
i++; // skip opening quote
|
|
249
|
+
const valueStart = i;
|
|
250
|
+
while (i < len && input[i] !== '"') {
|
|
251
|
+
i++;
|
|
252
|
+
}
|
|
253
|
+
value = input.slice(valueStart, i);
|
|
254
|
+
if (i < len)
|
|
255
|
+
i++; // skip closing quote
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
// Unquoted value - read until comma or whitespace
|
|
259
|
+
const valueStart = i;
|
|
260
|
+
while (i < len && input[i] !== ',' && input[i] !== ' ' && input[i] !== '\t') {
|
|
261
|
+
i++;
|
|
262
|
+
}
|
|
263
|
+
value = input.slice(valueStart, i);
|
|
264
|
+
}
|
|
265
|
+
params[key] = value;
|
|
266
|
+
}
|
|
267
|
+
return params;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Verify a pointer header and fetch the receipt
|
|
271
|
+
*
|
|
272
|
+
* Combines parsing and fetching in a single operation.
|
|
273
|
+
*
|
|
274
|
+
* @param pointerHeader - PEAC-Receipt-Pointer header value
|
|
275
|
+
* @param fetchOptions - Optional SSRF fetch options
|
|
276
|
+
* @returns Fetch result
|
|
277
|
+
*/
|
|
278
|
+
async function verifyAndFetchPointer(pointerHeader, fetchOptions) {
|
|
279
|
+
// Parse pointer header (RFC 8941 dictionary format)
|
|
280
|
+
// Format: sha256="<hex>", url="<url>"
|
|
281
|
+
// Using explicit parsing to avoid ReDoS in regex alternation
|
|
282
|
+
const params = parsePointerHeader(pointerHeader);
|
|
283
|
+
if (!params.sha256) {
|
|
284
|
+
return {
|
|
285
|
+
ok: false,
|
|
286
|
+
reason: 'pointer_fetch_failed',
|
|
287
|
+
errorCode: 'E_VERIFY_POINTER_FETCH_FAILED',
|
|
288
|
+
message: 'PEAC-Receipt-Pointer missing sha256 parameter',
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
if (!params.url) {
|
|
292
|
+
return {
|
|
293
|
+
ok: false,
|
|
294
|
+
reason: 'pointer_fetch_failed',
|
|
295
|
+
errorCode: 'E_VERIFY_POINTER_FETCH_FAILED',
|
|
296
|
+
message: 'PEAC-Receipt-Pointer missing url parameter',
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
return fetchPointerWithDigest({
|
|
300
|
+
url: params.url,
|
|
301
|
+
expectedDigest: params.sha256,
|
|
302
|
+
fetchOptions,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=pointer-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer-fetch.js","sourceRoot":"","sources":["../src/pointer-fetch.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AAyIH,wDA8GC;AAkHD,sDAgCC;AAvYD,yCAAyC;AACzC,yCAA+C;AAC/C,6DAAiG;AAmEjG,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E;;GAEG;AACH,SAAS,YAAY,CAAC,SAAyB;IAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;IAEhC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,WAAW,CAAC;QACjB,KAAK,YAAY,CAAC;QAClB,KAAK,UAAU,CAAC;QAChB,KAAK,YAAY,CAAC;QAClB,KAAK,aAAa,CAAC;QACnB,KAAK,uBAAuB;YAC1B,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,uBAAuB;gBAC/B,SAAS,EAAE,gCAAgC;gBAC3C,OAAO,EAAE,SAAS,CAAC,OAAO;aAC3B,CAAC;QAEJ,KAAK,SAAS;YACZ,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,uBAAuB;gBAC/B,SAAS,EAAE,gCAAgC;gBAC3C,OAAO,EAAE,SAAS,CAAC,OAAO;aAC3B,CAAC;QAEJ,KAAK,oBAAoB;YACvB,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,yBAAyB;gBACjC,SAAS,EAAE,kCAAkC;gBAC7C,OAAO,EAAE,SAAS,CAAC,OAAO;aAC3B,CAAC;QAEJ;YACE,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,sBAAsB;gBAC9B,SAAS,EAAE,+BAA+B;gBAC1C,OAAO,EAAE,SAAS,CAAC,OAAO;aAC3B,CAAC;IACN,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACI,KAAK,UAAU,sBAAsB,CAC1C,OAA4B;IAE5B,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAE3D,kCAAkC;IAClC,MAAM,QAAQ,GAAG,gBAAgB,CAAC;IAClC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QACnC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,sBAAsB;YAC9B,SAAS,EAAE,+BAA+B;YAC1C,OAAO,EAAE,8DAA8D;SACxE,CAAC;IACJ,CAAC;IAED,iDAAiD;IACjD,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,SAAS,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACpC,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,uBAAuB;gBAC/B,SAAS,EAAE,gCAAgC;gBAC3C,OAAO,EAAE,4BAA4B;aACtC,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,sBAAsB;YAC9B,SAAS,EAAE,+BAA+B;YAC1C,OAAO,EAAE,qBAAqB;SAC/B,CAAC;IACJ,CAAC;IAED,4CAA4C;IAC5C,2DAA2D;IAC3D,4EAA4E;IAC5E,+CAA+C;IAC/C,MAAM,WAAW,GAAG,MAAM,IAAA,kCAAa,EAAC,GAAG,EAAE;QAC3C,GAAG,YAAY;QACf,QAAQ,EAAE,wBAAe,CAAC,eAAe;QACzC,cAAc,EAAE,KAAK,EAAE,4CAA4C;QACnE,SAAS,EAAE,YAAY,EAAE,SAAS,IAAI,wBAAe,CAAC,cAAc;QACpE,OAAO,EAAE;YACP,MAAM,EAAE,gDAAgD;YACxD,GAAG,YAAY,CAAC,OAAO;SACxB;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;QACpB,OAAO,YAAY,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC;IAEjC,gFAAgF;IAChF,8DAA8D;IAC9D,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC;IAC5C,MAAM,oBAAoB,GAAG,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,YAAY,CAAC,CAAC;IACpF,MAAM,kBAAkB,GACtB,WAAW,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACvF,CAAC,CAAC,4BAA4B,WAAW,8DAA8D;QACvG,CAAC,CAAC,SAAS,CAAC;IAEhB,8BAA8B;IAC9B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,mBAAmB;YAC3B,SAAS,EAAE,4BAA4B;YACvC,OAAO,EAAE,uCAAuC;SACjD,CAAC;IACJ,CAAC;IAED,wFAAwF;IACxF,MAAM,aAAa,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC;IAC3D,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QACzB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,mBAAmB;YAC3B,SAAS,EAAE,4BAA4B;YACvC,OAAO,EAAE,aAAa,CAAC,OAAO;SAC/B,CAAC;IACJ,CAAC;IAED,gEAAgE;IAChE,MAAM,YAAY,GAAG,MAAM,IAAA,kBAAS,EAAC,OAAO,CAAC,CAAC;IAE9C,wBAAwB;IACxB,IAAI,YAAY,KAAK,cAAc,EAAE,CAAC;QACpC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,yBAAyB;YACjC,SAAS,EAAE,kCAAkC;YAC7C,OAAO,EAAE,uDAAuD;YAChE,YAAY;YACZ,cAAc;SACf,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE,EAAE,IAAI;QACR,OAAO;QACP,YAAY;QACZ,aAAa,EAAE,IAAI;QACnB,WAAW,EAAE,WAAW,CAAC,WAAW;QACpC,GAAG,CAAC,kBAAkB,IAAI,EAAE,kBAAkB,EAAE,CAAC;KAClD,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,2BAA2B,CAClC,KAAa;IAEb,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAElC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,+DAA+D,QAAQ,CAAC,MAAM,EAAE;SAC1F,CAAC;IACJ,CAAC;IAED,uEAAuE;IACvE,MAAM,cAAc,GAAG,kBAAkB,CAAC;IAE1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,OAAO,EAAE,8CAA8C,CAAC,GAAG,CAAC,WAAW;aACxE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,OAAO,EAAE,8CAA8C,CAAC,GAAG,CAAC,8BAA8B;aAC3F,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,KAAa;IACvC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;IAEzB,OAAO,CAAC,GAAG,GAAG,EAAE,CAAC;QACf,6BAA6B;QAC7B,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;YAC9E,CAAC,EAAE,CAAC;QACN,CAAC;QACD,IAAI,CAAC,IAAI,GAAG;YAAE,MAAM;QAEpB,mCAAmC;QACnC,MAAM,QAAQ,GAAG,CAAC,CAAC;QACnB,OAAO,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACtC,CAAC,EAAE,CAAC;QACN,CAAC;QACD,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,GAAG;YAAE,MAAM;QAEhB,6BAA6B;QAC7B,OAAO,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,CAAC,EAAE,CAAC;QAExC,aAAa;QACb,IAAI,CAAC,IAAI,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,MAAM;QACxC,CAAC,EAAE,CAAC,CAAC,WAAW;QAEhB,4BAA4B;QAC5B,OAAO,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,CAAC,EAAE,CAAC;QAExC,mCAAmC;QACnC,IAAI,KAAa,CAAC;QAClB,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACrB,oCAAoC;YACpC,CAAC,EAAE,CAAC,CAAC,qBAAqB;YAC1B,MAAM,UAAU,GAAG,CAAC,CAAC;YACrB,OAAO,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACnC,CAAC,EAAE,CAAC;YACN,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YACnC,IAAI,CAAC,GAAG,GAAG;gBAAE,CAAC,EAAE,CAAC,CAAC,qBAAqB;QACzC,CAAC;aAAM,CAAC;YACN,kDAAkD;YAClD,MAAM,UAAU,GAAG,CAAC,CAAC;YACrB,OAAO,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC5E,CAAC,EAAE,CAAC;YACN,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QACrC,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;GAQG;AACI,KAAK,UAAU,qBAAqB,CACzC,aAAqB,EACrB,YAAiD;IAEjD,oDAAoD;IACpD,sCAAsC;IACtC,6DAA6D;IAC7D,MAAM,MAAM,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAEjD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,sBAAsB;YAC9B,SAAS,EAAE,+BAA+B;YAC1C,OAAO,EAAE,+CAA+C;SACzD,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QAChB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,sBAAsB;YAC9B,SAAS,EAAE,+BAA+B;YAC1C,OAAO,EAAE,4CAA4C;SACtD,CAAC;IACJ,CAAC;IAED,OAAO,sBAAsB,CAAC;QAC5B,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,cAAc,EAAE,MAAM,CAAC,MAAM;QAC7B,YAAY;KACb,CAAC,CAAC;AACL,CAAC"}
|