@aarmos/bridge 0.1.10 → 0.1.11

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.
Files changed (45) hide show
  1. package/dist/bridge.js +7 -129
  2. package/dist/chunk-GMH5B5YX.js +871 -0
  3. package/dist/index.js +1500 -219
  4. package/dist/verify-O6X7MFEE.js +409 -0
  5. package/package.json +4 -3
  6. package/dist/bridge.js.map +0 -1
  7. package/dist/commands/attest.js +0 -62
  8. package/dist/commands/attest.js.map +0 -1
  9. package/dist/commands/demo.js +0 -171
  10. package/dist/commands/demo.js.map +0 -1
  11. package/dist/commands/dev.js +0 -56
  12. package/dist/commands/dev.js.map +0 -1
  13. package/dist/commands/pack.js +0 -96
  14. package/dist/commands/pack.js.map +0 -1
  15. package/dist/commands/playbook.js +0 -55
  16. package/dist/commands/playbook.js.map +0 -1
  17. package/dist/commands/run.js +0 -290
  18. package/dist/commands/run.js.map +0 -1
  19. package/dist/commands/simulate.js +0 -180
  20. package/dist/commands/simulate.js.map +0 -1
  21. package/dist/commands/verify.js +0 -87
  22. package/dist/commands/verify.js.map +0 -1
  23. package/dist/index.js.map +0 -1
  24. package/dist/lib/attest.js +0 -167
  25. package/dist/lib/attest.js.map +0 -1
  26. package/dist/lib/http-broker.js +0 -82
  27. package/dist/lib/http-broker.js.map +0 -1
  28. package/dist/lib/llm-test.js +0 -174
  29. package/dist/lib/llm-test.js.map +0 -1
  30. package/dist/lib/mcp-broker.js +0 -85
  31. package/dist/lib/mcp-broker.js.map +0 -1
  32. package/dist/lib/pack.js +0 -84
  33. package/dist/lib/pack.js.map +0 -1
  34. package/dist/lib/playbook.js +0 -237
  35. package/dist/lib/playbook.js.map +0 -1
  36. package/dist/lib/scope-templates.js +0 -152
  37. package/dist/lib/scope-templates.js.map +0 -1
  38. package/dist/rpc/router.js +0 -349
  39. package/dist/rpc/router.js.map +0 -1
  40. package/dist/session.js +0 -100
  41. package/dist/session.js.map +0 -1
  42. package/dist/watchers/files.js +0 -31
  43. package/dist/watchers/files.js.map +0 -1
  44. package/dist/watchers/git.js +0 -39
  45. package/dist/watchers/git.js.map +0 -1
@@ -0,0 +1,409 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/commands/verify.ts
4
+ import { readFile } from "fs/promises";
5
+ import { unzipSync as unzipSync2, strFromU8 as strFromU82 } from "fflate";
6
+
7
+ // ../avar-core/dist/index.js
8
+ import { unzipSync, strFromU8 } from "fflate";
9
+ var NFC = (s) => s.normalize("NFC");
10
+ function encodeString(s) {
11
+ return JSON.stringify(NFC(s));
12
+ }
13
+ function encodeNumber(n) {
14
+ if (!Number.isFinite(n)) {
15
+ throw new Error(`avar-core/canonicalize: non-finite number (${n}) is forbidden.`);
16
+ }
17
+ return JSON.stringify(n);
18
+ }
19
+ function canonicalize(value) {
20
+ if (value === null) return "null";
21
+ if (typeof value === "boolean") return value ? "true" : "false";
22
+ if (typeof value === "number") return encodeNumber(value);
23
+ if (typeof value === "string") return encodeString(value);
24
+ if (typeof value === "undefined") {
25
+ throw new Error("avar-core/canonicalize: undefined is forbidden at value position.");
26
+ }
27
+ if (typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") {
28
+ throw new Error(`avar-core/canonicalize: ${typeof value} is forbidden.`);
29
+ }
30
+ if (Array.isArray(value)) {
31
+ return "[" + value.map((v) => canonicalize(v)).join(",") + "]";
32
+ }
33
+ if (typeof value === "object") {
34
+ const obj = value;
35
+ const keys = [];
36
+ for (const k of Object.keys(obj)) {
37
+ if (obj[k] === void 0) continue;
38
+ keys.push(NFC(k));
39
+ }
40
+ keys.sort();
41
+ const parts = new Array(keys.length);
42
+ for (let i = 0; i < keys.length; i++) {
43
+ const k = keys[i];
44
+ const rawVal = obj[k] ?? findKey(obj, k);
45
+ parts[i] = encodeString(k) + ":" + canonicalize(rawVal);
46
+ }
47
+ return "{" + parts.join(",") + "}";
48
+ }
49
+ throw new Error(`avar-core/canonicalize: unsupported type ${typeof value}.`);
50
+ }
51
+ function findKey(obj, nfcKey) {
52
+ for (const k of Object.keys(obj)) {
53
+ if (NFC(k) === nfcKey) return obj[k];
54
+ }
55
+ return void 0;
56
+ }
57
+ function utf8(s) {
58
+ return new TextEncoder().encode(s);
59
+ }
60
+ var GENESIS_PREV_HASH = "0000000000000000000000000000000000000000000000000000000000000000";
61
+ function getSubtle() {
62
+ const c = typeof globalThis !== "undefined" ? globalThis.crypto : void 0;
63
+ if (!c || !c.subtle) {
64
+ throw new Error(
65
+ "avar-core: WebCrypto SubtleCrypto is unavailable. Requires Node 20+ or a modern browser."
66
+ );
67
+ }
68
+ return c.subtle;
69
+ }
70
+ async function sha256Hex(input) {
71
+ const bytes = typeof input === "string" ? utf8(input) : input;
72
+ const digest = await getSubtle().digest("SHA-256", bytes);
73
+ return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, "0")).join("");
74
+ }
75
+ async function computeEntryHash(entry, prevHash) {
76
+ const withPrev = { ...entry, prevHash };
77
+ const { entryHash: _e, signature: _sig, devicePubKey: _pk, ...rest } = withPrev;
78
+ void _e;
79
+ void _sig;
80
+ void _pk;
81
+ return sha256Hex(prevHash + "\n" + canonicalize(rest));
82
+ }
83
+ async function computeStepHash(step, prevStepHash) {
84
+ const asRec = step;
85
+ const { stepHash: _s, prevStepHash: _p, ...rest } = asRec;
86
+ void _s;
87
+ void _p;
88
+ const withPrev = { ...rest, prevStepHash };
89
+ return sha256Hex(prevStepHash + "\n" + canonicalize(withPrev));
90
+ }
91
+ function getSubtle2() {
92
+ const c = typeof globalThis !== "undefined" ? globalThis.crypto : void 0;
93
+ if (!c || !c.subtle) {
94
+ throw new Error("avar-core: WebCrypto SubtleCrypto is unavailable.");
95
+ }
96
+ return c.subtle;
97
+ }
98
+ function b64uDecode(s) {
99
+ const b64 = s.replace(/-/g, "+").replace(/_/g, "/") + "===".slice((s.length + 3) % 4);
100
+ const bin = typeof atob === "function" ? atob(b64) : globalThis.Buffer.from(b64, "base64").toString("binary");
101
+ const out = new Uint8Array(bin.length);
102
+ for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
103
+ return out;
104
+ }
105
+ async function verifySignature(signedBody, signatureB64u, publicKeyB64u) {
106
+ try {
107
+ const raw = b64uDecode(publicKeyB64u);
108
+ const key = await getSubtle2().importKey("raw", raw, "Ed25519", false, [
109
+ "verify"
110
+ ]);
111
+ const sig = b64uDecode(signatureB64u);
112
+ const bytes = utf8(canonicalize(signedBody));
113
+ return await getSubtle2().verify("Ed25519", key, sig, bytes);
114
+ } catch {
115
+ return false;
116
+ }
117
+ }
118
+ async function verifyRawSignature(message, signatureB64u, publicKeyB64u) {
119
+ try {
120
+ const raw = b64uDecode(publicKeyB64u);
121
+ const key = await getSubtle2().importKey("raw", raw, "Ed25519", false, [
122
+ "verify"
123
+ ]);
124
+ const sig = b64uDecode(signatureB64u);
125
+ return await getSubtle2().verify("Ed25519", key, sig, message);
126
+ } catch {
127
+ return false;
128
+ }
129
+ }
130
+ async function computeDeviceFingerprint(publicKeyB64u) {
131
+ const hex = await sha256Hex(utf8(publicKeyB64u));
132
+ return hex.slice(0, 12);
133
+ }
134
+ function signedBodyOf(entry) {
135
+ const { signature: _sig, devicePubKey: _pk, ...rest } = entry;
136
+ void _sig;
137
+ void _pk;
138
+ return rest;
139
+ }
140
+ var SPEC_VERSION = "avar/1";
141
+ async function verifyBundle(bundle) {
142
+ const issues = [];
143
+ let formatOk = true;
144
+ const specV = bundle.specVersion.trim();
145
+ if (specV !== SPEC_VERSION) {
146
+ formatOk = false;
147
+ issues.push({
148
+ index: -1,
149
+ kind: "spec-version-mismatch",
150
+ detail: `Expected "${SPEC_VERSION}", got "${specV}".`
151
+ });
152
+ }
153
+ if (bundle.manifest.format !== SPEC_VERSION) {
154
+ formatOk = false;
155
+ issues.push({
156
+ index: -1,
157
+ kind: "manifest-invalid",
158
+ detail: `manifest.format expected "${SPEC_VERSION}", got "${bundle.manifest.format}".`
159
+ });
160
+ }
161
+ const actualSha = await sha256Hex(bundle.entriesNdjsonBytes);
162
+ const entriesSha256Ok = actualSha === bundle.manifest.entriesSha256;
163
+ if (!entriesSha256Ok) {
164
+ issues.push({
165
+ index: -1,
166
+ kind: "entries-sha256-mismatch",
167
+ detail: `Expected ${bundle.manifest.entriesSha256}, got ${actualSha}.`
168
+ });
169
+ }
170
+ const entries = bundle.entries;
171
+ const entryCount = entries.length;
172
+ let signaturesOk = true;
173
+ let fingerprintsOk = true;
174
+ let signedCount = 0;
175
+ let unsignedCount = 0;
176
+ for (let i = 0; i < entries.length; i++) {
177
+ const e = entries[i];
178
+ const hasSig = typeof e.signature === "string" && typeof e.devicePubKey === "string";
179
+ if (!hasSig) {
180
+ unsignedCount++;
181
+ continue;
182
+ }
183
+ signedCount++;
184
+ if (typeof e.deviceFingerprint === "string") {
185
+ const expected = await computeDeviceFingerprint(e.devicePubKey);
186
+ if (expected !== e.deviceFingerprint) {
187
+ fingerprintsOk = false;
188
+ issues.push({
189
+ index: i,
190
+ kind: "fingerprint-mismatch",
191
+ detail: `Expected ${expected}, got ${e.deviceFingerprint}.`
192
+ });
193
+ }
194
+ }
195
+ const ok = await verifySignature(signedBodyOf(e), e.signature, e.devicePubKey);
196
+ if (!ok) {
197
+ signaturesOk = false;
198
+ issues.push({ index: i, kind: "signature-invalid" });
199
+ }
200
+ }
201
+ let chainOk = true;
202
+ let unchainedCount = 0;
203
+ let expectedPrev = GENESIS_PREV_HASH;
204
+ for (let i = 0; i < entries.length; i++) {
205
+ const e = entries[i];
206
+ const isLegacyUnchained = !e.entryHash || !e.prevHash;
207
+ if (isLegacyUnchained) {
208
+ unchainedCount++;
209
+ expectedPrev = GENESIS_PREV_HASH;
210
+ continue;
211
+ }
212
+ if (e.prevHash !== expectedPrev) {
213
+ chainOk = false;
214
+ issues.push({
215
+ index: i,
216
+ kind: "chain-broken",
217
+ detail: `prevHash mismatch at entry ${i}.`
218
+ });
219
+ }
220
+ const recomputed = await computeEntryHash(e, e.prevHash);
221
+ if (recomputed !== e.entryHash) {
222
+ chainOk = false;
223
+ issues.push({
224
+ index: i,
225
+ kind: "chain-broken",
226
+ detail: `entryHash mismatch at entry ${i} (body modified after signing).`
227
+ });
228
+ }
229
+ expectedPrev = e.entryHash;
230
+ }
231
+ const perStepChainOk = await verifyAllStepChains(entries, issues);
232
+ let agentSignaturesOk = true;
233
+ let agentSignaturesChecked = 0;
234
+ let agentSignaturesUnresolved = 0;
235
+ for (let i = 0; i < entries.length; i++) {
236
+ const e = entries[i];
237
+ if (typeof e.agentSignature !== "string") continue;
238
+ const pk = e.agentIdentity?.publicKey;
239
+ if (typeof pk !== "string" || pk.length === 0) {
240
+ agentSignaturesUnresolved++;
241
+ issues.push({
242
+ index: i,
243
+ kind: "agent-key-unresolved",
244
+ detail: "agentSignature present but agentIdentity.publicKey missing."
245
+ });
246
+ continue;
247
+ }
248
+ const tail = tailStepHash(e);
249
+ const tailBytes = new TextEncoder().encode(tail);
250
+ const ok = await verifyRawSignature(tailBytes, e.agentSignature, pk);
251
+ agentSignaturesChecked++;
252
+ if (!ok) {
253
+ agentSignaturesOk = false;
254
+ issues.push({
255
+ index: i,
256
+ kind: "agent-signature-invalid",
257
+ detail: `entry ${i}: agentSignature does not verify against agentIdentity.publicKey.`
258
+ });
259
+ }
260
+ }
261
+ const chainHead = computeChainHead(entries);
262
+ const anyHardFail = !formatOk || !entriesSha256Ok || !chainOk || !perStepChainOk || !signaturesOk || !fingerprintsOk || !agentSignaturesOk;
263
+ const verdict = anyHardFail ? "invalid" : unsignedCount > 0 || unchainedCount > 0 || agentSignaturesUnresolved > 0 ? "valid-with-warnings" : "valid";
264
+ return {
265
+ formatOk,
266
+ entriesSha256Ok,
267
+ chainOk,
268
+ perStepChainOk,
269
+ signaturesOk,
270
+ fingerprintsOk,
271
+ agentSignaturesOk,
272
+ agentSignaturesChecked,
273
+ agentSignaturesUnresolved,
274
+ entryCount,
275
+ signedCount,
276
+ unsignedCount,
277
+ unchainedCount,
278
+ chainHead,
279
+ issues,
280
+ verdict
281
+ };
282
+ }
283
+ function tailStepHash(e) {
284
+ const steps = Array.isArray(e.steps) ? e.steps : [];
285
+ for (let i = steps.length - 1; i >= 0; i--) {
286
+ const h = steps[i]?.stepHash;
287
+ if (typeof h === "string" && h.length > 0) return h;
288
+ }
289
+ return GENESIS_PREV_HASH;
290
+ }
291
+ async function verifyAllStepChains(entries, issues) {
292
+ let ok = true;
293
+ for (let i = 0; i < entries.length; i++) {
294
+ const e = entries[i];
295
+ if (!Array.isArray(e.steps) || e.steps.length === 0) continue;
296
+ const anyChained = e.steps.some(hasChainFields);
297
+ const allChained = e.steps.every(hasChainFields);
298
+ if (anyChained && !allChained) {
299
+ ok = false;
300
+ issues.push({ index: i, kind: "partial-step-chain" });
301
+ continue;
302
+ }
303
+ if (!anyChained) continue;
304
+ let prev = "step-genesis:0000000000000000000000000000000000000000000000000000000000000000";
305
+ for (let j = 0; j < e.steps.length; j++) {
306
+ const s = e.steps[j];
307
+ if (s.prevStepHash !== prev) {
308
+ ok = false;
309
+ issues.push({
310
+ index: i,
311
+ kind: "step-chain-broken",
312
+ detail: `entry ${i} step ${j}: prevStepHash mismatch.`
313
+ });
314
+ }
315
+ const recomputed = await computeStepHash(s, s.prevStepHash);
316
+ if (recomputed !== s.stepHash) {
317
+ ok = false;
318
+ issues.push({
319
+ index: i,
320
+ kind: "step-chain-broken",
321
+ detail: `entry ${i} step ${j}: stepHash mismatch (step body modified).`
322
+ });
323
+ }
324
+ prev = s.stepHash;
325
+ }
326
+ }
327
+ return ok;
328
+ }
329
+ function hasChainFields(s) {
330
+ return typeof s.prevStepHash === "string" && typeof s.stepHash === "string";
331
+ }
332
+ function computeChainHead(entries) {
333
+ for (let i = entries.length - 1; i >= 0; i--) {
334
+ const e = entries[i];
335
+ if (e.entryHash) return { entryHash: e.entryHash, index: i };
336
+ }
337
+ return { entryHash: "", index: -1 };
338
+ }
339
+
340
+ // src/commands/verify.ts
341
+ async function runVerify(opts) {
342
+ let bundle;
343
+ try {
344
+ const buf = await readFile(opts.file);
345
+ bundle = await parseBundle(new Uint8Array(buf));
346
+ } catch (err) {
347
+ const msg = err instanceof Error ? err.message : String(err);
348
+ if (opts.json) {
349
+ process.stdout.write(JSON.stringify({ ok: false, error: "malformed", detail: msg }) + "\n");
350
+ } else if (!opts.quiet) {
351
+ process.stderr.write(`\u2716 malformed bundle: ${msg}
352
+ `);
353
+ }
354
+ return 3;
355
+ }
356
+ const report = await verifyBundle(bundle);
357
+ if (opts.json) {
358
+ process.stdout.write(JSON.stringify(report) + "\n");
359
+ } else if (!opts.quiet) {
360
+ printHumanReport(opts.file, report);
361
+ }
362
+ if (report.verdict === "invalid") return 1;
363
+ if (opts.strict && report.verdict === "valid-with-warnings") return 2;
364
+ return 0;
365
+ }
366
+ async function parseBundle(bytes) {
367
+ const files = unzipSync2(bytes);
368
+ const required = ["SPEC-VERSION", "manifest.json", "entries.ndjson", "pubkeys.json"];
369
+ const missing = required.filter((n) => !files[n]);
370
+ if (missing.length > 0) {
371
+ throw new Error(`missing required file(s): ${missing.join(", ")}`);
372
+ }
373
+ const specVersion = strFromU82(files["SPEC-VERSION"]).trim();
374
+ const manifest = JSON.parse(strFromU82(files["manifest.json"]));
375
+ const pubkeys = JSON.parse(strFromU82(files["pubkeys.json"]));
376
+ const entriesBytes = files["entries.ndjson"];
377
+ const entries = strFromU82(entriesBytes).split("\n").filter((l) => l.length > 0).map((l) => JSON.parse(l));
378
+ return { specVersion, manifest, entriesNdjsonBytes: entriesBytes, entries, pubkeys };
379
+ }
380
+ function printHumanReport(file, r) {
381
+ const verdictSym = r.verdict === "valid" ? "\u2714" : r.verdict === "valid-with-warnings" ? "!" : "\u2716";
382
+ const line = (ok, label) => ` ${ok ? "\u2714" : "\u2716"} ${label}`;
383
+ process.stdout.write(
384
+ `${verdictSym} ${r.verdict.toUpperCase()} ${file}
385
+ entries: ${r.entryCount} signed: ${r.signedCount} unsigned: ${r.unsignedCount} unchained: ${r.unchainedCount}
386
+ ` + line(r.formatOk, "format (SPEC-VERSION + manifest.format = avar/1)") + "\n" + line(r.entriesSha256Ok, "envelope integrity (sha256 of entries.ndjson)") + "\n" + line(r.signaturesOk, "Ed25519 signatures") + "\n" + line(r.fingerprintsOk, "device fingerprints match public keys") + "\n" + line(r.chainOk, "entry-level hash chain") + "\n" + line(r.perStepChainOk, "per-step hash chain") + "\n"
387
+ );
388
+ if (r.chainHead.entryHash) {
389
+ process.stdout.write(` chain head (#${r.chainHead.index}): ${r.chainHead.entryHash}
390
+ `);
391
+ }
392
+ if (r.issues.length > 0) {
393
+ process.stdout.write(` issues:
394
+ `);
395
+ for (const iss of r.issues.slice(0, 20)) {
396
+ const idx = iss.index >= 0 ? `entry ${iss.index}: ` : "";
397
+ const detail = iss.detail ? ` \u2014 ${iss.detail}` : "";
398
+ process.stdout.write(` - ${idx}${iss.kind}${detail}
399
+ `);
400
+ }
401
+ if (r.issues.length > 20) {
402
+ process.stdout.write(` (\u2026and ${r.issues.length - 20} more)
403
+ `);
404
+ }
405
+ }
406
+ }
407
+ export {
408
+ runVerify
409
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aarmos/bridge",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Aarmos CLI bridge — local WebSocket host that gives the Aarmos PWA scoped, deny-by-default access to files, shell, git, and read-only Postgres on the developer's machine. The PWA stays the brain; this is the arms.",
5
5
  "keywords": [
6
6
  "aarmos",
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "type": "module",
19
19
  "scripts": {
20
- "build": "tsc -p tsconfig.json",
20
+ "build": "tsup",
21
21
  "dev": "tsx src/index.ts dev",
22
22
  "start": "node dist/index.js",
23
23
  "test": "tsx test/e2e.ts && tsx test/sample-smoke.ts && tsx test/daemon-e2e.ts && node test/crash-handling.mjs && tsx --test test/llm-test.test.mjs",
@@ -38,7 +38,6 @@
38
38
  "author": "Aarmatix LLC",
39
39
  "license": "Apache-2.0",
40
40
  "dependencies": {
41
- "@aarmos/avar-core": "^1.10.0",
42
41
  "@types/pg": "^8.20.0",
43
42
  "chokidar": "^3.6.0",
44
43
  "commander": "^12.1.0",
@@ -50,8 +49,10 @@
50
49
  "zod": "^3.23.8"
51
50
  },
52
51
  "devDependencies": {
52
+ "@aarmos/runtime-core": "workspace:*",
53
53
  "@types/node": "^22.5.0",
54
54
  "@types/ws": "^8.5.12",
55
+ "tsup": "^8.5.1",
55
56
  "tsx": "^4.19.0",
56
57
  "typescript": "^5.6.2"
57
58
  },
@@ -1 +0,0 @@
1
- {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
@@ -1,62 +0,0 @@
1
- // `aarmos attest` and `aarmos attest verify` — audit-ready export.
2
- //
3
- // The attestation bundle is the artifact enterprises actually pay for:
4
- // a single self-contained JSON file with signed receipts, the policy
5
- // hash, playbook hash, installed pack hashes, and a merkle-style root
6
- // hash — verifiable air-gapped by anyone.
7
- import fs from "node:fs/promises";
8
- import path from "node:path";
9
- import { buildAttestation, parseSince, readAttestation, signAttestation, verifyAttestation, writeAttestation, } from "../lib/attest.js";
10
- // eslint-disable-next-line no-console
11
- const log = (s) => console.log(s);
12
- export async function runAttest(opts) {
13
- const workspace = path.resolve(opts.workspace ?? process.cwd());
14
- const since = opts.since ? parseSince(opts.since) : new Date(0);
15
- const bundle = await buildAttestation({
16
- workspace,
17
- receiptsFile: path.resolve(opts.receipts),
18
- since,
19
- until: new Date(),
20
- playbookFile: opts.playbook,
21
- policyFile: opts.policy ?? path.join(workspace, "aarmos.json"),
22
- packsDir: path.join(workspace, ".aarmos/packs"),
23
- });
24
- const finalBundle = opts.signKey
25
- ? await signAttestation(bundle, await fs.readFile(path.resolve(opts.signKey), "utf8"))
26
- : bundle;
27
- await writeAttestation(opts.out, finalBundle);
28
- log("");
29
- log(" aarmos attest");
30
- log(` window : ${finalBundle.since} → ${finalBundle.until}`);
31
- log(` receipts : ${finalBundle.receipts.length}`);
32
- log(` playbook : ${finalBundle.playbook ? finalBundle.playbook.name + " (" + finalBundle.playbook.hash.slice(0, 16) + "…)" : "(none)"}`);
33
- log(` policy : ${finalBundle.policyHash ? finalBundle.policyHash.slice(0, 16) + "…" : "(none)"}`);
34
- log(` packs : ${finalBundle.packs.length}`);
35
- log(` rootHash : ${finalBundle.rootHash}`);
36
- log(` signature : ${finalBundle.signature ? finalBundle.signature.pubKey : "(unsigned)"}`);
37
- log(` written to : ${path.resolve(opts.out)}`);
38
- log("");
39
- }
40
- export async function runAttestVerify(opts) {
41
- const bundle = await readAttestation(opts.file);
42
- const res = verifyAttestation(bundle);
43
- log("");
44
- log(` aarmos attest verify — ${opts.file}`);
45
- log(` receipts : ${bundle.receipts.length}`);
46
- log(` rootHash : ${bundle.rootHash}`);
47
- log(` result : ${res.ok ? "OK" : "INVALID"}${res.reason ? " " + res.reason : ""}`);
48
- if (bundle.signature) {
49
- log(` signer : ${bundle.signature.pubKey}`);
50
- if (opts.trustedPubkey && bundle.signature.pubKey !== opts.trustedPubkey) {
51
- log(" trust : REJECTED — signer not in trusted set");
52
- process.exitCode = 1;
53
- }
54
- }
55
- else {
56
- log(" signer : (unsigned)");
57
- }
58
- if (!res.ok)
59
- process.exitCode = 1;
60
- log("");
61
- }
62
- //# sourceMappingURL=attest.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"attest.js","sourceRoot":"","sources":["../../src/commands/attest.ts"],"names":[],"mappings":"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"}