@vorim/verify 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 +135 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +149 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +199 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +65 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vorim AI
|
|
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,135 @@
|
|
|
1
|
+
# @vorim/verify
|
|
2
|
+
|
|
3
|
+
**Offline verifier for Vorim audit bundles.** No network. No Vorim API call. No telemetry.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@vorim/verify)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[]()
|
|
8
|
+
[](https://nodejs.org/)
|
|
9
|
+
|
|
10
|
+
`vorim-verify` checks that a Vorim audit bundle is authentic and untampered, using only Node's built-in cryptography. The verifier never contacts Vorim — every public key needed to verify a signature is embedded in the bundle itself.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install -g @vorim/verify
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or run without installing:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @vorim/verify bundle.json
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
vorim-verify bundle.json # verify a bundle file
|
|
28
|
+
cat bundle.json | vorim-verify - # read from stdin
|
|
29
|
+
vorim-verify --explain bundle.json # per-event verdicts
|
|
30
|
+
vorim-verify --json bundle.json # machine-readable JSON output
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Exit codes: `0` ok, `1` verification failed, `2` CLI / IO error.
|
|
34
|
+
|
|
35
|
+
Example output:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
vorim-verify: OK
|
|
39
|
+
|
|
40
|
+
bundle_version : vaip-v0
|
|
41
|
+
manifest : OK (sha256:8ff556a7222f...)
|
|
42
|
+
|
|
43
|
+
events total : 247
|
|
44
|
+
verified : 247
|
|
45
|
+
unsigned : 0
|
|
46
|
+
bad signature : 0
|
|
47
|
+
unknown agent : 0
|
|
48
|
+
malformed : 0
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## What verification proves
|
|
52
|
+
|
|
53
|
+
For every event marked `verified`:
|
|
54
|
+
|
|
55
|
+
1. **The bundle has not been edited since the API exported it.** The bundle's SHA-256 manifest must match the bytes of `events + agents` exactly.
|
|
56
|
+
2. **The agent identified in the event is the one that authored the bytes recorded.** The event's `ed25519` signature verifies under the agent's public key (embedded in the bundle's `agents[]`).
|
|
57
|
+
3. **The bytes signed are exactly the bytes recorded.** Tampering with any of `event_type`, `action`, `resource`, `input_hash`, `output_hash`, or `result` invalidates the signature.
|
|
58
|
+
|
|
59
|
+
## What verification does NOT prove
|
|
60
|
+
|
|
61
|
+
Be honest about the limits:
|
|
62
|
+
|
|
63
|
+
- **It does not prove the agent's identity is who it claims to be.** That requires a separate trust anchor (the Vorim trust API, an IdP, a public key directory). The verifier confirms the *binding* between the signature and the public key in the bundle.
|
|
64
|
+
- **It does not prove the bundle is recent.** Add a timestamp authority or an externally-witnessed hash chain if freshness matters.
|
|
65
|
+
- **It does not detect missing events.** A bundle with N signed events is a true record of those N events. Whether other events were dropped before export is outside the verifier's scope. Pair with the Vorim `audit_events` count for that.
|
|
66
|
+
- **`unsigned` and `unknown_agent` events are reported but do not fail the bundle.** Operator's call: a fresh bundle from a v3.1+ SDK should be 100% signed; an older bundle may not be. The CLI surfaces the count; the operator decides what the threshold is.
|
|
67
|
+
|
|
68
|
+
## Bundle format
|
|
69
|
+
|
|
70
|
+
The verifier expects the JSON shape produced by `POST /v1/audit/export` on Vorim API (`bundle_version: "vaip-v0"`). Minimum required:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"bundle_version": "vaip-v0",
|
|
75
|
+
"events": [
|
|
76
|
+
{
|
|
77
|
+
"event_id": "evt_...",
|
|
78
|
+
"agent_id_str": "agid_...",
|
|
79
|
+
"event_type": "tool_call",
|
|
80
|
+
"action": "transfer_funds",
|
|
81
|
+
"resource": "acct-1",
|
|
82
|
+
"input_hash": null,
|
|
83
|
+
"output_hash": null,
|
|
84
|
+
"result": "success",
|
|
85
|
+
"signature": "ed25519:..."
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"agents": [
|
|
89
|
+
{ "agent_id": "agid_...", "public_key": "-----BEGIN PUBLIC KEY-----\n..." }
|
|
90
|
+
],
|
|
91
|
+
"manifest": "sha256:..."
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Canonical bytes signed
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
event_type|action|resource|input_hash|output_hash|result
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Pipe-joined, empty string for missing optional fields. The verifier exposes `canonicalPayloadV0()` so you can reproduce the bytes yourself.
|
|
102
|
+
|
|
103
|
+
## Programmatic use
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import { verifyBundle } from '@vorim/verify';
|
|
107
|
+
|
|
108
|
+
const bundle = JSON.parse(fs.readFileSync('bundle.json', 'utf-8'));
|
|
109
|
+
const report = verifyBundle(bundle);
|
|
110
|
+
|
|
111
|
+
if (!report.ok) {
|
|
112
|
+
console.error('bundle failed verification', report);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Returns a `VerifyReport` with per-event verdicts and aggregate counts.
|
|
118
|
+
|
|
119
|
+
## Auditing this code
|
|
120
|
+
|
|
121
|
+
The verifier is small and intentionally has no runtime dependencies. To audit it from source:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
git clone https://github.com/Kzino/vorim-protocol
|
|
125
|
+
cd vorim-protocol/packages/verify
|
|
126
|
+
npm install
|
|
127
|
+
npm test # 23 unit tests
|
|
128
|
+
npm run build # produces dist/cli.js
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Read `src/index.ts` for the verification logic (≈220 lines) and `src/cli.ts` for the CLI shim.
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
MIT — see [LICENSE](LICENSE).
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* vorim-verify — Offline verifier for Vorim audit bundles.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* vorim-verify <path/to/bundle.json>
|
|
7
|
+
* cat bundle.json | vorim-verify -
|
|
8
|
+
* vorim-verify --explain <path> # per-event verdict list
|
|
9
|
+
* vorim-verify --json <path> # machine-readable report
|
|
10
|
+
* vorim-verify --help
|
|
11
|
+
* vorim-verify --version
|
|
12
|
+
*
|
|
13
|
+
* Exit codes:
|
|
14
|
+
* 0 bundle ok (no bad/malformed signatures, manifest checks if present)
|
|
15
|
+
* 1 bundle failed verification (at least one bad/malformed sig or wrong manifest)
|
|
16
|
+
* 2 CLI usage error / unreadable input
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* vorim-verify — Offline verifier for Vorim audit bundles.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* vorim-verify <path/to/bundle.json>
|
|
7
|
+
* cat bundle.json | vorim-verify -
|
|
8
|
+
* vorim-verify --explain <path> # per-event verdict list
|
|
9
|
+
* vorim-verify --json <path> # machine-readable report
|
|
10
|
+
* vorim-verify --help
|
|
11
|
+
* vorim-verify --version
|
|
12
|
+
*
|
|
13
|
+
* Exit codes:
|
|
14
|
+
* 0 bundle ok (no bad/malformed signatures, manifest checks if present)
|
|
15
|
+
* 1 bundle failed verification (at least one bad/malformed sig or wrong manifest)
|
|
16
|
+
* 2 CLI usage error / unreadable input
|
|
17
|
+
*/
|
|
18
|
+
import { readFileSync } from 'node:fs';
|
|
19
|
+
import { verifyBundle } from './index.js';
|
|
20
|
+
const VERSION = '0.1.0';
|
|
21
|
+
function printUsage(stream) {
|
|
22
|
+
stream.write(`vorim-verify ${VERSION} — offline verifier for Vorim audit bundles
|
|
23
|
+
|
|
24
|
+
Usage:
|
|
25
|
+
vorim-verify <bundle.json> verify a bundle file
|
|
26
|
+
vorim-verify - read bundle from stdin
|
|
27
|
+
vorim-verify --explain <bundle.json> list per-event verdicts
|
|
28
|
+
vorim-verify --json <bundle.json> emit JSON report (no human formatting)
|
|
29
|
+
vorim-verify --help show this help
|
|
30
|
+
vorim-verify --version print version
|
|
31
|
+
|
|
32
|
+
Exit codes:
|
|
33
|
+
0 = OK, 1 = verification failed, 2 = CLI / IO error
|
|
34
|
+
|
|
35
|
+
This tool makes NO network calls. It reads the bundle and verifies
|
|
36
|
+
Ed25519 signatures against the public keys embedded in the bundle.
|
|
37
|
+
`);
|
|
38
|
+
}
|
|
39
|
+
function readSource(arg) {
|
|
40
|
+
if (arg === '-') {
|
|
41
|
+
return readFileSync(0, 'utf-8');
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
return readFileSync(arg, 'utf-8');
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
process.stderr.write(`vorim-verify: cannot read ${arg}: ${e.message}\n`);
|
|
48
|
+
process.exit(2);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function parseBundle(src) {
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(src);
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
process.stderr.write(`vorim-verify: invalid JSON: ${e.message}\n`);
|
|
57
|
+
process.exit(2);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function formatHuman(report, explain) {
|
|
61
|
+
const lines = [];
|
|
62
|
+
const status = report.ok ? 'OK' : 'FAILED';
|
|
63
|
+
lines.push(`vorim-verify: ${status}`);
|
|
64
|
+
lines.push('');
|
|
65
|
+
lines.push(`bundle_version : ${report.bundle_version ?? '(unspecified)'}`);
|
|
66
|
+
if (report.manifest_ok === null) {
|
|
67
|
+
lines.push('manifest : (no manifest field — bundle pre-dates v0)');
|
|
68
|
+
}
|
|
69
|
+
else if (report.manifest_ok) {
|
|
70
|
+
lines.push(`manifest : OK (${report.manifest_actual})`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
lines.push(`manifest : MISMATCH`);
|
|
74
|
+
lines.push(` expected: ${report.manifest_expected}`);
|
|
75
|
+
lines.push(` actual : ${report.manifest_actual}`);
|
|
76
|
+
}
|
|
77
|
+
lines.push('');
|
|
78
|
+
lines.push(`events total : ${report.event_count}`);
|
|
79
|
+
lines.push(` verified : ${report.verified}`);
|
|
80
|
+
lines.push(` unsigned : ${report.unsigned}`);
|
|
81
|
+
lines.push(` bad signature : ${report.bad_signature}`);
|
|
82
|
+
lines.push(` unknown agent : ${report.unknown_agent}`);
|
|
83
|
+
lines.push(` malformed : ${report.malformed_signature}`);
|
|
84
|
+
if (explain && report.events.length > 0) {
|
|
85
|
+
lines.push('');
|
|
86
|
+
lines.push('per-event verdicts:');
|
|
87
|
+
for (const e of report.events) {
|
|
88
|
+
const id = e.event_id ?? '(no id)';
|
|
89
|
+
const reason = e.reason ? ` — ${e.reason}` : '';
|
|
90
|
+
lines.push(` [${e.verdict.padEnd(12, ' ')}] ${id} agent=${e.agent_id ?? '?'} action=${e.action}${reason}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (!report.ok) {
|
|
94
|
+
lines.push('');
|
|
95
|
+
lines.push('Bundle did NOT verify cleanly. See verdicts above.');
|
|
96
|
+
}
|
|
97
|
+
return lines.join('\n') + '\n';
|
|
98
|
+
}
|
|
99
|
+
function main() {
|
|
100
|
+
const argv = process.argv.slice(2);
|
|
101
|
+
if (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {
|
|
102
|
+
printUsage(argv.length === 0 ? process.stderr : process.stdout);
|
|
103
|
+
process.exit(argv.length === 0 ? 2 : 0);
|
|
104
|
+
}
|
|
105
|
+
if (argv.includes('--version') || argv.includes('-v')) {
|
|
106
|
+
process.stdout.write(`${VERSION}\n`);
|
|
107
|
+
process.exit(0);
|
|
108
|
+
}
|
|
109
|
+
let json = false;
|
|
110
|
+
let explain = false;
|
|
111
|
+
const positional = [];
|
|
112
|
+
for (const a of argv) {
|
|
113
|
+
if (a === '--json')
|
|
114
|
+
json = true;
|
|
115
|
+
else if (a === '--explain')
|
|
116
|
+
explain = true;
|
|
117
|
+
else if (a.startsWith('--')) {
|
|
118
|
+
process.stderr.write(`vorim-verify: unknown flag ${a}\n`);
|
|
119
|
+
process.exit(2);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
positional.push(a);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (positional.length === 0) {
|
|
126
|
+
process.stderr.write(`vorim-verify: missing bundle path. Use - for stdin.\n`);
|
|
127
|
+
process.exit(2);
|
|
128
|
+
}
|
|
129
|
+
if (positional.length > 1) {
|
|
130
|
+
process.stderr.write(`vorim-verify: expected one bundle path, got ${positional.length}\n`);
|
|
131
|
+
process.exit(2);
|
|
132
|
+
}
|
|
133
|
+
const src = readSource(positional[0]);
|
|
134
|
+
const parsed = parseBundle(src);
|
|
135
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
136
|
+
process.stderr.write(`vorim-verify: bundle must be a JSON object\n`);
|
|
137
|
+
process.exit(2);
|
|
138
|
+
}
|
|
139
|
+
const report = verifyBundle(parsed);
|
|
140
|
+
if (json) {
|
|
141
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
process.stdout.write(formatHuman(report, explain));
|
|
145
|
+
}
|
|
146
|
+
process.exit(report.ok ? 0 : 1);
|
|
147
|
+
}
|
|
148
|
+
main();
|
|
149
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vorim/verify — Offline verifier for Vorim audit bundles.
|
|
3
|
+
*
|
|
4
|
+
* Pure Node.js (built-in `crypto` only). No network calls, no Vorim API
|
|
5
|
+
* dependency, no telemetry. Designed to be reproduced from scratch by any
|
|
6
|
+
* counterparty who wants to convince themselves the bundle is authentic
|
|
7
|
+
* without trusting Vorim.
|
|
8
|
+
*/
|
|
9
|
+
import type { AuditBundle, BundleEvent, VerifyReport } from './types.js';
|
|
10
|
+
export type { AuditBundle, BundleAgent, BundleEvent, EventResult, EventVerdict, VerifyReport, } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* VAIP v0 canonical bytes for audit-event signing.
|
|
13
|
+
*
|
|
14
|
+
* Pipe-joined content fields with empty-string substitution for missing
|
|
15
|
+
* values. Must produce byte-identical output to:
|
|
16
|
+
* - @vorim/sdk `canonicalPayloadV0` (TypeScript SDK)
|
|
17
|
+
* - vorim Python SDK `canonical_payload_v0`
|
|
18
|
+
* - @vorim/shared-types `canonicalPayloadV0` (server)
|
|
19
|
+
*
|
|
20
|
+
* This is intentionally duplicated here so the verifier has zero
|
|
21
|
+
* dependencies. The test suite for each implementation cross-checks them
|
|
22
|
+
* against the same fixture matrix.
|
|
23
|
+
*/
|
|
24
|
+
export declare function canonicalPayloadV0(event: {
|
|
25
|
+
event_type: string;
|
|
26
|
+
action: string;
|
|
27
|
+
resource?: string | null;
|
|
28
|
+
input_hash?: string | null;
|
|
29
|
+
output_hash?: string | null;
|
|
30
|
+
result: string;
|
|
31
|
+
}): string;
|
|
32
|
+
/**
|
|
33
|
+
* Verify the SHA-256 manifest over `{ events, agents }`. Returns null if
|
|
34
|
+
* the bundle has no manifest field (older exports). Manifest format is
|
|
35
|
+
* `sha256:<hex>` to match the server's `exportAuditBundle`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function verifyManifest(bundle: AuditBundle): {
|
|
38
|
+
ok: boolean | null;
|
|
39
|
+
expected: string | null;
|
|
40
|
+
actual: string | null;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Verify a single Ed25519 signature against `canonicalPayloadV0(event)`.
|
|
44
|
+
* `signature` is the `ed25519:<base64>` form the SDK produces; the prefix
|
|
45
|
+
* is stripped before decoding.
|
|
46
|
+
*/
|
|
47
|
+
export declare function verifyEventSignature(event: BundleEvent, publicKeyPem: string): {
|
|
48
|
+
ok: boolean;
|
|
49
|
+
reason?: string;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Verify every event in the bundle. Each event ends up in exactly one of
|
|
53
|
+
* five buckets:
|
|
54
|
+
*
|
|
55
|
+
* - `verified` — signature present, agent's public key found, sig valid
|
|
56
|
+
* - `unsigned` — no signature in the event (acceptable; just unverifiable)
|
|
57
|
+
* - `bad_signature` — signature present but does not verify
|
|
58
|
+
* - `unknown_agent` — signature present but no public key in `agents[]`
|
|
59
|
+
* - `malformed_signature` — signature present but unparseable / wrong key format
|
|
60
|
+
*
|
|
61
|
+
* The whole report is `ok` iff `bad_signature` and `malformed_signature`
|
|
62
|
+
* are both zero, AND the manifest verifies (or is absent). Unsigned and
|
|
63
|
+
* unknown-agent events do NOT fail the report — they are surfaced so the
|
|
64
|
+
* reader can make their own call.
|
|
65
|
+
*/
|
|
66
|
+
export declare function verifyBundle(bundle: AuditBundle): VerifyReport;
|
|
67
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EACV,WAAW,EAEX,WAAW,EAEX,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CAST;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG;IACnD,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAKA;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,EAClB,YAAY,EAAE,MAAM,GACnB;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA6BlC;AAYD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAyG9D"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vorim/verify — Offline verifier for Vorim audit bundles.
|
|
3
|
+
*
|
|
4
|
+
* Pure Node.js (built-in `crypto` only). No network calls, no Vorim API
|
|
5
|
+
* dependency, no telemetry. Designed to be reproduced from scratch by any
|
|
6
|
+
* counterparty who wants to convince themselves the bundle is authentic
|
|
7
|
+
* without trusting Vorim.
|
|
8
|
+
*/
|
|
9
|
+
import { createHash, createPublicKey, verify as cryptoVerify } from 'node:crypto';
|
|
10
|
+
/**
|
|
11
|
+
* VAIP v0 canonical bytes for audit-event signing.
|
|
12
|
+
*
|
|
13
|
+
* Pipe-joined content fields with empty-string substitution for missing
|
|
14
|
+
* values. Must produce byte-identical output to:
|
|
15
|
+
* - @vorim/sdk `canonicalPayloadV0` (TypeScript SDK)
|
|
16
|
+
* - vorim Python SDK `canonical_payload_v0`
|
|
17
|
+
* - @vorim/shared-types `canonicalPayloadV0` (server)
|
|
18
|
+
*
|
|
19
|
+
* This is intentionally duplicated here so the verifier has zero
|
|
20
|
+
* dependencies. The test suite for each implementation cross-checks them
|
|
21
|
+
* against the same fixture matrix.
|
|
22
|
+
*/
|
|
23
|
+
export function canonicalPayloadV0(event) {
|
|
24
|
+
return [
|
|
25
|
+
event.event_type,
|
|
26
|
+
event.action,
|
|
27
|
+
event.resource ?? '',
|
|
28
|
+
event.input_hash ?? '',
|
|
29
|
+
event.output_hash ?? '',
|
|
30
|
+
event.result,
|
|
31
|
+
].join('|');
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Verify the SHA-256 manifest over `{ events, agents }`. Returns null if
|
|
35
|
+
* the bundle has no manifest field (older exports). Manifest format is
|
|
36
|
+
* `sha256:<hex>` to match the server's `exportAuditBundle`.
|
|
37
|
+
*/
|
|
38
|
+
export function verifyManifest(bundle) {
|
|
39
|
+
if (!bundle.manifest)
|
|
40
|
+
return { ok: null, expected: null, actual: null };
|
|
41
|
+
const body = JSON.stringify({ events: bundle.events, agents: bundle.agents });
|
|
42
|
+
const actual = 'sha256:' + createHash('sha256').update(body).digest('hex');
|
|
43
|
+
return { ok: actual === bundle.manifest, expected: bundle.manifest, actual };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Verify a single Ed25519 signature against `canonicalPayloadV0(event)`.
|
|
47
|
+
* `signature` is the `ed25519:<base64>` form the SDK produces; the prefix
|
|
48
|
+
* is stripped before decoding.
|
|
49
|
+
*/
|
|
50
|
+
export function verifyEventSignature(event, publicKeyPem) {
|
|
51
|
+
const sig = event.signature;
|
|
52
|
+
if (!sig)
|
|
53
|
+
return { ok: false, reason: 'no signature' };
|
|
54
|
+
const stripped = sig.startsWith('ed25519:') ? sig.slice('ed25519:'.length) : sig;
|
|
55
|
+
let sigBytes;
|
|
56
|
+
try {
|
|
57
|
+
sigBytes = Buffer.from(stripped, 'base64');
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return { ok: false, reason: 'malformed base64 signature' };
|
|
61
|
+
}
|
|
62
|
+
if (sigBytes.length === 0)
|
|
63
|
+
return { ok: false, reason: 'empty signature' };
|
|
64
|
+
let pubKey;
|
|
65
|
+
try {
|
|
66
|
+
pubKey = createPublicKey(publicKeyPem);
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
reason: `unparseable public key: ${e.message}`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const payload = Buffer.from(canonicalPayloadV0(event), 'utf-8');
|
|
75
|
+
try {
|
|
76
|
+
return { ok: cryptoVerify(null, payload, pubKey, sigBytes) };
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
return { ok: false, reason: `verify error: ${e.message}` };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function eventAgentId(event) {
|
|
83
|
+
// The export joins agents and stores the public-facing agent_id as
|
|
84
|
+
// `agent_id_str`. Fall back to `agent_id` for hand-crafted bundles.
|
|
85
|
+
return ((typeof event.agent_id_str === 'string' && event.agent_id_str) ||
|
|
86
|
+
(typeof event.agent_id === 'string' && event.agent_id) ||
|
|
87
|
+
null);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Verify every event in the bundle. Each event ends up in exactly one of
|
|
91
|
+
* five buckets:
|
|
92
|
+
*
|
|
93
|
+
* - `verified` — signature present, agent's public key found, sig valid
|
|
94
|
+
* - `unsigned` — no signature in the event (acceptable; just unverifiable)
|
|
95
|
+
* - `bad_signature` — signature present but does not verify
|
|
96
|
+
* - `unknown_agent` — signature present but no public key in `agents[]`
|
|
97
|
+
* - `malformed_signature` — signature present but unparseable / wrong key format
|
|
98
|
+
*
|
|
99
|
+
* The whole report is `ok` iff `bad_signature` and `malformed_signature`
|
|
100
|
+
* are both zero, AND the manifest verifies (or is absent). Unsigned and
|
|
101
|
+
* unknown-agent events do NOT fail the report — they are surfaced so the
|
|
102
|
+
* reader can make their own call.
|
|
103
|
+
*/
|
|
104
|
+
export function verifyBundle(bundle) {
|
|
105
|
+
const agentMap = new Map((bundle.agents ?? []).map(a => [a.agent_id, a]));
|
|
106
|
+
const events = (bundle.events ?? []).map(e => {
|
|
107
|
+
const agentId = eventAgentId(e);
|
|
108
|
+
const baseId = typeof e.event_id === 'string' ? e.event_id : undefined;
|
|
109
|
+
if (!e.signature) {
|
|
110
|
+
return {
|
|
111
|
+
event_id: baseId,
|
|
112
|
+
agent_id: agentId,
|
|
113
|
+
action: e.action,
|
|
114
|
+
verdict: 'unsigned',
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (!agentId) {
|
|
118
|
+
return {
|
|
119
|
+
event_id: baseId,
|
|
120
|
+
agent_id: null,
|
|
121
|
+
action: e.action,
|
|
122
|
+
verdict: 'unknown_agent',
|
|
123
|
+
reason: 'event has no agent_id',
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const agent = agentMap.get(agentId);
|
|
127
|
+
if (!agent) {
|
|
128
|
+
return {
|
|
129
|
+
event_id: baseId,
|
|
130
|
+
agent_id: agentId,
|
|
131
|
+
action: e.action,
|
|
132
|
+
verdict: 'unknown_agent',
|
|
133
|
+
reason: `bundle.agents[] does not contain ${agentId}`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const v = verifyEventSignature(e, agent.public_key);
|
|
137
|
+
if (v.ok) {
|
|
138
|
+
return {
|
|
139
|
+
event_id: baseId,
|
|
140
|
+
agent_id: agentId,
|
|
141
|
+
action: e.action,
|
|
142
|
+
verdict: 'verified',
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (v.reason && v.reason.startsWith('unparseable public key')) {
|
|
146
|
+
return {
|
|
147
|
+
event_id: baseId,
|
|
148
|
+
agent_id: agentId,
|
|
149
|
+
action: e.action,
|
|
150
|
+
verdict: 'malformed_signature',
|
|
151
|
+
reason: v.reason,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (v.reason && (v.reason.includes('base64') || v.reason.includes('verify error'))) {
|
|
155
|
+
return {
|
|
156
|
+
event_id: baseId,
|
|
157
|
+
agent_id: agentId,
|
|
158
|
+
action: e.action,
|
|
159
|
+
verdict: 'malformed_signature',
|
|
160
|
+
reason: v.reason,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
event_id: baseId,
|
|
165
|
+
agent_id: agentId,
|
|
166
|
+
action: e.action,
|
|
167
|
+
verdict: 'bad_signature',
|
|
168
|
+
reason: v.reason,
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
const counts = {
|
|
172
|
+
verified: 0,
|
|
173
|
+
unsigned: 0,
|
|
174
|
+
bad_signature: 0,
|
|
175
|
+
unknown_agent: 0,
|
|
176
|
+
malformed_signature: 0,
|
|
177
|
+
};
|
|
178
|
+
for (const r of events)
|
|
179
|
+
counts[r.verdict]++;
|
|
180
|
+
const manifest = verifyManifest(bundle);
|
|
181
|
+
const ok = counts.bad_signature === 0 &&
|
|
182
|
+
counts.malformed_signature === 0 &&
|
|
183
|
+
manifest.ok !== false;
|
|
184
|
+
return {
|
|
185
|
+
bundle_version: typeof bundle.bundle_version === 'string' ? bundle.bundle_version : null,
|
|
186
|
+
manifest_ok: manifest.ok,
|
|
187
|
+
manifest_expected: manifest.expected,
|
|
188
|
+
manifest_actual: manifest.actual,
|
|
189
|
+
event_count: events.length,
|
|
190
|
+
verified: counts.verified,
|
|
191
|
+
unsigned: counts.unsigned,
|
|
192
|
+
bad_signature: counts.bad_signature,
|
|
193
|
+
unknown_agent: counts.unknown_agent,
|
|
194
|
+
malformed_signature: counts.malformed_signature,
|
|
195
|
+
events,
|
|
196
|
+
ok,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shape of a Vorim audit bundle as produced by the API's
|
|
3
|
+
* `POST /v1/audit/export` endpoint (bundle_version: "vaip-v0").
|
|
4
|
+
*
|
|
5
|
+
* The verifier only depends on the fields it inspects; extra fields are
|
|
6
|
+
* preserved so future bundle revisions remain readable.
|
|
7
|
+
*/
|
|
8
|
+
export interface AuditBundle {
|
|
9
|
+
bundle_version?: string;
|
|
10
|
+
canonical_form?: string;
|
|
11
|
+
manifest?: string;
|
|
12
|
+
events: BundleEvent[];
|
|
13
|
+
agents: BundleAgent[];
|
|
14
|
+
event_count?: number;
|
|
15
|
+
agent_count?: number;
|
|
16
|
+
from?: string;
|
|
17
|
+
to?: string;
|
|
18
|
+
org_id?: string;
|
|
19
|
+
generated_at?: string;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
export interface BundleEvent {
|
|
23
|
+
event_id?: string;
|
|
24
|
+
agent_id_str?: string;
|
|
25
|
+
agent_id?: string | number;
|
|
26
|
+
event_type: string;
|
|
27
|
+
action: string;
|
|
28
|
+
resource?: string | null;
|
|
29
|
+
input_hash?: string | null;
|
|
30
|
+
output_hash?: string | null;
|
|
31
|
+
result: string;
|
|
32
|
+
signature?: string | null;
|
|
33
|
+
timestamp?: string;
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
export interface BundleAgent {
|
|
37
|
+
agent_id: string;
|
|
38
|
+
public_key: string;
|
|
39
|
+
key_fingerprint?: string;
|
|
40
|
+
status?: string;
|
|
41
|
+
name?: string;
|
|
42
|
+
}
|
|
43
|
+
export type EventVerdict = 'verified' | 'unsigned' | 'bad_signature' | 'unknown_agent' | 'malformed_signature';
|
|
44
|
+
export interface EventResult {
|
|
45
|
+
event_id?: string;
|
|
46
|
+
agent_id: string | null;
|
|
47
|
+
action: string;
|
|
48
|
+
verdict: EventVerdict;
|
|
49
|
+
reason?: string;
|
|
50
|
+
}
|
|
51
|
+
export interface VerifyReport {
|
|
52
|
+
bundle_version: string | null;
|
|
53
|
+
manifest_ok: boolean | null;
|
|
54
|
+
manifest_expected: string | null;
|
|
55
|
+
manifest_actual: string | null;
|
|
56
|
+
event_count: number;
|
|
57
|
+
verified: number;
|
|
58
|
+
unsigned: number;
|
|
59
|
+
bad_signature: number;
|
|
60
|
+
unknown_agent: number;
|
|
61
|
+
malformed_signature: number;
|
|
62
|
+
events: EventResult[];
|
|
63
|
+
ok: boolean;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,YAAY,GACpB,UAAU,GACV,UAAU,GACV,eAAe,GACf,eAAe,GACf,qBAAqB,CAAC;AAE1B,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,EAAE,EAAE,OAAO,CAAC;CACb"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vorim/verify",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Offline verifier for Vorim audit bundles — no network, no Vorim API call, no telemetry.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"vorim-verify": "dist/cli.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"typecheck": "tsc --noEmit"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^22.0.0",
|
|
30
|
+
"typescript": "^5.4.0",
|
|
31
|
+
"vitest": "^2.0.0"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"vorim",
|
|
35
|
+
"audit",
|
|
36
|
+
"verifier",
|
|
37
|
+
"ed25519",
|
|
38
|
+
"offline",
|
|
39
|
+
"agent-identity",
|
|
40
|
+
"ai-agents"
|
|
41
|
+
],
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/Kzino/vorim-protocol",
|
|
45
|
+
"directory": "packages/verify"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://vorim.ai",
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/Kzino/vorim-protocol/issues"
|
|
50
|
+
},
|
|
51
|
+
"author": "Vorim AI <hello@vorim.ai>",
|
|
52
|
+
"license": "MIT",
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=18.0.0"
|
|
55
|
+
}
|
|
56
|
+
}
|