Skip to content

Commit ee4c098

Browse files
committed
fix: audit — remove console.log from production paths, fix test file, improve error handling, update .env.example, fix doc code fences
1 parent 4ff3a8e commit ee4c098

7 files changed

Lines changed: 228 additions & 449 deletions

File tree

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1+
# Required: base URL of the CommandLayer runtime service.
2+
# Used by api/verify-receipt.js (proxy) and api/health.js.
3+
# Example: https://runtime.commandlayer.org
14
RUNTIME_BASE_URL=https://runtime.commandlayer.org

api/verify-receipt.js

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,6 @@ module.exports = async function handler(req, res) {
147147
const schema = qflag(req.query?.schema, '0');
148148
const verifyUrl = `${RUNTIME_BASE}/verify?ens=${ens}&refresh=${refresh}&schema=${schema}`;
149149

150-
console.log('[verify-receipt] runtime verify target', JSON.stringify({ runtime_url: verifyUrl }));
151-
console.log('[verify-receipt] outgoing verify body', JSON.stringify({ body: bareReceipt }));
152-
console.log('[verify-receipt] normalized receipt', JSON.stringify({ normalized_receipt: bareReceipt }));
153-
154150
try {
155151
const upstream = await fetchTextWithTimeout(verifyUrl, {
156152
method: 'POST',
@@ -165,8 +161,6 @@ module.exports = async function handler(req, res) {
165161
: { ok: false, error: 'Non-JSON response from runtime /verify', raw: String(upstream.text || '').slice(0, 2000) };
166162
const normalizedChecks = normalizeChecks(data, schema === '1');
167163

168-
console.log('[verify-receipt] raw verify response', JSON.stringify({ runtime_url: verifyUrl, body: data }));
169-
170164
return res.status(upstream.status).end(
171165
JSON.stringify(
172166
{
@@ -180,13 +174,6 @@ module.exports = async function handler(req, res) {
180174
runtime_content_type: upstream.contentType,
181175
normalized_receipt_used: bareReceipt,
182176
},
183-
logs: {
184-
runtime_url: verifyUrl,
185-
outgoing_request_body: bareReceipt,
186-
raw_runtime_response_body: data,
187-
normalized_receipt_chosen: bareReceipt,
188-
canonical_validation_failure_reason: data?.error || null,
189-
},
190177
},
191178
null,
192179
2
@@ -205,13 +192,6 @@ module.exports = async function handler(req, res) {
205192
verify: { ens, refresh, schema },
206193
normalized_receipt_used: bareReceipt,
207194
},
208-
logs: {
209-
runtime_url: verifyUrl,
210-
outgoing_request_body: bareReceipt,
211-
raw_runtime_response_body: null,
212-
normalized_receipt_chosen: bareReceipt,
213-
canonical_validation_failure_reason: e?.message || String(e),
214-
},
215195
},
216196
null,
217197
2

docs/wrap-your-agent.md

Lines changed: 85 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,19 @@ Turn any agent action into a signed, verifiable receipt.
44

55
This is the core primitive of CommandLayer:
66

7-
**Agents dont make claims — they produce proof.**
7+
**Agents don't make claims — they produce proof.**
88

99
---
1010

1111
## Install
1212

13-
```
14-
bash
13+
```bash
1514
npm install @commandlayer/agent-sdk
1615
```
1716

18-
1917
## What this does
20-
When you wrap an agent action:
2118

19+
When you wrap an agent action:
2220

2321
- Your action executes normally
2422
- CommandLayer captures the output
@@ -29,190 +27,206 @@ When you wrap an agent action:
2927

3028
## Quick start
3129

32-
```
30+
```ts
3331
import { CommandLayer } from "@commandlayer/agent-sdk";
3432

3533
const cl = new CommandLayer({
36-
agent: "runtime.commandlayer.eth",
37-
privateKey: process.env.CL_PRIVATE_KEY_PEM,
38-
keyId: "vC4WbcNoq2znSCiQ",
39-
verifierUrl: "https://www.commandlayer.org/api/verify"});
34+
agent: "runtime.commandlayer.eth",
35+
privateKey: process.env.CL_PRIVATE_KEY_PEM,
36+
keyId: "vC4WbcNoq2znSCiQ",
37+
verifierUrl: "https://www.commandlayer.org/api/verify"
38+
});
39+
40+
const result = await cl.wrap("summarize", async () => {
41+
return { summary: "hello world" };
42+
});
4043

41-
const result = await cl.wrap("summarize", async () => { return { summary: "hello world" };});
42-
console.log(result.output);console.log(result.receipt);
44+
console.log(result.output);
45+
console.log(result.receipt);
4346

4447
const verified = await cl.verify(result.receipt);
4548
console.log(verified.status);
4649
```
4750

4851
## What `wrap()` returns
49-
`wrap()` returns both:
5052

53+
`wrap()` returns both:
5154

5255
- `output` — the value returned by your agent function
5356
- `receipt` — the signed CommandLayer receipt for that action
5457

55-
5658
### Example
57-
```
59+
60+
```ts
5861
const result = await cl.wrap("summarize", async () => {
59-
return { summary: "AI agents need verification" };});
62+
return { summary: "AI agents need verification" };
63+
});
6064

6165
console.log(result.output);
6266
console.log(result.receipt);
6367
```
6468

6569
### Example receipt
70+
71+
```json
72+
{
73+
"signer": "runtime.commandlayer.eth",
74+
"verb": "summarize",
75+
"ts": "2026-05-02T02:53:33.056Z",
76+
"input": {},
77+
"output": {
78+
"summary": "hello world"
79+
},
80+
"execution": {
81+
"status": "ok",
82+
"duration_ms": 1,
83+
"started_at": "2026-05-02T02:53:33.056Z",
84+
"completed_at": "2026-05-02T02:53:33.057Z"
85+
},
86+
"metadata": {
87+
"proof": {
88+
"canonicalization": "json.sorted_keys.v1",
89+
"hash_sha256": "14e559e9454eaba437934220623b95947fdbaf38d45a1d358c327622c8352617"
90+
}
91+
},
92+
"signature": {
93+
"alg": "ed25519",
94+
"kid": "vC4WbcNoq2znSCiQ",
95+
"sig": "..."
96+
}
97+
}
6698
```
67-
{ "signer": "runtime.commandlayer.eth",
68-
"verb": "summarize",
69-
"ts": "2026-05-02T02:53:33.056Z",
70-
"input": {},
71-
"output": {
72-
"summary": "hello world"
73-
},
74-
"execution": {
75-
"status": "ok",
76-
"duration_ms": 1,
77-
"started_at": "2026-05-02T02:53:33.056Z",
78-
"completed_at": "2026-05-02T02:53:33.057Z"
79-
},
80-
"metadata": {
81-
"proof": {
82-
"canonicalization": "json.sorted_keys.v1",
83-
"hash_sha256": "14e559e9454eaba437934220623b95947fdbaf38d45a1d358c327622c8352617"
84-
}
85-
},
86-
"signature": {
87-
"alg": "ed25519",
88-
"kid": "vC4WbcNoq2znSCiQ",
89-
"sig": "..." }}
90-
```
91-
92-
### What verification checks
99+
100+
## What verification checks
93101

94102
The verifier:
103+
95104
- Rebuilds the canonical receipt payload
96105
- Recomputes the SHA-256 hash
97106
- Compares it to `metadata.proof.hash_sha256`
98107
- Resolves signer key metadata from ENS when available
99108
- Validates the Ed25519 signature
100109
- Returns `VERIFIED` or `INVALID`
101110

111+
If the input or output changes after signing, the recomputed hash no longer matches and verification returns `INVALID`.
102112

103-
If the input or output changes after signing, the recomputed hash no longer matches and verification returns `INVALID.`
104-
105-
### ENS signer records
113+
## ENS signer records
106114

107115
The signer should publish key metadata through ENS TXT records.
108116

109-
For `runtime.commandlayer.eth,` the important records are:
117+
For `runtime.commandlayer.eth`, the important records are:
118+
110119
```
111120
cl.sig.kid=vC4WbcNoq2znSCiQ
112121
cl.sig.pub=ed25519:<base64-public-key>
113122
cl.sig.canonical=json.sorted_keys.v1
114123
cl.receipt.signer=runtime.commandlayer.eth
115124
```
125+
116126
The private key stays local. Never commit it, paste it into frontend code, or publish it.
117127

118-
### Verify through the public API
119-
```
128+
## Verify through the public API
129+
130+
```ts
120131
const verified = await cl.verify(result.receipt);
121132
if (verified.status === "VERIFIED") {
122-
console.log("VERIFIED");
133+
console.log("VERIFIED");
123134
} else {
124-
console.log("INVALID");
135+
console.log("INVALID");
125136
}
126137
```
127138

128-
#### Default verifier:
139+
Default verifier:
140+
129141
```
130142
POST https://www.commandlayer.org/api/verify
131143
```
132144

133-
### VerifyAgent.eth callable endpoint
145+
## VerifyAgent.eth callable endpoint
134146

135147
VerifyAgent.eth can also be called directly:
148+
136149
```
137150
POST https://www.commandlayer.org/api/agents/verifyagent
138151
```
139152

140-
#### Request
141-
```
153+
### Request
154+
155+
```json
142156
{
143-
"receipt": {
144-
"...": "CommandLayer receipt"
157+
"receipt": {
158+
"...": "CommandLayer receipt"
145159
}
146160
}
161+
```
147162

148163
VerifyAgent.eth does not execute the original task. It verifies whether a submitted receipt is valid or tampered.
149164

150-
#### Verify in the browser
165+
## Verify in the browser
151166

152167
Paste any receipt into:
168+
153169
```
154170
https://www.commandlayer.org/verify.html
155-
156171
```
172+
157173
Expected behavior:
158174

159175
- valid receipt → VERIFIED
160176
- tampered receipt → INVALID
161177

162-
#### Full proof demo
163-
178+
## Full proof demo
164179

165180
The SDK includes a full proof-loop demo:
166-
```
181+
182+
```bash
167183
npm run example:demo
168184
```
185+
169186
It runs:
187+
170188
```
171189
wrap action → emit receipt → verify → tamper → verify invalid
172190
```
191+
173192
Expected output:
174193

175194
```
176195
Original receipt verification: VERIFIED
177196
Tampered receipt verification: INVALID
178197
```
179198

180-
181-
### Why this matters
199+
## Why this matters
182200

183201
Without CommandLayer:
202+
184203
- agents only claim what happened
185204
- platforms are trusted by default
186205
- outputs can be edited without proof
187206
- verification is not portable
188207

189-
190208
With CommandLayer:
191209

192-
193210
- every action can produce a signed receipt
194211
- signer identity can be resolved through ENS
195212
- receipts can be verified independently
196213
- tampering breaks the proof
197214

198-
### Design principles
199-
215+
## Design principles
200216

201217
- deterministic receipts
202218
- independent verification
203219
- no platform trust required
204220
- composable across agents and apps
205221

206-
### Next steps
222+
## Next steps
207223

208224
- Install the SDK
209225
- Wrap one important agent action
210226
- Emit a signed receipt
211227
- Verify it through VerifyAgent.eth
212228
- Expose receipts anywhere users need proof
213229

214-
215-
216-
### One-line summary
230+
## One-line summary
217231

218232
**Wrap your agent → produce a receipt → prove what actually happened.**

0 commit comments

Comments
 (0)