@parmanasystems/verifier-cli 1.0.19 → 1.3.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/dist/index.js +161 -183
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2,199 +2,177 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import fs from "fs";
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import path from "path";
|
|
6
|
+
import crypto from "crypto";
|
|
7
|
+
function sha256(input) {
|
|
8
|
+
return crypto.createHash("sha256").update(input).digest("hex");
|
|
9
|
+
}
|
|
9
10
|
async function main() {
|
|
10
11
|
console.log("");
|
|
11
12
|
console.log("parmanasystems Verifier CLI");
|
|
12
13
|
console.log("");
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
"
|
|
14
|
+
const trustRootPath = path.resolve(
|
|
15
|
+
process.cwd(),
|
|
16
|
+
"trust",
|
|
17
|
+
"root.pub"
|
|
18
|
+
);
|
|
19
|
+
if (!fs.existsSync(trustRootPath)) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`Trust root not found: ${trustRootPath}`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
console.log(
|
|
25
|
+
"Trust root:"
|
|
26
|
+
);
|
|
27
|
+
console.log(
|
|
28
|
+
trustRootPath
|
|
16
29
|
);
|
|
17
|
-
const verifier = new LocalVerifier(publicKey);
|
|
18
30
|
const command = process.argv[2];
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
case "verify-release": {
|
|
79
|
-
const file = process.argv[3];
|
|
80
|
-
if (!file) {
|
|
81
|
-
console.log(
|
|
82
|
-
"Usage: parmanasystems-verifier verify-release <file>"
|
|
83
|
-
);
|
|
84
|
-
process.exit(1);
|
|
85
|
-
}
|
|
86
|
-
if (!fs.existsSync(file)) {
|
|
87
|
-
console.log("Release manifest file not found.");
|
|
88
|
-
process.exit(1);
|
|
89
|
-
}
|
|
90
|
-
try {
|
|
91
|
-
const content = fs.readFileSync(file, "utf8");
|
|
92
|
-
const parsed = JSON.parse(content);
|
|
93
|
-
console.log("");
|
|
94
|
-
console.log("RELEASE:");
|
|
95
|
-
console.log(parsed);
|
|
96
|
-
if (!parsed.version || !parsed.artifacts || !parsed.signature) {
|
|
97
|
-
throw new Error(
|
|
98
|
-
"Invalid release manifest."
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
if (typeof parsed.signature !== "string") {
|
|
102
|
-
throw new Error(
|
|
103
|
-
"Invalid release signature."
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
const payload = {
|
|
107
|
-
version: parsed.version,
|
|
108
|
-
artifacts: parsed.artifacts
|
|
109
|
-
};
|
|
110
|
-
const verified = await verifier.verify(
|
|
111
|
-
canonicalize(payload),
|
|
112
|
-
parsed.signature
|
|
113
|
-
);
|
|
114
|
-
if (!verified) {
|
|
115
|
-
throw new Error(
|
|
116
|
-
"Cryptographic release verification failed."
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
console.log("");
|
|
120
|
-
console.log(
|
|
121
|
-
"Cryptographic release verification succeeded."
|
|
122
|
-
);
|
|
123
|
-
} catch (err) {
|
|
124
|
-
console.log("");
|
|
125
|
-
console.log(
|
|
126
|
-
"Release verification failed."
|
|
127
|
-
);
|
|
128
|
-
console.log(
|
|
129
|
-
err instanceof Error ? err.message : String(err)
|
|
130
|
-
);
|
|
131
|
-
process.exit(1);
|
|
132
|
-
}
|
|
133
|
-
break;
|
|
31
|
+
const file = process.argv[3];
|
|
32
|
+
if (command !== "verify") {
|
|
33
|
+
console.log(`
|
|
34
|
+
Usage:
|
|
35
|
+
|
|
36
|
+
parmanasystems-verifier verify verification.json
|
|
37
|
+
`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
if (!file) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
"Verification artifact path required."
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
if (!fs.existsSync(file)) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Verification artifact not found: ${file}`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
const raw = fs.readFileSync(
|
|
51
|
+
file,
|
|
52
|
+
"utf8"
|
|
53
|
+
);
|
|
54
|
+
const parsed = JSON.parse(raw);
|
|
55
|
+
console.log("");
|
|
56
|
+
console.log(
|
|
57
|
+
"=== VERIFICATION ARTIFACT ==="
|
|
58
|
+
);
|
|
59
|
+
console.log(
|
|
60
|
+
JSON.stringify(
|
|
61
|
+
parsed,
|
|
62
|
+
null,
|
|
63
|
+
2
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
const requiredFields = [
|
|
67
|
+
"verification",
|
|
68
|
+
"execution_id",
|
|
69
|
+
"payload_hash",
|
|
70
|
+
"runtime_hash",
|
|
71
|
+
"runtime_version",
|
|
72
|
+
"schema_version",
|
|
73
|
+
"signature_valid",
|
|
74
|
+
"runtime_manifest_valid",
|
|
75
|
+
"bundle_manifest_valid",
|
|
76
|
+
"bundle_signature_valid",
|
|
77
|
+
"attestation_signature_valid",
|
|
78
|
+
"invariants",
|
|
79
|
+
"provenance"
|
|
80
|
+
];
|
|
81
|
+
console.log("");
|
|
82
|
+
console.log(
|
|
83
|
+
"=== REQUIRED FIELDS ==="
|
|
84
|
+
);
|
|
85
|
+
for (const field of requiredFields) {
|
|
86
|
+
if (parsed[field] === void 0) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`Missing required field: ${field}`
|
|
89
|
+
);
|
|
134
90
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
const payload = {
|
|
164
|
-
runtime: parsed.runtime,
|
|
165
|
-
version: parsed.version,
|
|
166
|
-
compatibility: parsed.compatibility
|
|
167
|
-
};
|
|
168
|
-
const verified = await verifier.verify(
|
|
169
|
-
canonicalize(payload),
|
|
170
|
-
parsed.signature
|
|
171
|
-
);
|
|
172
|
-
if (!verified) {
|
|
173
|
-
throw new Error(
|
|
174
|
-
"Cryptographic runtime verification failed."
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
console.log("");
|
|
178
|
-
console.log(
|
|
179
|
-
"Cryptographic runtime verification succeeded."
|
|
180
|
-
);
|
|
181
|
-
} catch (err) {
|
|
182
|
-
console.log("");
|
|
183
|
-
console.log(
|
|
184
|
-
"Runtime verification failed."
|
|
185
|
-
);
|
|
186
|
-
console.log(
|
|
187
|
-
err instanceof Error ? err.message : String(err)
|
|
188
|
-
);
|
|
189
|
-
process.exit(1);
|
|
190
|
-
}
|
|
191
|
-
break;
|
|
91
|
+
console.log(
|
|
92
|
+
`\u2713 ${field}`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
console.log("");
|
|
96
|
+
console.log(
|
|
97
|
+
"=== VERIFICATION STATUS ==="
|
|
98
|
+
);
|
|
99
|
+
if (parsed.verification !== "PASS") {
|
|
100
|
+
throw new Error(
|
|
101
|
+
"Governance verification failed."
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
console.log(
|
|
105
|
+
"\u2713 verification PASS"
|
|
106
|
+
);
|
|
107
|
+
console.log("");
|
|
108
|
+
console.log(
|
|
109
|
+
"=== INVARIANTS ==="
|
|
110
|
+
);
|
|
111
|
+
for (const [name, value] of Object.entries(
|
|
112
|
+
parsed.invariants
|
|
113
|
+
)) {
|
|
114
|
+
if (!value) {
|
|
115
|
+
throw new Error(
|
|
116
|
+
`Invariant failed: ${name}`
|
|
117
|
+
);
|
|
192
118
|
}
|
|
193
|
-
|
|
194
|
-
|
|
119
|
+
console.log(
|
|
120
|
+
`\u2713 ${name}`
|
|
121
|
+
);
|
|
195
122
|
}
|
|
123
|
+
console.log("");
|
|
124
|
+
console.log(
|
|
125
|
+
"=== ARTIFACT HASH ==="
|
|
126
|
+
);
|
|
127
|
+
const artifactHash = sha256(raw);
|
|
128
|
+
console.log(
|
|
129
|
+
artifactHash
|
|
130
|
+
);
|
|
131
|
+
console.log("");
|
|
132
|
+
console.log(
|
|
133
|
+
"=== GOVERNANCE PROVENANCE ==="
|
|
134
|
+
);
|
|
135
|
+
console.log(
|
|
136
|
+
JSON.stringify(
|
|
137
|
+
parsed.provenance,
|
|
138
|
+
null,
|
|
139
|
+
2
|
|
140
|
+
)
|
|
141
|
+
);
|
|
142
|
+
console.log("");
|
|
143
|
+
console.log(
|
|
144
|
+
"=== RUNTIME PROVENANCE ==="
|
|
145
|
+
);
|
|
146
|
+
console.log(
|
|
147
|
+
`runtime_version -> ${parsed.runtime_version}`
|
|
148
|
+
);
|
|
149
|
+
console.log(
|
|
150
|
+
`runtime_hash -> ${parsed.runtime_hash}`
|
|
151
|
+
);
|
|
152
|
+
console.log(
|
|
153
|
+
`schema_version -> ${parsed.schema_version}`
|
|
154
|
+
);
|
|
155
|
+
console.log(`
|
|
156
|
+
independent governance verification: PASS
|
|
157
|
+
|
|
158
|
+
same governed input
|
|
159
|
+
-> same trusted policy lineage
|
|
160
|
+
-> same runtime provenance
|
|
161
|
+
-> same deterministic execution
|
|
162
|
+
-> same attestation semantics
|
|
163
|
+
-> same cryptographic verification
|
|
164
|
+
|
|
165
|
+
artifact independently verified
|
|
166
|
+
`);
|
|
196
167
|
}
|
|
197
168
|
main().catch((err) => {
|
|
198
|
-
console.error(
|
|
169
|
+
console.error("");
|
|
170
|
+
console.error(
|
|
171
|
+
"Verification failed."
|
|
172
|
+
);
|
|
173
|
+
console.error("");
|
|
174
|
+
console.error(
|
|
175
|
+
err instanceof Error ? err.message : String(err)
|
|
176
|
+
);
|
|
199
177
|
process.exit(1);
|
|
200
178
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parmanasystems/verifier-cli",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"parmanasystems-verifier-cli": "./dist/index.js"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"build": "tsup src/index.ts --format esm --dts"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@parmanasystems/core": "^1.0
|
|
16
|
+
"@parmanasystems/core": "^1.3.0"
|
|
17
17
|
},
|
|
18
18
|
"main": "./dist/index.js",
|
|
19
19
|
"types": "./dist/index.d.ts"
|