@algovoi/audit-verifier 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +113 -0
- package/dist/canonicalize.d.ts +5 -0
- package/dist/canonicalize.d.ts.map +1 -0
- package/dist/canonicalize.js +26 -0
- package/dist/canonicalize.js.map +1 -0
- package/dist/check-report.d.ts +18 -0
- package/dist/check-report.d.ts.map +1 -0
- package/dist/check-report.js +48 -0
- package/dist/check-report.js.map +1 -0
- package/dist/checks.d.ts +9 -0
- package/dist/checks.d.ts.map +1 -0
- package/dist/checks.js +337 -0
- package/dist/checks.js.map +1 -0
- package/dist/demo.d.ts +17 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +186 -0
- package/dist/demo.js.map +1 -0
- package/dist/extractors.d.ts +13 -0
- package/dist/extractors.d.ts.map +1 -0
- package/dist/extractors.js +72 -0
- package/dist/extractors.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +59 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/verify.d.ts +10 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +44 -0
- package/dist/verify.js.map +1 -0
- package/package.json +64 -0
- package/src/canonicalize.ts +29 -0
- package/src/check-report.ts +58 -0
- package/src/checks.ts +435 -0
- package/src/demo.ts +214 -0
- package/src/extractors.ts +87 -0
- package/src/index.ts +44 -0
- package/src/types.ts +70 -0
- package/src/verify.ts +66 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AlgoVoi / Christopher Hopley
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# @algovoi/audit-verifier (TypeScript)
|
|
2
|
+
|
|
3
|
+
TypeScript reference verifier for AlgoVoi selective-disclosure audit bundles.
|
|
4
|
+
Byte-for-byte parity with the Python sibling
|
|
5
|
+
[`algovoi-audit-verifier`](https://pypi.org/project/algovoi-audit-verifier/)
|
|
6
|
+
on PyPI.
|
|
7
|
+
|
|
8
|
+
Standalone — auditor-runnable on any Node.js 18+ machine with no AlgoVoi
|
|
9
|
+
infrastructure trust required.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @algovoi/substrate canonicalize # peer deps
|
|
15
|
+
npm install @algovoi/audit-verifier
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or just install the package directly (canonicalize is a dependency, pulled
|
|
19
|
+
automatically):
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @algovoi/audit-verifier
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Three ways to verify
|
|
26
|
+
|
|
27
|
+
### 1. Hosted endpoint (zero install)
|
|
28
|
+
|
|
29
|
+
POST your bundle to `https://verify.algovoi.co.uk/verify` and get a
|
|
30
|
+
structured verification report. Same code path as this package.
|
|
31
|
+
|
|
32
|
+
### 2. Programmatic use
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { verifyBundle } from '@algovoi/audit-verifier';
|
|
36
|
+
|
|
37
|
+
const bundle = JSON.parse(fs.readFileSync('audit-bundle.json', 'utf-8'));
|
|
38
|
+
const report = await verifyBundle(bundle, {
|
|
39
|
+
signingKey: process.env.AUDIT_BUNDLE_KEY, // optional
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
console.log(report.render()); // human-readable PASS/FAIL
|
|
43
|
+
console.log(report.toJSON()); // machine-readable
|
|
44
|
+
if (!report.allPassed) process.exit(1);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 3. Demo + smoke test
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { buildDemoBundle, verifyBundle } from '@algovoi/audit-verifier';
|
|
51
|
+
|
|
52
|
+
const bundle = buildDemoBundle({ chainName: 'audit_log', rowCount: 3 });
|
|
53
|
+
const report = await verifyBundle(bundle, {
|
|
54
|
+
signingKey: 'demo-key-not-for-production-use',
|
|
55
|
+
});
|
|
56
|
+
console.log(report.allPassed); // true
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## What this verifier checks
|
|
60
|
+
|
|
61
|
+
| # | Check | What it proves |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| 1 | `per_row_content_hash` | Each row's stored `content_hash` matches `SHA-256(JCS(canonical-fields))` — per-row tamper-evidence |
|
|
64
|
+
| 2 | `continuity` | `prev_hash` walks unbroken across `rows + bridging_rows` ordered by `chain_position` — no fabricated gap or reorder |
|
|
65
|
+
| 3 | `bundle_signature` | HMAC-SHA256 over `JCS(bundle - signature)` matches `bundle_signature.hex` — proves AlgoVoi emission (when signing key supplied) |
|
|
66
|
+
| 4 | `selection_criteria_match` | Selected rows actually match the filter declared in `selection_criteria` (when exact-match filters are set) |
|
|
67
|
+
| 5 | `off_vm_anchor` | Off-VM Object-Lock manifest tail entry matches `chain_anchor.current_head` (when `manifestDir` supplied) |
|
|
68
|
+
|
|
69
|
+
A bundle that passes all five checks (or has them skipped for legitimate
|
|
70
|
+
reasons — no signing key supplied, no manifest available, etc.) has its
|
|
71
|
+
`all_passed` set to `true`.
|
|
72
|
+
|
|
73
|
+
## Cross-implementation parity
|
|
74
|
+
|
|
75
|
+
This TypeScript verifier is **byte-for-byte equivalent** to the Python
|
|
76
|
+
sibling on PyPI:
|
|
77
|
+
|
|
78
|
+
| Implementation | Package |
|
|
79
|
+
|---|---|
|
|
80
|
+
| Python | [`algovoi-audit-verifier`](https://pypi.org/project/algovoi-audit-verifier/) |
|
|
81
|
+
| TypeScript | `@algovoi/audit-verifier` (this package) |
|
|
82
|
+
|
|
83
|
+
Both verifiers produce identical:
|
|
84
|
+
- JCS canonical bytes for the same input object (RFC 8785)
|
|
85
|
+
- SHA-256 hash for the same canonical preimage
|
|
86
|
+
- HMAC-SHA256 signature for the same `(bundle - signature, key)` pair
|
|
87
|
+
- Per-row `content_hash` for the same row content
|
|
88
|
+
- Check report shape (`all_passed`, `fatal[]`, `checks[]`)
|
|
89
|
+
|
|
90
|
+
The parity is exercised by 9 cross-impl tests in this repo's
|
|
91
|
+
`test/parity.test.ts`, which generate bundles in Python and verify them in
|
|
92
|
+
TypeScript (and vice versa).
|
|
93
|
+
|
|
94
|
+
## Substrate
|
|
95
|
+
|
|
96
|
+
This verifier composes against the AlgoVoi canonicalisation substrate:
|
|
97
|
+
|
|
98
|
+
- Spec: `specs/canonicalisation.md` ([PR #2436](https://github.com/x402-foundation/x402/pull/2436)) — three-voice coalition co-signed
|
|
99
|
+
- Pin: `urn:x402:canonicalisation:jcs-rfc8785-v1`
|
|
100
|
+
- Substrate SDK: [`@algovoi/substrate`](https://www.npmjs.com/package/@algovoi/substrate)
|
|
101
|
+
- 53-vector conformance corpus: [`chopmob-cloud/algovoi-jcs-conformance-vectors`](https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors)
|
|
102
|
+
|
|
103
|
+
## Hosted equivalent
|
|
104
|
+
|
|
105
|
+
The same code path runs at <https://verify.algovoi.co.uk> behind nginx + Cloudflare on a dedicated VM. POST any audit bundle to `/verify` and get back the same `CheckReportJSON` shape this package returns programmatically.
|
|
106
|
+
|
|
107
|
+
## Licence
|
|
108
|
+
|
|
109
|
+
MIT. See `LICENSE`.
|
|
110
|
+
|
|
111
|
+
## Author
|
|
112
|
+
|
|
113
|
+
AlgoVoi (Christopher Hopley, GitHub [`chopmob-cloud`](https://github.com/chopmob-cloud)).
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function canonicalize(obj: unknown): string;
|
|
2
|
+
export declare function canonicaliseToBytes(obj: unknown): Buffer;
|
|
3
|
+
export declare function sha256Hex(bytes: Buffer | string): string;
|
|
4
|
+
export declare function sha256JcsHex(obj: unknown): string;
|
|
5
|
+
//# sourceMappingURL=canonicalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonicalize.d.ts","sourceRoot":"","sources":["../src/canonicalize.ts"],"names":[],"mappings":"AAUA,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAMjD;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAExD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEjD"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonicalisation wrapper for the audit verifier.
|
|
3
|
+
*
|
|
4
|
+
* Uses RFC 8785 JCS via the `canonicalize` npm package, byte-for-byte
|
|
5
|
+
* equivalent to the Python `rfc8785` package used by the sibling
|
|
6
|
+
* algovoi-audit-verifier (Python).
|
|
7
|
+
*/
|
|
8
|
+
import canonicalizeLib from 'canonicalize';
|
|
9
|
+
import { createHash } from 'node:crypto';
|
|
10
|
+
export function canonicalize(obj) {
|
|
11
|
+
const out = canonicalizeLib(obj);
|
|
12
|
+
if (out === undefined) {
|
|
13
|
+
throw new Error('canonicalize returned undefined (input not JCS-canonicalisable)');
|
|
14
|
+
}
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
export function canonicaliseToBytes(obj) {
|
|
18
|
+
return Buffer.from(canonicalize(obj), 'utf-8');
|
|
19
|
+
}
|
|
20
|
+
export function sha256Hex(bytes) {
|
|
21
|
+
return createHash('sha256').update(bytes).digest('hex');
|
|
22
|
+
}
|
|
23
|
+
export function sha256JcsHex(obj) {
|
|
24
|
+
return sha256Hex(canonicaliseToBytes(obj));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=canonicalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonicalize.js","sourceRoot":"","sources":["../src/canonicalize.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,eAAe,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAY;IAC9C,OAAO,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAsB;IAC9C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,OAAO,SAAS,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CheckReport — aggregates individual check results into a single
|
|
3
|
+
* PASS / FAIL summary. Byte-for-byte equivalent to the Python sibling's
|
|
4
|
+
* CheckReport class.
|
|
5
|
+
*/
|
|
6
|
+
import type { CheckEntry, CheckReportJSON } from './types.js';
|
|
7
|
+
export declare class CheckReport {
|
|
8
|
+
readonly checks: CheckEntry[];
|
|
9
|
+
readonly fatal: string[];
|
|
10
|
+
add(name: string, passed: boolean, detail?: string): void;
|
|
11
|
+
addSkip(name: string, reason: string): void;
|
|
12
|
+
addFatal(msg: string): void;
|
|
13
|
+
get allPassed(): boolean;
|
|
14
|
+
get hasFatal(): boolean;
|
|
15
|
+
toJSON(): CheckReportJSON;
|
|
16
|
+
render(): string;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=check-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-report.d.ts","sourceRoot":"","sources":["../src/check-report.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9D,qBAAa,WAAW;IACtB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,CAAM;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAM;IAE9B,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,SAAK,GAAG,IAAI;IAIrD,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAI3C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI3B,IAAI,SAAS,IAAI,OAAO,CAGvB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,MAAM,IAAI,eAAe;IAQzB,MAAM,IAAI,MAAM;CAiBjB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export class CheckReport {
|
|
2
|
+
checks = [];
|
|
3
|
+
fatal = [];
|
|
4
|
+
add(name, passed, detail = '') {
|
|
5
|
+
this.checks.push({ name, passed, detail });
|
|
6
|
+
}
|
|
7
|
+
addSkip(name, reason) {
|
|
8
|
+
this.checks.push({ name, passed: null, detail: `skipped: ${reason}` });
|
|
9
|
+
}
|
|
10
|
+
addFatal(msg) {
|
|
11
|
+
this.fatal.push(msg);
|
|
12
|
+
}
|
|
13
|
+
get allPassed() {
|
|
14
|
+
if (this.fatal.length > 0)
|
|
15
|
+
return false;
|
|
16
|
+
return this.checks.every((c) => c.passed !== false);
|
|
17
|
+
}
|
|
18
|
+
get hasFatal() {
|
|
19
|
+
return this.fatal.length > 0;
|
|
20
|
+
}
|
|
21
|
+
toJSON() {
|
|
22
|
+
return {
|
|
23
|
+
all_passed: this.allPassed,
|
|
24
|
+
fatal: this.fatal.slice(),
|
|
25
|
+
checks: this.checks.map((c) => ({ ...c })),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
render() {
|
|
29
|
+
const lines = [];
|
|
30
|
+
if (this.fatal.length > 0) {
|
|
31
|
+
lines.push('FATAL:');
|
|
32
|
+
for (const f of this.fatal)
|
|
33
|
+
lines.push(` ! ${f}`);
|
|
34
|
+
return lines.join('\n');
|
|
35
|
+
}
|
|
36
|
+
for (const c of this.checks) {
|
|
37
|
+
const mark = c.passed === true ? ' ok' : c.passed === false ? 'FAIL' : 'skip';
|
|
38
|
+
let line = ` [${mark}] ${c.name}`;
|
|
39
|
+
if (c.detail)
|
|
40
|
+
line += ` -- ${c.detail}`;
|
|
41
|
+
lines.push(line);
|
|
42
|
+
}
|
|
43
|
+
const verdict = this.allPassed ? 'PASS' : 'FAIL';
|
|
44
|
+
lines.push(`\nVerdict: ${verdict}`);
|
|
45
|
+
return lines.join('\n');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=check-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-report.js","sourceRoot":"","sources":["../src/check-report.ts"],"names":[],"mappings":"AAOA,MAAM,OAAO,WAAW;IACb,MAAM,GAAiB,EAAE,CAAC;IAC1B,KAAK,GAAa,EAAE,CAAC;IAE9B,GAAG,CAAC,IAAY,EAAE,MAAe,EAAE,MAAM,GAAG,EAAE;QAC5C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,CAAC,IAAY,EAAE,MAAc;QAClC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,MAAM,EAAE,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,QAAQ,CAAC,GAAW;QAClB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,SAAS;QACX,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACxC,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM;QACJ,OAAO;YACL,UAAU,EAAE,IAAI,CAAC,SAAS;YAC1B,KAAK,EAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;YAC9B,MAAM,EAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;SAC/C,CAAC;IACJ,CAAC;IAED,MAAM;QACJ,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACrB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK;gBAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACnD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;YAC/E,IAAI,IAAI,GAAG,MAAM,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,CAAC,MAAM;gBAAE,IAAI,IAAI,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF"}
|
package/dist/checks.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CheckReport } from './check-report.js';
|
|
2
|
+
import type { AuditBundle } from './types.js';
|
|
3
|
+
export declare function checkPerRowContentHash(bundle: AuditBundle, report: CheckReport): void;
|
|
4
|
+
export declare function checkContinuity(bundle: AuditBundle, report: CheckReport): void;
|
|
5
|
+
export declare function checkBundleSignature(bundle: AuditBundle, signingKey: string | null | undefined, report: CheckReport): void;
|
|
6
|
+
export declare function checkSelectionCriteriaMatch(bundle: AuditBundle, report: CheckReport): void;
|
|
7
|
+
export declare function parseObjectKeyShaPrefix(objectKey: string | undefined): string | null;
|
|
8
|
+
export declare function checkOffVmAnchor(bundle: AuditBundle, manifestDir: string | null | undefined, report: CheckReport): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EACV,WAAW,EAGZ,MAAM,YAAY,CAAC;AAMpB,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAuCrF;AAaD,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAsF9E;AAMD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACrC,MAAM,EAAE,WAAW,GAClB,IAAI,CAmDN;AAmCD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAgD1F;AAMD,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAWpF;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACtC,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,IAAI,CAAC,CAsGf"}
|
package/dist/checks.js
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The five verifier checks ported byte-for-byte from verify_audit_bundle.py:
|
|
3
|
+
*
|
|
4
|
+
* 1. checkPerRowContentHash -- SHA-256(JCS(canonical-fields)) per row
|
|
5
|
+
* 2. checkContinuity -- prev_hash walks unbroken across rows + bridging
|
|
6
|
+
* 3. checkBundleSignature -- HMAC-SHA256 over RFC 8785 canonical bundle
|
|
7
|
+
* 4. checkSelectionCriteria -- selected rows actually match the filter
|
|
8
|
+
* 5. checkOffVmAnchor -- off-VM Object-Lock manifest cross-check
|
|
9
|
+
* (when manifestDir provided)
|
|
10
|
+
*/
|
|
11
|
+
import { createHash, createHmac } from 'node:crypto';
|
|
12
|
+
import { promises as fs } from 'node:fs';
|
|
13
|
+
import * as path from 'node:path';
|
|
14
|
+
import { canonicaliseToBytes, sha256Hex } from './canonicalize.js';
|
|
15
|
+
import { FIELD_EXTRACTORS, KNOWN_CHAIN_NAMES } from './extractors.js';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// 1. Per-row content_hash
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
export function checkPerRowContentHash(bundle, report) {
|
|
20
|
+
const chainName = bundle.chain_name;
|
|
21
|
+
const extractor = chainName ? FIELD_EXTRACTORS[chainName] : undefined;
|
|
22
|
+
if (!extractor) {
|
|
23
|
+
report.add('per_row_content_hash', false, `unknown chain_name '${chainName}' (expected one of ${JSON.stringify(KNOWN_CHAIN_NAMES)})`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const rows = bundle.rows ?? [];
|
|
27
|
+
if (rows.length === 0) {
|
|
28
|
+
report.addSkip('per_row_content_hash', 'selection is empty (zero rows)');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const failures = [];
|
|
32
|
+
for (const r of rows) {
|
|
33
|
+
const expected = r['content_hash'];
|
|
34
|
+
if (typeof expected !== 'string' || expected.length !== 64) {
|
|
35
|
+
failures.push(`chain_position=${JSON.stringify(r['chain_position'])}: stored content_hash missing or wrong length`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const canonical = extractor(r);
|
|
39
|
+
const actual = sha256Hex(canonicaliseToBytes(canonical));
|
|
40
|
+
if (actual !== expected) {
|
|
41
|
+
failures.push(`chain_position=${JSON.stringify(r['chain_position'])}: ` +
|
|
42
|
+
`recomputed ${actual.slice(0, 16)}... != stored ${expected.slice(0, 16)}...`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (failures.length > 0) {
|
|
46
|
+
let detail = `${failures.length} of ${rows.length} rows failed: ${failures.slice(0, 3).join('; ')}`;
|
|
47
|
+
if (failures.length > 3)
|
|
48
|
+
detail += `; (+${failures.length - 3} more)`;
|
|
49
|
+
report.add('per_row_content_hash', false, detail);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
report.add('per_row_content_hash', true, `${rows.length} rows verified`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function checkContinuity(bundle, report) {
|
|
56
|
+
const rows = bundle.rows ?? [];
|
|
57
|
+
const bridging = bundle.bridging_rows ?? [];
|
|
58
|
+
const bridgingMeta = bundle.bridging ?? {};
|
|
59
|
+
if (rows.length === 0) {
|
|
60
|
+
report.addSkip('continuity', 'selection is empty');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const union = [];
|
|
64
|
+
for (const r of rows) {
|
|
65
|
+
union.push({
|
|
66
|
+
chain_position: r['chain_position'] ?? null,
|
|
67
|
+
content_hash: r['content_hash'],
|
|
68
|
+
prev_hash: r['prev_hash'],
|
|
69
|
+
kind: 'selected',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
for (const b of bridging) {
|
|
73
|
+
union.push({
|
|
74
|
+
chain_position: b['chain_position'] ?? null,
|
|
75
|
+
content_hash: b['content_hash'],
|
|
76
|
+
prev_hash: b['prev_hash'],
|
|
77
|
+
kind: 'bridging',
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// Sort by chain_position, nulls last (Python uses (None, position) tuple).
|
|
81
|
+
union.sort((a, b) => {
|
|
82
|
+
if (a.chain_position === null && b.chain_position === null)
|
|
83
|
+
return 0;
|
|
84
|
+
if (a.chain_position === null)
|
|
85
|
+
return 1;
|
|
86
|
+
if (b.chain_position === null)
|
|
87
|
+
return -1;
|
|
88
|
+
return a.chain_position - b.chain_position;
|
|
89
|
+
});
|
|
90
|
+
// Detect gaps in the merged set.
|
|
91
|
+
if (union.length > 1) {
|
|
92
|
+
const gaps = [];
|
|
93
|
+
for (let i = 1; i < union.length; i++) {
|
|
94
|
+
const p0 = union[i - 1].chain_position;
|
|
95
|
+
const p1 = union[i].chain_position;
|
|
96
|
+
if (p0 === null || p1 === null)
|
|
97
|
+
continue;
|
|
98
|
+
if (p1 - p0 > 1)
|
|
99
|
+
gaps.push([p0, p1]);
|
|
100
|
+
}
|
|
101
|
+
if (gaps.length > 0 && !bridgingMeta.included) {
|
|
102
|
+
report.addSkip('continuity', `gaps between selected positions ${JSON.stringify(gaps.slice(0, 2))} but bridging_rows not included; ` +
|
|
103
|
+
'request the bundle with include_bridging_rows=true to enable this check');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (gaps.length > 0) {
|
|
107
|
+
report.add('continuity', false, `gaps remain after bridging at positions ${JSON.stringify(gaps.slice(0, 3))} -- chain has missing rows`);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Walk
|
|
112
|
+
const failures = [];
|
|
113
|
+
for (let i = 1; i < union.length; i++) {
|
|
114
|
+
const prev = union[i - 1];
|
|
115
|
+
const curr = union[i];
|
|
116
|
+
if (curr.prev_hash !== prev.content_hash) {
|
|
117
|
+
failures.push(`position ${curr.chain_position} (${curr.kind}): ` +
|
|
118
|
+
`prev_hash ${(curr.prev_hash ?? '').slice(0, 12)}... != ` +
|
|
119
|
+
`content_hash of position ${prev.chain_position} (${prev.kind}) ` +
|
|
120
|
+
`${(prev.content_hash ?? '').slice(0, 12)}...`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (failures.length > 0) {
|
|
124
|
+
const detail = `${failures.length} broken link(s): ${failures.slice(0, 2).join('; ')}`;
|
|
125
|
+
report.add('continuity', false, detail);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
report.add('continuity', true, `${union.length} entries (selected=${rows.length}, bridging=${bridging.length}) chain forward correctly`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// 3. Bundle signature
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
export function checkBundleSignature(bundle, signingKey, report) {
|
|
135
|
+
const sig = bundle.bundle_signature;
|
|
136
|
+
if (sig === null || sig === undefined) {
|
|
137
|
+
report.addSkip('bundle_signature', 'bundle has bundle_signature: null (signing not configured server-side)');
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (typeof sig !== 'object' || Array.isArray(sig) || !('hex' in sig)) {
|
|
141
|
+
report.add('bundle_signature', false, `bundle_signature is not a valid signature object: ${JSON.stringify(sig)}`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const s = sig;
|
|
145
|
+
if (!signingKey) {
|
|
146
|
+
report.addSkip('bundle_signature', `bundle is signed with key_id='${s.key_id}', algorithm='${s.algorithm}' -- ` +
|
|
147
|
+
'pass --signing-key or --signing-key-env to verify');
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (s.algorithm !== 'HMAC-SHA256' || s.canonicalisation !== 'RFC 8785') {
|
|
151
|
+
report.add('bundle_signature', false, `unsupported signature algorithm/canonicalisation: ${s.algorithm}/${s.canonicalisation}`);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// Build inner = bundle minus bundle_signature
|
|
155
|
+
const inner = {};
|
|
156
|
+
for (const [k, v] of Object.entries(bundle)) {
|
|
157
|
+
if (k !== 'bundle_signature')
|
|
158
|
+
inner[k] = v;
|
|
159
|
+
}
|
|
160
|
+
const canonical = canonicaliseToBytes(inner);
|
|
161
|
+
const expected = createHmac('sha256', signingKey).update(canonical).digest('hex');
|
|
162
|
+
if (expected === s.hex) {
|
|
163
|
+
report.add('bundle_signature', true, `HMAC-SHA256 verified against key_id='${s.key_id}'`);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
report.add('bundle_signature', false, `recomputed ${expected.slice(0, 16)}... != stored ${s.hex.slice(0, 16)}... -- wrong key, or bundle tampered`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
// 4. Selection criteria match
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
const CRITERIA_EXACT_MATCH = {
|
|
173
|
+
audit_log: {
|
|
174
|
+
actor: 'actor',
|
|
175
|
+
action: 'action',
|
|
176
|
+
target_type: 'target_type',
|
|
177
|
+
tenant_id: 'tenant_id',
|
|
178
|
+
trace_id: 'trace_id',
|
|
179
|
+
},
|
|
180
|
+
screening_hits: {
|
|
181
|
+
subject_type: 'subject_type',
|
|
182
|
+
action_taken: 'action_taken',
|
|
183
|
+
screening_context: 'screening_context',
|
|
184
|
+
tenant_id: 'tenant_id',
|
|
185
|
+
wallet_address: 'wallet_address',
|
|
186
|
+
},
|
|
187
|
+
compliance_events: {
|
|
188
|
+
tenant_id: 'tenant_id',
|
|
189
|
+
rule_id: 'rule_id',
|
|
190
|
+
event_type: 'event_type',
|
|
191
|
+
payment_ledger_id: 'payment_ledger_id',
|
|
192
|
+
},
|
|
193
|
+
negotiation_trace_events: {
|
|
194
|
+
tenant_id: 'tenant_id',
|
|
195
|
+
session_id: 'session_id',
|
|
196
|
+
protocol: 'protocol',
|
|
197
|
+
payment_ledger_id: 'payment_ledger_id',
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
export function checkSelectionCriteriaMatch(bundle, report) {
|
|
201
|
+
const rows = bundle.rows ?? [];
|
|
202
|
+
const criteria = bundle.selection_criteria ?? {};
|
|
203
|
+
const chainName = bundle.chain_name ?? '';
|
|
204
|
+
const exactMap = CRITERIA_EXACT_MATCH[chainName] ?? {};
|
|
205
|
+
// Find which exact-match filters were set
|
|
206
|
+
const activeFilters = [];
|
|
207
|
+
for (const [criterionKey, rowField] of Object.entries(exactMap)) {
|
|
208
|
+
if (criterionKey in criteria && criteria[criterionKey] !== null && criteria[criterionKey] !== undefined) {
|
|
209
|
+
activeFilters.push([rowField, criteria[criterionKey]]);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (activeFilters.length === 0) {
|
|
213
|
+
report.addSkip('selection_criteria_match', 'no exact-match filters set in selection_criteria');
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (rows.length === 0) {
|
|
217
|
+
report.addSkip('selection_criteria_match', 'no rows to check');
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const violations = [];
|
|
221
|
+
for (const r of rows) {
|
|
222
|
+
for (const [field, expected] of activeFilters) {
|
|
223
|
+
// Negotiation_trace counterparty is a disjunctive filter handled separately;
|
|
224
|
+
// exactMap above does not include it.
|
|
225
|
+
const actual = r[field];
|
|
226
|
+
if (actual !== expected) {
|
|
227
|
+
violations.push(`chain_position=${JSON.stringify(r['chain_position'])}: ` +
|
|
228
|
+
`row.${field}=${JSON.stringify(actual)} != criteria.${field}=${JSON.stringify(expected)}`);
|
|
229
|
+
break; // one violation per row is enough
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (violations.length > 0) {
|
|
234
|
+
let detail = `${violations.length} of ${rows.length} rows do not match selection_criteria: ${violations.slice(0, 3).join('; ')}`;
|
|
235
|
+
if (violations.length > 3)
|
|
236
|
+
detail += `; (+${violations.length - 3} more)`;
|
|
237
|
+
report.add('selection_criteria_match', false, detail);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
report.add('selection_criteria_match', true, `${rows.length} rows match ${activeFilters.length} exact-match filter(s)`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// ---------------------------------------------------------------------------
|
|
244
|
+
// 5. Off-VM anchor
|
|
245
|
+
// ---------------------------------------------------------------------------
|
|
246
|
+
export function parseObjectKeyShaPrefix(objectKey) {
|
|
247
|
+
if (!objectKey)
|
|
248
|
+
return null;
|
|
249
|
+
const basename = objectKey.includes('/') ? objectKey.slice(objectKey.lastIndexOf('/') + 1) : objectKey;
|
|
250
|
+
if (!basename.endsWith('.ndjson'))
|
|
251
|
+
return null;
|
|
252
|
+
const stem = basename.slice(0, -'.ndjson'.length);
|
|
253
|
+
const dashIdx = stem.lastIndexOf('-');
|
|
254
|
+
if (dashIdx < 0)
|
|
255
|
+
return null;
|
|
256
|
+
const shaPrefix = stem.slice(dashIdx + 1);
|
|
257
|
+
if (shaPrefix.length !== 16)
|
|
258
|
+
return null;
|
|
259
|
+
if (!/^[0-9a-f]+$/.test(shaPrefix))
|
|
260
|
+
return null;
|
|
261
|
+
return shaPrefix;
|
|
262
|
+
}
|
|
263
|
+
export async function checkOffVmAnchor(bundle, manifestDir, report) {
|
|
264
|
+
const anchor = bundle.off_vm_anchor;
|
|
265
|
+
if (!anchor || !anchor.object_key) {
|
|
266
|
+
report.addSkip('off_vm_anchor', 'no off_vm_anchor in bundle (chain has not been shipped yet, or bundle is from before shipping started)');
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (!manifestDir) {
|
|
270
|
+
report.addSkip('off_vm_anchor', `manifestDir not provided -- run \`aws s3api head-object --bucket ${anchor.bucket_name} --key ${anchor.object_key}\` and confirm ObjectLockMode=COMPLIANCE`);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
const expectedShaPrefix = parseObjectKeyShaPrefix(anchor.object_key);
|
|
274
|
+
if (!expectedShaPrefix) {
|
|
275
|
+
report.add('off_vm_anchor', false, `object_key has no parseable sha256 prefix: ${anchor.object_key}`);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
// Try to locate the manifest file: by full key path, by basename.
|
|
279
|
+
const candidates = [
|
|
280
|
+
path.join(manifestDir, anchor.object_key),
|
|
281
|
+
path.join(manifestDir, path.basename(anchor.object_key)),
|
|
282
|
+
];
|
|
283
|
+
let manifestPath = null;
|
|
284
|
+
for (const c of candidates) {
|
|
285
|
+
try {
|
|
286
|
+
await fs.access(c);
|
|
287
|
+
manifestPath = c;
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
// continue
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (!manifestPath) {
|
|
295
|
+
report.add('off_vm_anchor', false, `manifest file not found in ${manifestDir} for object_key=${anchor.object_key}`);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
// Compute SHA-256 of the file bytes.
|
|
299
|
+
const buf = await fs.readFile(manifestPath);
|
|
300
|
+
const fullSha = createHash('sha256').update(buf).digest('hex');
|
|
301
|
+
if (fullSha.slice(0, 16) !== expectedShaPrefix) {
|
|
302
|
+
report.add('off_vm_anchor', false, `manifest sha prefix ${fullSha.slice(0, 16)} != object_key prefix ${expectedShaPrefix}`);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
// Parse last NDJSON line and confirm chain_position + content_hash match bundle.chain_anchor.current_head.
|
|
306
|
+
const text = buf.toString('utf-8');
|
|
307
|
+
const lines = text.split('\n').filter((l) => l.trim().length > 0);
|
|
308
|
+
if (lines.length === 0) {
|
|
309
|
+
report.add('off_vm_anchor', false, 'manifest file is empty');
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
let lastEntry;
|
|
313
|
+
try {
|
|
314
|
+
lastEntry = JSON.parse(lines[lines.length - 1]);
|
|
315
|
+
}
|
|
316
|
+
catch (e) {
|
|
317
|
+
report.add('off_vm_anchor', false, `last NDJSON line is not valid JSON: ${e.message}`);
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const head = bundle.chain_anchor?.current_head;
|
|
321
|
+
if (!head) {
|
|
322
|
+
report.add('off_vm_anchor', false, 'bundle.chain_anchor.current_head missing -- cannot cross-check manifest tail');
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const headPos = head.chain_position;
|
|
326
|
+
const headHash = head.content_hash;
|
|
327
|
+
if (lastEntry['chain_position'] !== headPos) {
|
|
328
|
+
report.add('off_vm_anchor', false, `manifest tail chain_position=${lastEntry['chain_position']} != bundle chain_anchor.current_head.chain_position=${headPos}`);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (lastEntry['content_hash'] !== headHash) {
|
|
332
|
+
report.add('off_vm_anchor', false, `manifest tail content_hash=${String(lastEntry['content_hash']).slice(0, 16)}... != bundle chain_anchor.current_head.content_hash=${String(headHash).slice(0, 16)}...`);
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
report.add('off_vm_anchor', true, `manifest sha verified + tail entry at chain_position=${headPos} matches chain_anchor.current_head`);
|
|
336
|
+
}
|
|
337
|
+
//# sourceMappingURL=checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.js","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAgB,mBAAmB,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEjF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAOtE,8EAA8E;AAC9E,0BAA0B;AAC1B,8EAA8E;AAE9E,MAAM,UAAU,sBAAsB,CAAC,MAAmB,EAAE,MAAmB;IAC7E,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;IACpC,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACtE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CACR,sBAAsB,EACtB,KAAK,EACL,uBAAuB,SAAS,sBAAsB,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,GAAG,CAC3F,CAAC;QACF,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IAC/B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,OAAO,CAAC,sBAAsB,EAAE,gCAAgC,CAAC,CAAC;QACzE,OAAO;IACT,CAAC;IACD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,CAAC,CAAC,cAAc,CAAC,CAAC;QACnC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;YAC3D,QAAQ,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,+CAA+C,CAAC,CAAC;YACpH,SAAS;QACX,CAAC;QACD,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,CAAC;QACzD,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxB,QAAQ,CAAC,IAAI,CACX,kBAAkB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,IAAI;gBACzD,cAAc,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAC7E,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,IAAI,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,OAAO,IAAI,CAAC,MAAM,iBAAiB,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpG,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC;QACtE,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,gBAAgB,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAaD,MAAM,UAAU,eAAe,CAAC,MAAmB,EAAE,MAAmB;IACtE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC;IAC5C,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IAE3C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC;QACnD,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC;YACT,cAAc,EAAG,CAAC,CAAC,gBAAgB,CAA+B,IAAI,IAAI;YAC1E,YAAY,EAAI,CAAC,CAAC,cAAc,CAAuB;YACvD,SAAS,EAAO,CAAC,CAAC,WAAW,CAA0B;YACvD,IAAI,EAAY,UAAU;SAC3B,CAAC,CAAC;IACL,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC;YACT,cAAc,EAAG,CAAC,CAAC,gBAAgB,CAA+B,IAAI,IAAI;YAC1E,YAAY,EAAI,CAAC,CAAC,cAAc,CAAuB;YACvD,SAAS,EAAO,CAAC,CAAC,WAAW,CAA0B;YACvD,IAAI,EAAY,UAAU;SAC3B,CAAC,CAAC;IACL,CAAC;IACD,2EAA2E;IAC3E,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAClB,IAAI,CAAC,CAAC,cAAc,KAAK,IAAI,IAAI,CAAC,CAAC,cAAc,KAAK,IAAI;YAAE,OAAO,CAAC,CAAC;QACrE,IAAI,CAAC,CAAC,cAAc,KAAK,IAAI;YAAE,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,CAAC,cAAc,KAAK,IAAI;YAAE,OAAO,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,cAAc,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,iCAAiC;IACjC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,GAA4B,EAAE,CAAC;QACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,cAAc,CAAC;YACxC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,cAAc,CAAC;YACpC,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,IAAI;gBAAE,SAAS;YACzC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;YAC9C,MAAM,CAAC,OAAO,CACZ,YAAY,EACZ,mCAAmC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,mCAAmC;gBACtG,yEAAyE,CAC1E,CAAC;YACF,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,CAAC,GAAG,CACR,YAAY,EACZ,KAAK,EACL,2CAA2C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,4BAA4B,CACxG,CAAC;YACF,OAAO;QACT,CAAC;IACH,CAAC;IAED,OAAO;IACP,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACvB,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;YACzC,QAAQ,CAAC,IAAI,CACX,YAAY,IAAI,CAAC,cAAc,KAAK,IAAI,CAAC,IAAI,KAAK;gBAClD,aAAa,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS;gBACzD,4BAA4B,IAAI,CAAC,cAAc,KAAK,IAAI,CAAC,IAAI,IAAI;gBACjE,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAC/C,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,oBAAoB,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvF,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,GAAG,CACR,YAAY,EACZ,IAAI,EACJ,GAAG,KAAK,CAAC,MAAM,sBAAsB,IAAI,CAAC,MAAM,cAAc,QAAQ,CAAC,MAAM,2BAA2B,CACzG,CAAC;IACJ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E,MAAM,UAAU,oBAAoB,CAClC,MAAmB,EACnB,UAAqC,EACrC,MAAmB;IAEnB,MAAM,GAAG,GAAG,MAAM,CAAC,gBAAgB,CAAC;IACpC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,CAAC,OAAO,CACZ,kBAAkB,EAClB,wEAAwE,CACzE,CAAC;QACF,OAAO;IACT,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,EAAE,CAAC;QACrE,MAAM,CAAC,GAAG,CAAC,kBAAkB,EAAE,KAAK,EAAE,qDAAqD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClH,OAAO;IACT,CAAC;IACD,MAAM,CAAC,GAAG,GAAsB,CAAC;IACjC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,CAAC,OAAO,CACZ,kBAAkB,EAClB,iCAAiC,CAAC,CAAC,MAAM,iBAAiB,CAAC,CAAC,SAAS,OAAO;YAC5E,mDAAmD,CACpD,CAAC;QACF,OAAO;IACT,CAAC;IACD,IAAI,CAAC,CAAC,SAAS,KAAK,aAAa,IAAI,CAAC,CAAC,gBAAgB,KAAK,UAAU,EAAE,CAAC;QACvE,MAAM,CAAC,GAAG,CACR,kBAAkB,EAClB,KAAK,EACL,qDAAqD,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,gBAAgB,EAAE,CACzF,CAAC;QACF,OAAO;IACT,CAAC;IAED,8CAA8C;IAC9C,MAAM,KAAK,GAA4B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,kBAAkB;YAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,SAAS,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClF,IAAI,QAAQ,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,CACR,kBAAkB,EAClB,IAAI,EACJ,wCAAwC,CAAC,CAAC,MAAM,GAAG,CACpD,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,GAAG,CACR,kBAAkB,EAClB,KAAK,EACL,cAAc,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,sCAAsC,CAC7G,CAAC;IACJ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,8BAA8B;AAC9B,8EAA8E;AAE9E,MAAM,oBAAoB,GAA2C;IACnE,SAAS,EAAE;QACT,KAAK,EAAQ,OAAO;QACpB,MAAM,EAAO,QAAQ;QACrB,WAAW,EAAE,aAAa;QAC1B,SAAS,EAAI,WAAW;QACxB,QAAQ,EAAK,UAAU;KACxB;IACD,cAAc,EAAE;QACd,YAAY,EAAO,cAAc;QACjC,YAAY,EAAO,cAAc;QACjC,iBAAiB,EAAE,mBAAmB;QACtC,SAAS,EAAU,WAAW;QAC9B,cAAc,EAAK,gBAAgB;KACpC;IACD,iBAAiB,EAAE;QACjB,SAAS,EAAU,WAAW;QAC9B,OAAO,EAAY,SAAS;QAC5B,UAAU,EAAS,YAAY;QAC/B,iBAAiB,EAAE,mBAAmB;KACvC;IACD,wBAAwB,EAAE;QACxB,SAAS,EAAU,WAAW;QAC9B,UAAU,EAAS,YAAY;QAC/B,QAAQ,EAAW,UAAU;QAC7B,iBAAiB,EAAE,mBAAmB;KACvC;CACF,CAAC;AAEF,MAAM,UAAU,2BAA2B,CAAC,MAAmB,EAAE,MAAmB;IAClF,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,kBAAkB,IAAI,EAAE,CAAC;IACjD,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,oBAAoB,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IAEvD,0CAA0C;IAC1C,MAAM,aAAa,GAA6B,EAAE,CAAC;IACnD,KAAK,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChE,IAAI,YAAY,IAAI,QAAQ,IAAI,QAAQ,CAAC,YAAY,CAAC,KAAK,IAAI,IAAI,QAAQ,CAAC,YAAY,CAAC,KAAK,SAAS,EAAE,CAAC;YACxG,aAAa,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,CAAC,OAAO,CAAC,0BAA0B,EAAE,kDAAkD,CAAC,CAAC;QAC/F,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,OAAO,CAAC,0BAA0B,EAAE,kBAAkB,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,aAAa,EAAE,CAAC;YAC9C,6EAA6E;YAC7E,sCAAsC;YACtC,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;YACxB,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACxB,UAAU,CAAC,IAAI,CACb,kBAAkB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,IAAI;oBACzD,OAAO,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,gBAAgB,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAC1F,CAAC;gBACF,MAAM,CAAE,kCAAkC;YAC5C,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,IAAI,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,OAAO,IAAI,CAAC,MAAM,0CAA0C,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACjI,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC;QAC1E,MAAM,CAAC,GAAG,CAAC,0BAA0B,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,GAAG,CACR,0BAA0B,EAC1B,IAAI,EACJ,GAAG,IAAI,CAAC,MAAM,eAAe,aAAa,CAAC,MAAM,wBAAwB,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,MAAM,UAAU,uBAAuB,CAAC,SAA6B;IACnE,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACvG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;IAC1C,IAAI,SAAS,CAAC,MAAM,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAmB,EACnB,WAAsC,EACtC,MAAmB;IAEnB,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC;IACpC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QAClC,MAAM,CAAC,OAAO,CACZ,eAAe,EACf,wGAAwG,CACzG,CAAC;QACF,OAAO;IACT,CAAC;IACD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,CACZ,eAAe,EACf,oEAAoE,MAAM,CAAC,WAAW,UAAU,MAAM,CAAC,UAAU,0CAA0C,CAC5J,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACrE,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,EAAE,8CAA8C,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QACtG,OAAO;IACT,CAAC;IAED,kEAAkE;IAClE,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,UAAU,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;KACzD,CAAC;IACF,IAAI,YAAY,GAAkB,IAAI,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACnB,YAAY,GAAG,CAAC,CAAC;YACjB,MAAM;QACR,CAAC;QAAC,MAAM,CAAC;YACP,WAAW;QACb,CAAC;IACH,CAAC;IACD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,CAAC,GAAG,CACR,eAAe,EACf,KAAK,EACL,8BAA8B,WAAW,mBAAmB,MAAM,CAAC,UAAU,EAAE,CAChF,CAAC;QACF,OAAO;IACT,CAAC;IAED,qCAAqC;IACrC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/D,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,iBAAiB,EAAE,CAAC;QAC/C,MAAM,CAAC,GAAG,CACR,eAAe,EACf,KAAK,EACL,uBAAuB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,yBAAyB,iBAAiB,EAAE,CACxF,CAAC;QACF,OAAO;IACT,CAAC;IAED,2GAA2G;IAC3G,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,EAAE,wBAAwB,CAAC,CAAC;QAC7D,OAAO;IACT,CAAC;IACD,IAAI,SAAkC,CAAC;IACvC,IAAI,CAAC;QACH,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,EAAE,uCAAwC,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QAClG,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC;IAC/C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,EAAE,8EAA8E,CAAC,CAAC;QACnH,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC;IACnC,IAAI,SAAS,CAAC,gBAAgB,CAAC,KAAK,OAAO,EAAE,CAAC;QAC5C,MAAM,CAAC,GAAG,CACR,eAAe,EACf,KAAK,EACL,gCAAgC,SAAS,CAAC,gBAAgB,CAAC,uDAAuD,OAAO,EAAE,CAC5H,CAAC;QACF,OAAO;IACT,CAAC;IACD,IAAI,SAAS,CAAC,cAAc,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,CACR,eAAe,EACf,KAAK,EACL,8BAA8B,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,wDAAwD,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CACvK,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,CAAC,GAAG,CACR,eAAe,EACf,IAAI,EACJ,wDAAwD,OAAO,oCAAoC,CACpG,CAAC;AACJ,CAAC"}
|
package/dist/demo.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AuditBundle } from './types.js';
|
|
2
|
+
export declare const GENESIS_PREV_HASH: string;
|
|
3
|
+
export declare const DEFAULT_KEY = "demo-key-not-for-production-use";
|
|
4
|
+
export interface BuildDemoBundleOptions {
|
|
5
|
+
chainName?: string;
|
|
6
|
+
rowCount?: number;
|
|
7
|
+
signingKey?: string;
|
|
8
|
+
keyId?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Override the bundle_emitted_at timestamp; defaults to current time.
|
|
11
|
+
* Pass a fixed ISO string when you need byte-for-byte determinism (e.g.
|
|
12
|
+
* cross-impl tests against the Python sibling).
|
|
13
|
+
*/
|
|
14
|
+
bundleEmittedAt?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function buildDemoBundle(options?: BuildDemoBundleOptions): AuditBundle;
|
|
17
|
+
//# sourceMappingURL=demo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../src/demo.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAY,MAAM,YAAY,CAAC;AAExD,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAChD,eAAO,MAAM,WAAW,oCAAoC,CAAC;AAwH7D,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,WAAW,CAiEjF"}
|