Skip to content

Commit 381da50

Browse files
committed
Harden runtime signing config and verification paths
1 parent 6d88040 commit 381da50

File tree

3 files changed

+178
-148
lines changed

3 files changed

+178
-148
lines changed

.env.example

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Required runtime signing config
2+
CL_RECEIPT_SIGNER=runtime.commandlayer.eth
3+
CL_KEY_ID=v1
4+
CL_CANONICAL_ID=json.sorted_keys.v1
5+
6+
# Recommended for node --env-file: single-line PEM with literal \n escapes
7+
CL_PRIVATE_KEY_PEM=-----BEGIN PRIVATE KEY-----\nREPLACE_WITH_BASE64_BODY\n-----END PRIVATE KEY-----
8+
9+
# Base64 of raw 32-byte Ed25519 public key (same bytes as ENS TXT after ed25519:)
10+
CL_PUBLIC_KEY_B64=REPLACE_WITH_32_BYTE_RAW_PUBKEY_BASE64
11+
12+
# Optional (required only for /verify?ens=1)
13+
ETH_RPC_URL=
14+
15+
HOST=0.0.0.0
16+
PORT=8080
17+
ENABLED_VERBS=fetch,describe,format,clean,parse,summarize,convert,explain,analyze,classify

scripts/smoke.mjs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import process from "node:process";
2+
3+
const base = process.env.SMOKE_BASE_URL || `http://127.0.0.1:${process.env.PORT || 8080}`;
4+
const input = {
5+
x402: { entry: "x402://describeagent.eth/describe/v1.0.0", verb: "describe", version: "1.0.0" },
6+
input: { subject: "CommandLayer", detail_level: "short" },
7+
};
8+
9+
function fail(step, details) {
10+
console.error(`[smoke] FAIL: ${step}`);
11+
if (details) console.error(typeof details === "string" ? details : JSON.stringify(details, null, 2));
12+
process.exit(1);
13+
}
14+
15+
try {
16+
const healthResp = await fetch(`${base}/health`);
17+
const health = await healthResp.json();
18+
if (!healthResp.ok) fail("/health http", health);
19+
if (!health.signer_ok || !health.verifier_ok) fail("/health signer/verifier", health);
20+
21+
const describeResp = await fetch(`${base}/describe/v1.0.0`, {
22+
method: "POST",
23+
headers: { "content-type": "application/json" },
24+
body: JSON.stringify(input),
25+
});
26+
const receipt = await describeResp.json();
27+
if (!describeResp.ok) fail("/describe/v1.0.0 http", receipt);
28+
if (!receipt?.metadata?.proof?.hash_sha256 || !receipt?.metadata?.proof?.signature_b64) {
29+
fail("describe proof fields", receipt?.metadata?.proof || receipt);
30+
}
31+
32+
const verifyResp = await fetch(`${base}/verify?schema=0&ens=0`, {
33+
method: "POST",
34+
headers: { "content-type": "application/json" },
35+
body: JSON.stringify(receipt),
36+
});
37+
const verify = await verifyResp.json();
38+
if (!verifyResp.ok) fail("/verify http", verify);
39+
if (!verify.ok || !verify?.checks?.signature_valid || !verify?.checks?.hash_matches) {
40+
fail("/verify checks", verify);
41+
}
42+
43+
console.log("[smoke] PASS");
44+
console.log(JSON.stringify({ health, verify }, null, 2));
45+
} catch (err) {
46+
fail("exception", err?.stack || String(err));
47+
}

0 commit comments

Comments
 (0)