pazair-verify 1.6.0 → 1.7.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 +9 -9
- package/README.md +96 -67
- package/bin/cli.js +38 -22
- package/package.json +68 -56
- package/src/index.d.ts +45 -28
- package/src/index.js +362 -322
- package/src/remember.js +151 -0
package/LICENSE
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Kula Labs
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
-
|
|
7
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
-
|
|
9
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kula Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,67 +1,96 @@
|
|
|
1
|
-
# pazair-verify
|
|
2
|
-
|
|
3
|
-
Trust between AI agents, checkable by anyone. Verify PazAIr receipts, Word Passes and Merkle proofs
|
|
4
|
-
(the [PazAIr Trust Protocol](../SPEC.md)) in a few lines, without trusting PazAIr.
|
|
5
|
-
|
|
6
|
-
Zero dependencies. WebCrypto (Ed25519, SHA-256): Node 20+, Deno, Bun, Cloudflare Workers, browsers.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
1
|
+
# pazair-verify
|
|
2
|
+
|
|
3
|
+
Trust between AI agents, checkable by anyone. Verify PazAIr receipts, Word Passes and Merkle proofs
|
|
4
|
+
(the [PazAIr Trust Protocol](../SPEC.md)) in a few lines, without trusting PazAIr.
|
|
5
|
+
|
|
6
|
+
Zero dependencies. WebCrypto (Ed25519, SHA-256): Node 20+, Deno, Bun, Cloudflare Workers, browsers.
|
|
7
|
+
To also check the post-quantum signatures (ML-DSA-65, FIPS 204) install `@noble/post-quantum` next to it; without it
|
|
8
|
+
they are reported as *not checked*, never as valid.
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
npm install pazair-verify
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## "May I see your Word Pass?"
|
|
15
|
+
|
|
16
|
+
Another agent answers with its pass URL. Check it, from any issuer, in one line:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
npx pazair-verify https://pazair.kulalabs.ch/v1/agents/ag_xyz/pass
|
|
20
|
+
# Alpha (Word Pass by pazair): kept its word on 99 % or more; 12 paid orders delivered to 6 buyers, 0 disputes lost.
|
|
21
|
+
# Checked: signature of pazair.kulalabs.ch valid, in the Merkle root of 2026-10-05, found on Stellar, confirmed in Bitcoin block 915102 (2026-10-05).
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
import { checkWordPass } from 'pazair-verify';
|
|
26
|
+
const r = await checkWordPass(urlTheOtherAgentGaveYou);
|
|
27
|
+
if (r.trust === 'kept_its_word') { /* trade */ } // also: signed_unanchored, no_badge_yet, invalid, unreachable
|
|
28
|
+
console.log(r.say); // one sentence for your principal
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
A URL can be copied. To be sure the pass belongs to the agent showing it, send a fresh random nonce first; it
|
|
32
|
+
answers with a holder proof from its issuer, and you check both:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
const nonce = crypto.randomUUID();
|
|
36
|
+
// ... the other agent replies with { url, proof } ...
|
|
37
|
+
const r = await checkWordPass(url, { proof, nonce }); // r.checks.holder === true
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Remember: "Forgets nothing. Holds nothing against you."
|
|
41
|
+
|
|
42
|
+
An issuer's daily roots form one chain, `head_d = sha256(head_{d-1} ‖ root_d)` from 64 zeros, every link signed with
|
|
43
|
+
Ed25519 and ML-DSA-65. Every answer the issuer gives carries the current head (`pazair-head` header). Recompute the
|
|
44
|
+
whole chain here, from the issuer's published roots, and compare it with what the issuer claims:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
npx pazair-verify remember https://pazair.kulalabs.ch
|
|
48
|
+
# https://pazair.kulalabs.ch: Remember holds. 12 days recomputed from genesis to head 3f9c1a…, document signed by the issuer's key and by ML-DSA-65, 12/12 links signed (12 post-quantum).
|
|
49
|
+
|
|
50
|
+
npx pazair-verify witness 2026-10-10:3f9c1a… # a head you kept from an earlier answer
|
|
51
|
+
# Your head of 2026-10-10 is what the chain recomputes to today; 2 day(s) anchored since.
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
import { checkRemember, checkHead, recomputeChain } from 'pazair-verify';
|
|
56
|
+
const r = await checkRemember('https://pazair.kulalabs.ch'); // r.verdict: consistent | inconsistent | unreachable
|
|
57
|
+
const h = await checkHead('2026-10-10:3f9c…'); // the head you kept, against the chain you recompute
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Nothing here asks the issuer whether its chain is fine. The chain is fetched as data and recomputed; the issuer's
|
|
61
|
+
`witness` tool is for the issuer's own count of witnesses, this is yours. SPEC section 14 has the formulas.
|
|
62
|
+
|
|
63
|
+
## Lower level
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
import { verifyPass, verifyReceipt } from 'pazair-verify';
|
|
67
|
+
|
|
68
|
+
// Before you buy: is this seller as good as it says?
|
|
69
|
+
const res = await fetch('https://pazair.kulalabs.ch/v1/agents/ag_xyz/pass');
|
|
70
|
+
const { anchored } = await res.json();
|
|
71
|
+
console.log(await verifyPass(anchored));
|
|
72
|
+
// { valid: true, signature_valid: true, in_root: true, word: { kept_pct: 99.2, badge: 'word_kept_99' }, anchors: {...} }
|
|
73
|
+
|
|
74
|
+
// After delivery: is this receipt real, and is this the delivery it covers?
|
|
75
|
+
console.log(await verifyReceipt(receipt, { delivery }));
|
|
76
|
+
// { valid: true, signature_valid: true, delivery_matches: true }
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
| Function | Checks |
|
|
80
|
+
|---|---|
|
|
81
|
+
| `checkWordPass(url, { fetch?, keys?, proof?, nonce? })` | the pass at a URL with the issuer's own keys, the proof, the root on Stellar and in its Bitcoin block; a verdict and a sentence |
|
|
82
|
+
| `checkRemember(origin, { fetch? })` | Section 14: the Remember document's two signatures, the chain recomputed from genesis, the document's head against it, every link's two signatures; a verdict and a sentence |
|
|
83
|
+
| `checkHead("<day>:<head>", origin, { fetch? })` | a head you kept (`pazair-head`) against the chain you recompute; consistent, inconsistent, unreachable |
|
|
84
|
+
| `recomputeChain(days)` / `verifyLink(link, sig, { keys, pqPublicKey })` / `verifyRememberDocument(doc, { keys })` | the pieces: heads from roots with the first broken day, one link's Ed25519 and ML-DSA-65 signatures, the document's |
|
|
85
|
+
| `bitcoinHasRoot(otsBase64, root, { fetch? })` | the .ots proof is for this root and ends in the Merkle root of the block it names (public block explorers) |
|
|
86
|
+
| `verifyReceipt(receipt, { keys?, delivery? })` | Ed25519 signature; optionally that `delivery` is the one signed |
|
|
87
|
+
| `verifyReceiptChain(top, { receipts, keys?, maxDepth? })` | Section 3.1: every receipt `top` was built on is present, signed, bought by its seller for that order; returns `{ valid, links, depth, total_minor, broken }` |
|
|
88
|
+
| `verifyMandate(receipt, mandate, { keys?, end? })` | Section 3.2: the receipt was bought within the principal's mandate (agent, currency, cap per order, before its end); returns `{ valid, covers, reasons }` |
|
|
89
|
+
| `verifyAward(receipt, tender, award, { keys?, qa? })` | Section 3.3: the receipt was paid under this award for this tender (buyer, awarded seller, budget, price or milestone, deadline, questions published before the award); returns `{ valid, covers, reasons }` |
|
|
90
|
+
| `receiptHash(receipt)` | The hash a parent receipt lists in `inputs` |
|
|
91
|
+
| `verifyPass(anchored, { keys? })` | signature, Merkle proof into the day's root; returns the anchors to check on Bitcoin and Stellar |
|
|
92
|
+
| `verifyProof(leaf, proof, root)` | a Merkle path |
|
|
93
|
+
| `leafOf(pass)`, `canonical(obj)`, `sha256hex(s)` | the building blocks of the spec |
|
|
94
|
+
| `fetchKeys(origin?)` | the issuer's keys from `/.well-known/pazair-receipts.json` |
|
|
95
|
+
|
|
96
|
+
Pass `keys` you pinned yourself to verify fully offline. MIT licensed, by Kula Labs, Switzerland.
|
package/bin/cli.js
CHANGED
|
@@ -1,22 +1,38 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// npx pazair-verify <word pass url> [--json]: "May I see your Word Pass?", checked from the command line.
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const clean = (s) => s.replace(/[\u0000-\u001f\u007f-\u009f]/g, '?'); //
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// npx pazair-verify <word pass url> [--json]: "May I see your Word Pass?", checked from the command line.
|
|
3
|
+
// npx pazair-verify remember [origin] [--json]: Remember, the issuer's chain of daily roots, recomputed here.
|
|
4
|
+
// npx pazair-verify witness <day:head> [origin] [--json]: a head you kept, against the chain you recompute.
|
|
5
|
+
// Exit codes: 0 trusted / consistent, 1 invalid / inconsistent (do not rely on it), 2 usage, 3 unreachable (could not check).
|
|
6
|
+
import { readFileSync } from 'node:fs';
|
|
7
|
+
import { checkHead, checkRemember, checkWordPass } from '../src/index.js';
|
|
8
|
+
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
if (args.includes('-v') || args.includes('--version')) {
|
|
11
|
+
console.log(JSON.parse(readFileSync(new URL('../package.json', import.meta.url))).version);
|
|
12
|
+
process.exit(0);
|
|
13
|
+
}
|
|
14
|
+
const words = args.filter((a) => !a.startsWith('-'));
|
|
15
|
+
const help = args.includes('-h') || args.includes('--help');
|
|
16
|
+
const json = args.includes('--json');
|
|
17
|
+
const usage = 'Usage: npx pazair-verify <word pass url> [--json]\n npx pazair-verify remember [origin] [--json]\n npx pazair-verify witness <day:head> [origin] [--json]\nExamples: npx pazair-verify https://pazair.kulalabs.ch/v1/agents/ag_xyz/pass\n npx pazair-verify remember https://pazair.kulalabs.ch\n npx pazair-verify witness 2026-10-10:3f9c… https://pazair.kulalabs.ch';
|
|
18
|
+
if (!words.length || help) { (help ? console.log : console.error)(usage); process.exit(help ? 0 : 2); }
|
|
19
|
+
const clean = (s) => String(s).replace(/[\u0000-\u001f\u007f-\u009f]/g, '?'); // nothing from the network rewrites your terminal
|
|
20
|
+
const codes = { consistent: 0, kept_its_word: 0, no_badge_yet: 0, signed_unanchored: 0, inconsistent: 1, invalid: 1, unreachable: 3 };
|
|
21
|
+
|
|
22
|
+
if (words[0] === 'remember') {
|
|
23
|
+
const r = await checkRemember(words[1] ?? 'https://pazair.kulalabs.ch');
|
|
24
|
+
console.log(clean(r.say));
|
|
25
|
+
if (json) console.log(JSON.stringify(r, null, 2));
|
|
26
|
+
process.exit(codes[r.verdict] ?? 1);
|
|
27
|
+
}
|
|
28
|
+
if (words[0] === 'witness') {
|
|
29
|
+
if (!words[1]) { console.error(usage); process.exit(2); }
|
|
30
|
+
const r = await checkHead(words[1], words[2] ?? 'https://pazair.kulalabs.ch');
|
|
31
|
+
console.log(clean(r.say));
|
|
32
|
+
if (json) console.log(JSON.stringify(r, null, 2));
|
|
33
|
+
process.exit(codes[r.verdict] ?? 1);
|
|
34
|
+
}
|
|
35
|
+
const r = await checkWordPass(words[0]);
|
|
36
|
+
console.log(clean(r.say));
|
|
37
|
+
if (json) console.log(JSON.stringify({ ...r, pass: undefined }, null, 2));
|
|
38
|
+
process.exit(codes[r.trust] ?? 1);
|
package/package.json
CHANGED
|
@@ -1,56 +1,68 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pazair-verify",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Verify Word Passes, receipts
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./src/index.js",
|
|
7
|
-
"types": "./src/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./src/index.d.ts",
|
|
11
|
-
"default": "./src/index.js"
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
"files": [
|
|
15
|
-
"src",
|
|
16
|
-
"bin",
|
|
17
|
-
"README.md",
|
|
18
|
-
"LICENSE"
|
|
19
|
-
],
|
|
20
|
-
"engines": {
|
|
21
|
-
"node": ">=20"
|
|
22
|
-
},
|
|
23
|
-
"scripts": {
|
|
24
|
-
"test": "node --test test/*.test.js"
|
|
25
|
-
},
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "pazair-verify",
|
|
3
|
+
"version": "1.7.0",
|
|
4
|
+
"description": "Verify Word Passes, receipts, Merkle proofs and Remember (the chain of daily roots, Ed25519 + ML-DSA-65): checked by anyone, for any issuer, without trusting it. Zero dependencies.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"types": "./src/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"default": "./src/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"src",
|
|
16
|
+
"bin",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"test": "node --test test/*.test.js"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@noble/post-quantum": "^0.7.1"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@noble/post-quantum": ">=0.7.0"
|
|
31
|
+
},
|
|
32
|
+
"peerDependenciesMeta": {
|
|
33
|
+
"@noble/post-quantum": { "optional": true }
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"word-pass",
|
|
37
|
+
"remember",
|
|
38
|
+
"post-quantum",
|
|
39
|
+
"ml-dsa",
|
|
40
|
+
"ai-agents",
|
|
41
|
+
"agent-trust",
|
|
42
|
+
"a2a",
|
|
43
|
+
"mcp",
|
|
44
|
+
"reputation",
|
|
45
|
+
"receipts",
|
|
46
|
+
"ed25519",
|
|
47
|
+
"merkle",
|
|
48
|
+
"bitcoin",
|
|
49
|
+
"stellar",
|
|
50
|
+
"pazair"
|
|
51
|
+
],
|
|
52
|
+
"author": "Kula Labs (https://kulalabs.ch)",
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"homepage": "https://github.com/Kula-Labs/pazair/tree/main/verify",
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "git+https://github.com/Kula-Labs/pazair.git",
|
|
58
|
+
"directory": "verify"
|
|
59
|
+
},
|
|
60
|
+
"bin": {
|
|
61
|
+
"pazair-verify": "bin/cli.js",
|
|
62
|
+
"word-pass": "bin/cli.js"
|
|
63
|
+
},
|
|
64
|
+
"publishConfig": {
|
|
65
|
+
"access": "public",
|
|
66
|
+
"provenance": true
|
|
67
|
+
}
|
|
68
|
+
}
|
package/src/index.d.ts
CHANGED
|
@@ -1,28 +1,45 @@
|
|
|
1
|
-
export type Jwk = { kid: string; kty?: string; crv?: string; x: string; revoked_at?: string };
|
|
2
|
-
export type Step = { side: 'L' | 'R'; hash: string };
|
|
3
|
-
export function canonical(v: unknown): string;
|
|
4
|
-
export function sha256hex(s: string): Promise<string>;
|
|
5
|
-
export function fetchKeys(origin?: string, f?: typeof fetch): Promise<Jwk[]>;
|
|
6
|
-
export function verifySignature(obj: { sig?: string; kid?: string } & Record<string, unknown>, keys: Jwk[], opts?: { anchoredBefore?: string }): Promise<boolean>;
|
|
7
|
-
export function fetchKeysDocument(origin?: string, f?: typeof fetch): Promise<{ keys: Jwk[]; anchors?: { stellar?: { account: string; network: string } } }>;
|
|
8
|
-
export function verifyHolderProof(proof: unknown, opts: { keys?: Jwk[]; agent: string; nonce: string; aud?: string; now?: number }): Promise<{ ok: boolean; reason: string }>;
|
|
9
|
-
export function verifyReceipt(receipt: Record<string, unknown>, opts?: { keys?: Jwk[]; delivery?: unknown }): Promise<{ valid: boolean; signature_valid: boolean; delivery_matches: boolean | null }>;
|
|
10
|
-
export function wordOf(pass: Record<string, unknown>): { kept_pct: number | null; badge: 'word_kept_99' | 'word_kept_95' | null };
|
|
11
|
-
export function verifyMandate(receipt: Record<string, unknown>, mandate: Record<string, unknown>, opts?: { keys?: Jwk[]; end?: Record<string, unknown> }): Promise<{ valid: boolean; covers: string[]; reasons: string[] }>;
|
|
12
|
-
export function
|
|
13
|
-
export function
|
|
14
|
-
export function
|
|
15
|
-
export function
|
|
16
|
-
export function
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export
|
|
25
|
-
export function
|
|
26
|
-
export function
|
|
27
|
-
export function
|
|
28
|
-
export function
|
|
1
|
+
export type Jwk = { kid: string; kty?: string; crv?: string; x: string; revoked_at?: string };
|
|
2
|
+
export type Step = { side: 'L' | 'R'; hash: string };
|
|
3
|
+
export function canonical(v: unknown): string;
|
|
4
|
+
export function sha256hex(s: string): Promise<string>;
|
|
5
|
+
export function fetchKeys(origin?: string, f?: typeof fetch): Promise<Jwk[]>;
|
|
6
|
+
export function verifySignature(obj: { sig?: string; kid?: string } & Record<string, unknown>, keys: Jwk[], opts?: { anchoredBefore?: string }): Promise<boolean>;
|
|
7
|
+
export function fetchKeysDocument(origin?: string, f?: typeof fetch): Promise<{ keys: Jwk[]; anchors?: { stellar?: { account: string; network: string } } }>;
|
|
8
|
+
export function verifyHolderProof(proof: unknown, opts: { keys?: Jwk[]; agent: string; nonce: string; aud?: string; now?: number }): Promise<{ ok: boolean; reason: string }>;
|
|
9
|
+
export function verifyReceipt(receipt: Record<string, unknown>, opts?: { keys?: Jwk[]; delivery?: unknown }): Promise<{ valid: boolean; signature_valid: boolean; delivery_matches: boolean | null }>;
|
|
10
|
+
export function wordOf(pass: Record<string, unknown>): { kept_pct: number | null; badge: 'word_kept_99' | 'word_kept_95' | null };
|
|
11
|
+
export function verifyMandate(receipt: Record<string, unknown>, mandate: Record<string, unknown>, opts?: { keys?: Jwk[]; end?: Record<string, unknown> }): Promise<{ valid: boolean; covers: string[]; reasons: string[] }>;
|
|
12
|
+
export function verifyAward(receipt: Record<string, unknown>, tender: Record<string, unknown>, award: Record<string, unknown>, opts?: { keys?: Jwk[]; qa?: Record<string, unknown>[] }): Promise<{ valid: boolean; covers: string[]; reasons: string[] }>;
|
|
13
|
+
export function receiptHash(receipt: Record<string, unknown>): Promise<string>;
|
|
14
|
+
export function verifyReceiptChain(top: Record<string, unknown>, opts?: { receipts?: Record<string, unknown>[]; keys?: Jwk[]; maxDepth?: number }): Promise<{ valid: boolean; links: number; depth: number; total_minor: Record<string, number>; broken: string | null }>;
|
|
15
|
+
export function leafOf(pass: Record<string, unknown>): Promise<string>;
|
|
16
|
+
export function verifyProof(leaf: string, proof: Step[], root: string): Promise<boolean>;
|
|
17
|
+
export function verifyPass(anchored: Record<string, unknown>, opts?: { keys?: Jwk[]; anchoredBefore?: string }): Promise<{ valid: boolean; signature_valid: boolean; word_consistent: boolean; in_root: boolean | null; word: unknown; anchors: { root: string; day: string; bitcoin_ots: string | null; stellar_tx: string | null } | null }>;
|
|
18
|
+
export type PassCheck = {
|
|
19
|
+
trust: 'kept_its_word' | 'signed_unanchored' | 'no_badge_yet' | 'invalid' | 'unreachable';
|
|
20
|
+
say: string; issuer: string | null;
|
|
21
|
+
checks: { signature: boolean; in_root: boolean | null; day: string | null; stellar: boolean | null; stellar_account_bound: boolean; bitcoin_ots: boolean; bitcoin: boolean | null; bitcoin_block?: BitcoinBlock; holder: boolean | null; word: boolean } | null;
|
|
22
|
+
pass: Record<string, unknown> | null;
|
|
23
|
+
};
|
|
24
|
+
export type BitcoinBlock = { height: number; hash: string; time: string };
|
|
25
|
+
export function readOts(bytes: Uint8Array): Promise<{ digest: string; claims: { height: number; msg: string }[] }>;
|
|
26
|
+
export function bitcoinHasRoot(otsBase64: string, root: string, opts?: { fetch?: typeof fetch; explorers?: string[] }): Promise<{ ok: boolean | null; status: 'confirmed' | 'pending' | 'unverified' | 'wrong_root' | 'wrong_block' | 'unreadable'; block?: BitcoinBlock }>;
|
|
27
|
+
export function stellarHasRoot(tx: string, root: string, opts?: { fetch?: typeof fetch; horizon?: string; account?: string }): Promise<boolean | null>;
|
|
28
|
+
export function checkWordPass(url: string, opts?: { fetch?: typeof fetch; keys?: Jwk[]; proof?: unknown; nonce?: string; aud?: string }): Promise<PassCheck>;
|
|
29
|
+
export function sayPass(pass: Record<string, unknown>, by?: string): string;
|
|
30
|
+
|
|
31
|
+
// Remember (SPEC section 14): the chain of daily roots and its two signatures, checked without the issuer.
|
|
32
|
+
export const GENESIS: string;
|
|
33
|
+
export function headOf(prev: string, root: string): Promise<string>;
|
|
34
|
+
export type ChainHead = { day: string; root: string; prev: string; head: string; published_head: string | null; published_matches: boolean | null };
|
|
35
|
+
export function recomputeChain(days: { day: string; root: string; head?: string | null }[]): Promise<{ head: string; days: number; last_day: string | null; broken_at: string | null; heads: ChainHead[] }>;
|
|
36
|
+
export type HeadSig = { kid: string; ed25519: string; pq_kid: string; ml_dsa_65: string; over?: string };
|
|
37
|
+
/** ml_dsa_65 is null when @noble/post-quantum is not installed next to pazair-verify: not checked, never trusted. */
|
|
38
|
+
export function verifyLink(link: { day: string; prev: string; root: string; head: string }, sig: HeadSig | null, opts?: { keys?: Jwk[]; pqPublicKey?: string }): Promise<{ ed25519: boolean; ml_dsa_65: boolean | null; pq_kid_matches: boolean }>;
|
|
39
|
+
export function verifyRememberDocument(doc: Record<string, unknown>, opts?: { keys?: Jwk[] }): Promise<{ ed25519: boolean; ml_dsa_65: boolean | null; pq_kid_matches: boolean }>;
|
|
40
|
+
export function loadMlDsa(): Promise<unknown | null>;
|
|
41
|
+
export function verifyMlDsa(sigB64u: string, msg: Uint8Array, publicKeyB64u: string): Promise<boolean | null>;
|
|
42
|
+
export function pqKid(publicKeyB64u: string): Promise<string>;
|
|
43
|
+
export type RememberCheck = { verdict: 'consistent' | 'inconsistent' | 'unreachable'; origin: string; say: string; checks: { document: { ed25519: boolean; ml_dsa_65: boolean | null; pq_kid_matches: boolean; kid_in_issuer_keys: boolean }; chain: { days: number; recomputed_head: string; document_head: string | null; head_matches: boolean; broken_at: string | null; published_heads_match: boolean }; links: { with_signature: number; ed25519_valid: number; ml_dsa_65_valid: number | null; failures: string[] }; ml_dsa_65_checked: boolean } | null };
|
|
44
|
+
export function checkRemember(origin?: string, opts?: { fetch?: typeof fetch }): Promise<RememberCheck>;
|
|
45
|
+
export function checkHead(kept: string, origin?: string, opts?: { fetch?: typeof fetch }): Promise<{ verdict: 'consistent' | 'inconsistent' | 'unreachable'; day?: string; kept?: string; recomputed?: string | null; published?: string | null; days_since?: number; say: string }>;
|