Spaces:
Running
Running
File size: 2,802 Bytes
518343a | 1 2 3 4 5 6 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 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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | #!/usr/bin/env node
import * as path from "node:path";
import {
appendReceiptJsonl,
createToolEnvelope,
emitReceipt,
readReceiptJsonl,
verifyChain,
type ReceiptProtocol,
} from "./index.ts";
interface CliArgs {
out: string;
actor: string;
tool: string;
protocol: ReceiptProtocol;
payloadJson: string;
quorum: string;
nodes: string[];
lambdaAxes: string[];
}
function parseArgs(argv: readonly string[]): CliArgs {
const args = new Map<string, string>();
for (let i = 0; i < argv.length; i += 1) {
const token = argv[i];
if (!token.startsWith("--")) continue;
const key = token.slice(2);
const value = argv[i + 1];
if (!value || value.startsWith("--")) {
throw new Error(`Missing value for --${key}`);
}
args.set(key, value);
i += 1;
}
const out = args.get("out");
const actor = args.get("actor");
const tool = args.get("tool");
const payloadJson = args.get("payload-json");
if (!out || !actor || !tool || !payloadJson) {
throw new Error("Required: --out <file> --actor <id> --tool <name> --payload-json <json>");
}
return {
out,
actor,
tool,
payloadJson,
protocol: (args.get("protocol") ?? "mcp") as ReceiptProtocol,
quorum: args.get("quorum") ?? "1-of-1",
nodes: (args.get("nodes") ?? "local-operator").split(",").map((node) => node.trim()).filter(Boolean),
lambdaAxes: (args.get("lambda-axes") ?? "Λ7").split(",").map((axis) => axis.trim()).filter(Boolean),
};
}
function main(): void {
const args = parseArgs(process.argv.slice(2));
const payload = JSON.parse(args.payloadJson) as unknown;
const out = path.resolve(args.out);
const chain = readReceiptJsonl(out);
const previousReceipt = chain.length > 0 ? chain[chain.length - 1] : null;
const envelope = createToolEnvelope({
protocol: args.protocol,
actor_id: args.actor,
tool_name: args.tool,
lambda_axes: args.lambdaAxes,
payload,
metadata: {
source: "a11oy-receipt-substrate-cli",
},
});
const receipt = emitReceipt(envelope, {
previousReceipt,
policy: {
algorithm: "SHA3-256",
chaining: "hash_chain",
quorum: args.quorum,
nodes: args.nodes,
},
});
const nextChain = [...chain, receipt];
const verification = verifyChain(nextChain, {
quorum: args.quorum,
nodes: args.nodes,
});
if (!verification.valid) {
throw new Error(`Refusing to append invalid receipt: ${verification.errors.join("; ")}`);
}
appendReceiptJsonl(out, receipt);
console.log(JSON.stringify({
ok: true,
out,
receipt_id: receipt.receipt_id,
merkle_root: receipt.merkle_root,
sequence: receipt.sequence,
}));
}
try {
main();
} catch (error) {
console.error((error as Error).message);
process.exit(1);
}
|