@atcn/verify-cli 1.4.1 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -13
- package/dist/cli.js +29 -6
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,31 +1,39 @@
|
|
|
1
1
|
# @atcn/verify-cli
|
|
2
2
|
|
|
3
|
-
`atcn-verify` checks ATCN
|
|
3
|
+
`atcn-verify` checks a signed [ATCN](https://github.com/fadnisnikhil/atcn) document on your machine, without contacting anyone. Use it when someone sends you a task closure, a receipt or a closure package and you want to know whether it's genuine and whether its numbers add up.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
5
|
+
It checks the signatures, recomputes the totals and exceptions from the records inside, and prints each check with its result. It accepts:
|
|
6
|
+
|
|
7
|
+
- task closures (the signed summary of an agent job and its costs);
|
|
8
|
+
- provider receipts (what one provider sees of a task);
|
|
9
|
+
- obligation closure packages (the signed record of paid work and how it was accepted);
|
|
10
|
+
- clearing verdicts (an obligation's decision, for a payment rail to read).
|
|
8
11
|
|
|
9
12
|
```bash
|
|
10
|
-
npx @atcn/verify-cli task-closure.json --keys keys.json
|
|
13
|
+
npx @atcn/verify-cli task-closure.json --keys keys.json
|
|
11
14
|
```
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
To try it, run `npx @atcn/local-runner demo`: it writes a closure, its keys and its closure packages, and prints the exact `atcn-verify` command to check them.
|
|
17
|
+
|
|
18
|
+
## Options
|
|
14
19
|
|
|
15
|
-
- **`--keys`:** a JSON array of
|
|
16
|
-
- **`--
|
|
20
|
+
- **`--keys`:** the signer's public keys, as a JSON array of key records or `{"items": [...]}`.
|
|
21
|
+
- **`--obligation-package`:** cross-checks a closure's linked obligations against their closure packages. You can repeat it. For a clearing verdict, pass the one package it was read from.
|
|
22
|
+
- **`--previous`:** checks the link to the previous version of a closure or revision of a receipt.
|
|
17
23
|
- **`--operator-keys` and `--require-operator-signature`:** check operator countersignatures.
|
|
18
|
-
- **`--
|
|
19
|
-
- **`--at <ISO-8601 time>`:** checks a
|
|
24
|
+
- **`--trace <trace.json>`:** supplies an agent trace file. You can repeat it. For a closure package, each trace is rechecked against the declared runs and every `usage_cost` result is recomputed from the terms' pricing. For a receipt or closure, each recorded usage summary is recomputed from its trace. Usage whose trace you did not supply is reported as `NOT INSPECTED`, which is neither a pass nor a failure.
|
|
25
|
+
- **`--at <ISO-8601 time>`:** checks a receipt's `expires_at` against that time instead of now, for example the time you received it.
|
|
20
26
|
- **`--json`:** prints the report as JSON.
|
|
21
27
|
|
|
22
|
-
Exit codes
|
|
28
|
+
## Exit codes
|
|
23
29
|
|
|
24
30
|
- `0`: valid.
|
|
25
31
|
- `1`: invalid.
|
|
26
32
|
- `2`: usage or input error.
|
|
27
33
|
- `3`: unsupported schema version, so upgrade `atcn-verify`.
|
|
28
34
|
|
|
29
|
-
Supported subledger schema versions are `1.2`
|
|
35
|
+
Supported subledger schema versions are `1.2` to `1.5`; see [compatibility](https://github.com/fadnisnikhil/atcn/blob/main/packages/schema/COMPATIBILITY.md).
|
|
36
|
+
|
|
37
|
+
A valid signature shows who stated something and that it hasn't changed since. It doesn't prove the work or payment really happened; each claim carries a label saying who stands behind it.
|
|
30
38
|
|
|
31
|
-
|
|
39
|
+
Part of [ATCN](https://github.com/fadnisnikhil/atcn). Apache-2.0.
|
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { parseArgs } from "node:util";
|
|
3
|
-
import { verifyClosurePackage } from "@atcn/core";
|
|
4
|
-
import { PublicKeyRecordSchema } from "@atcn/schema";
|
|
3
|
+
import { verifyClearingVerdict, verifyClosurePackage } from "@atcn/core";
|
|
4
|
+
import { CLEARING_VERDICT_TYPE, PublicKeyRecordSchema } from "@atcn/schema";
|
|
5
5
|
import { OperatorKeyRecordSchema, SUBLEDGER_VERIFIER_VERSION, SUPPORTED_SUBLEDGER_SCHEMA_VERSIONS, verifySubledgerDocument, } from "@atcn/subledger";
|
|
6
6
|
const USAGE = `usage: atcn-verify <document.json> --keys <published-keys.json> [--previous <previous-revision.json>]
|
|
7
7
|
[--operator-keys <operator-keys.json>] [--require-operator-signature]
|
|
8
|
-
[--obligation-package <closure-package.json> ...] [--
|
|
8
|
+
[--obligation-package <closure-package.json> ...] [--trace <trace.json> ...]
|
|
9
|
+
[--at <ISO-8601 time>] [--json]
|
|
9
10
|
|
|
10
11
|
Verifies offline, without contacting the service:
|
|
11
12
|
- ATCN closure packages (obligations): signatures, key validity, event references,
|
|
@@ -15,6 +16,9 @@ Verifies offline, without contacting the service:
|
|
|
15
16
|
provider response signatures, and the version chain.
|
|
16
17
|
- Subledger provider receipts (atcn.subledger.receipt): signature, schema, reversals,
|
|
17
18
|
totals, field disclosure, the revision chain, and expiry.
|
|
19
|
+
- Clearing verdicts (atcn.clearing.verdict): the service signature and, with --obligation-package, that
|
|
20
|
+
the package verifies and the verdict states the decision in effect in it. ATCN only publishes a verdict;
|
|
21
|
+
an escrow rail decides whether to release.
|
|
18
22
|
--keys accepts a JSON array of public key records or the /v1/service/keys response ({"items": [...]}).
|
|
19
23
|
--previous checks the chain link to the prior receipt revision or closure version.
|
|
20
24
|
--operator-keys checks countersignatures made with the operator's own keys
|
|
@@ -22,6 +26,11 @@ Verifies offline, without contacting the service:
|
|
|
22
26
|
--obligation-package (repeatable) cross-checks a task closure's obligation-backed delegations against
|
|
23
27
|
the obligations' closure packages (GET /v1/exports/{obligation_id}): each package must verify, and its
|
|
24
28
|
journal must produce exactly the costs the closure recorded from the clearing network.
|
|
29
|
+
For a clearing verdict, pass the one package it was read from.
|
|
30
|
+
--trace (repeatable) supplies agent trace files. For a closure package it rechecks agent_trace evidence
|
|
31
|
+
against the declared runs and recomputes usage_cost results from the terms' pricing; for a subledger
|
|
32
|
+
receipt or closure it recomputes each recorded usage summary from its trace. Evidence or usage whose
|
|
33
|
+
trace was not supplied is reported as NOT INSPECTED, which is neither a pass nor a failure.
|
|
25
34
|
--at checks a provider receipt's expires_at against that time instead of now.
|
|
26
35
|
Subledger schema versions supported: ${SUPPORTED_SUBLEDGER_SCHEMA_VERSIONS.join(", ")} (atcn-verify ${SUBLEDGER_VERIFIER_VERSION}).
|
|
27
36
|
Exit code 0 = valid, 1 = invalid, 2 = usage or input error, 3 = unsupported schema version (upgrade atcn-verify).`;
|
|
@@ -56,6 +65,7 @@ function main() {
|
|
|
56
65
|
"operator-keys": { type: "string" },
|
|
57
66
|
"require-operator-signature": { type: "boolean" },
|
|
58
67
|
"obligation-package": { type: "string", multiple: true },
|
|
68
|
+
trace: { type: "string", multiple: true },
|
|
59
69
|
at: { type: "string" },
|
|
60
70
|
json: { type: "boolean" },
|
|
61
71
|
help: { type: "boolean" },
|
|
@@ -80,7 +90,18 @@ function main() {
|
|
|
80
90
|
try {
|
|
81
91
|
const doc = readJson(parsed.positionals[0]);
|
|
82
92
|
const trustedKeys = loadKeys(parsed.values.keys);
|
|
83
|
-
|
|
93
|
+
const traces = parsed.values.trace?.map((path) => new Uint8Array(readFileSync(path)));
|
|
94
|
+
const documentType = doc?.payload?.document_type;
|
|
95
|
+
if (documentType === CLEARING_VERDICT_TYPE) {
|
|
96
|
+
const packages = parsed.values["obligation-package"]?.map(readJson) ?? [];
|
|
97
|
+
if (packages.length > 1) {
|
|
98
|
+
console.error(`a clearing verdict is checked against one --obligation-package, got ${packages.length}\n\n${USAGE}`);
|
|
99
|
+
return 2;
|
|
100
|
+
}
|
|
101
|
+
report = verifyClearingVerdict(doc, { trustedKeys, closurePackage: packages[0] });
|
|
102
|
+
label = "clearing verdict";
|
|
103
|
+
}
|
|
104
|
+
else if (isSubledgerDocument(doc)) {
|
|
84
105
|
const previous = parsed.values.previous ? readJson(parsed.values.previous) : undefined;
|
|
85
106
|
const operatorKeysPath = parsed.values["operator-keys"];
|
|
86
107
|
const operatorKeys = operatorKeysPath ? loadOperatorKeys(operatorKeysPath) : undefined;
|
|
@@ -91,13 +112,14 @@ function main() {
|
|
|
91
112
|
operatorKeys,
|
|
92
113
|
requireOperatorSignature: parsed.values["require-operator-signature"],
|
|
93
114
|
obligationPackages,
|
|
115
|
+
traces,
|
|
94
116
|
at: at === undefined ? undefined : new Date(at).toISOString(),
|
|
95
117
|
});
|
|
96
118
|
report = result;
|
|
97
119
|
label = result.document_type === "atcn.subledger.receipt" ? "provider receipt" : "task closure";
|
|
98
120
|
}
|
|
99
121
|
else {
|
|
100
|
-
report = verifyClosurePackage(doc, { trustedKeys });
|
|
122
|
+
report = verifyClosurePackage(doc, { trustedKeys, traces });
|
|
101
123
|
label = "closure package";
|
|
102
124
|
}
|
|
103
125
|
}
|
|
@@ -113,7 +135,8 @@ function main() {
|
|
|
113
135
|
}
|
|
114
136
|
else {
|
|
115
137
|
for (const check of report.checks) {
|
|
116
|
-
|
|
138
|
+
const status = !check.ok ? "FAIL" : check.state === "not_inspected" ? "NOT INSPECTED" : "PASS";
|
|
139
|
+
console.log(`${status} ${check.name}`);
|
|
117
140
|
for (const detail of check.details)
|
|
118
141
|
console.log(` ${detail}`);
|
|
119
142
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atcn/verify-cli",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "atcn-verify: check a signed ATCN closure, receipt, closure package or clearing verdict offline, without contacting anyone",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"build": "tsc -p tsconfig.build.json"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@atcn/core": "1.
|
|
31
|
-
"@atcn/schema": "1.
|
|
32
|
-
"@atcn/subledger": "1.
|
|
30
|
+
"@atcn/core": "1.5.1",
|
|
31
|
+
"@atcn/schema": "1.5.1",
|
|
32
|
+
"@atcn/subledger": "1.5.1"
|
|
33
33
|
}
|
|
34
34
|
}
|