@trucore/atf 1.0.2 → 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.
Files changed (3) hide show
  1. package/README.md +535 -260
  2. package/dist/index.js +3686 -793
  3. package/package.json +50 -47
package/README.md CHANGED
@@ -1,260 +1,535 @@
1
- # @trucore/atf
2
-
3
- > Agent Transaction Firewall CLI — simulate, verify, and audit on-chain transactions trustlessly.
4
-
5
- ## One-Liner
6
-
7
- ```bash
8
- npx @trucore/atf@1.0.0 simulate --preset swap_small --verify --pretty
9
- ```
10
-
11
- That's it. No install, no config, no API key required.
12
-
13
- ## What It Does
14
-
15
- 1. Sends a deterministic preset transaction to the ATF public API
16
- 2. Returns **allowed** or **denied** with a reason and receipt hash
17
- 3. Verifies **content_hash** integrity client-side — don't trust TruCore, verify
18
-
19
- ## Install (optional)
20
-
21
- ```bash
22
- npm install -g @trucore/atf@1.0.0
23
- ```
24
-
25
- Or use directly with `npx` (always pin the version):
26
-
27
- ```bash
28
- npx @trucore/atf@1.0.0 simulate --preset swap_small
29
- ```
30
-
31
- ## Commands
32
-
33
- ### `health`
34
-
35
- Check API health and round-trip latency.
36
-
37
- ```bash
38
- npx @trucore/atf@1.0.0 health
39
- npx @trucore/atf@1.0.0 health --pretty
40
- npx @trucore/atf@1.0.0 health --base-url http://localhost:3000
41
- ```
42
-
43
- **Output shape:**
44
-
45
- ```json
46
- { "ok": true, "base_url": "https://api.trucore.xyz", "latency_ms": 42, "response": { "status": "ok" } }
47
- ```
48
-
49
- ### `simulate`
50
-
51
- Run a transaction simulation against the ATF API.
52
-
53
- ```bash
54
- npx @trucore/atf@1.0.0 simulate --preset swap_small --verify
55
- npx @trucore/atf@1.0.0 simulate --preset swap_too_large --pretty
56
- npx @trucore/atf@1.0.0 simulate --json '{"chain_id":1,"value_eth":"0.5"}' --base-url http://localhost:3000
57
- ```
58
-
59
- **Output shape:**
60
-
61
- ```json
62
- { "ok": true, "base_url": "https://api.trucore.xyz", "preset": "swap_small", "verified": true, "response": { "decision": "allowed", "reasons": [], "receipt_hash": "a1b2...64hex", "content_hash": "c3d4...64hex" } }
63
- ```
64
-
65
- ### `approve`
66
-
67
- Approve a pending intent (requires authentication).
68
-
69
- ```bash
70
- npx @trucore/atf@1.0.0 approve --intent abc123 --token mytoken
71
- npx @trucore/atf@1.0.0 approve --intent abc123 --token mytoken --pretty
72
- ```
73
-
74
- **Output shape:**
75
-
76
- ```json
77
- { "ok": true, "base_url": "https://api.trucore.xyz", "intent": "abc123", "response": { "intent_id": "abc123", "status": "approved" } }
78
- ```
79
-
80
- ### `version`
81
-
82
- Show rich version information (CLI version, Node version, build info).
83
-
84
- ```bash
85
- npx @trucore/atf@1.0.0 version
86
- npx @trucore/atf@1.0.0 version --pretty
87
- ```
88
-
89
- **Output shape:**
90
-
91
- ```json
92
- { "ok": true, "cli_version": "1.0.1", "node_version": "v22.0.0", "platform": "linux", "arch": "x64", "default_base_url": "https://api.trucore.xyz", "build_commit": "abc1234", "build_date": "2025-01-01T00:00:00Z" }
93
- ```
94
-
95
- ## Global Options
96
-
97
- | Flag | Description | Default |
98
- |------|-------------|---------|
99
- | `--base-url <url>` | API base URL | `https://api.trucore.xyz` |
100
- | `--timeout-ms <ms>` | Request timeout in milliseconds | `20000` |
101
- | `--format <fmt>` | Output: `json` or `pretty` | `json` |
102
- | `--pretty` | Shorthand for `--format pretty` | `false` |
103
- | `--no-color` | Disable ANSI colors | `false` |
104
- | `--api-key <key>` | API key (also: `ATF_API_KEY` env var) | — |
105
-
106
- ## Simulate Options
107
-
108
- | Flag | Description | Default |
109
- |------|-------------|---------|
110
- | `--preset <name>` | Built-in preset: `swap_small`, `swap_too_large`, `ttl_too_high` | — |
111
- | `--json '<json>'` | Raw JSON transaction body | — |
112
- | `--verify` | Verify content_hash integrity | `false` |
113
- | `--quiet` | Suppress non-essential output | `false` |
114
-
115
- ## Approve Options
116
-
117
- | Flag | Description | Default |
118
- |------|-------------|---------|
119
- | `--intent <id>` | Intent ID to approve (required) | — |
120
- | `--intent-id <id>` | Alias for `--intent` (backward compat) | — |
121
- | `--token <bearer>` | Bearer token for auth (also: `ATF_API_KEY` env var) | |
122
-
123
- ### Presets
124
-
125
- | Preset | Description | Expected |
126
- |--------|-------------|----------|
127
- | `swap_small` | Small 0.01 ETH swap | ALLOWED |
128
- | `swap_too_large` | 999,999 ETH swap | DENIED (value limit) |
129
- | `ttl_too_high` | Swap with 24h TTL | DENIED (TTL policy) |
130
-
131
- ## Output
132
-
133
- All commands return a JSON envelope with `"ok": true/false`.
134
-
135
- ### Success (JSON, default)
136
-
137
- ```json
138
- {
139
- "ok": true,
140
- "base_url": "https://api.trucore.xyz",
141
- "preset": "swap_small",
142
- "verified": true,
143
- "response": {
144
- "decision": "allowed",
145
- "reasons": [],
146
- "receipt_hash": "a1b2c3...64hex",
147
- "content_hash": "d4e5f6...64hex"
148
- }
149
- }
150
- ```
151
-
152
- When `--verify` is not used, the `verified` field is `null`.
153
- When a preset is not used, the `preset` field is `null`.
154
- ```
155
-
156
- ### Success (Pretty, `--pretty`)
157
-
158
- ```
159
- ALLOWED
160
- Reason: All policies passed
161
- Receipt: a1b2c3...64hex
162
-
163
- ✓ Content hash verified
164
- ```
165
-
166
- ### Errors
167
-
168
- All errors return a structured JSON envelope:
169
-
170
- ```json
171
- {
172
- "ok": false,
173
- "error": {
174
- "code": "NETWORK_ERROR",
175
- "message": "Network failure — fetch failed",
176
- "details": {
177
- "hint": "Check your network connection and base URL."
178
- }
179
- }
180
- }
181
- ```
182
-
183
- Error codes: `USER_ERROR`, `DENIED`, `NETWORK_ERROR`, `SERVER_ERROR`, `VALIDATION_ERROR`, `AUTH_ERROR`, `VERIFY_FAILED`.
184
-
185
- ## Exit Codes
186
-
187
- | Code | Meaning |
188
- |------|---------|
189
- | 0 | Success (allowed, healthy, approved, etc.) |
190
- | 1 | User error or denied (bad input, auth failure, transaction denied, verify failed) |
191
- | 2 | Network / server error (unreachable, 5xx, timeout, rate limited) |
192
-
193
- ## Trustless Verification
194
-
195
- **Don't trust TruCore verify.**
196
-
197
- Every simulation produces a `content_hash` (SHA-256). You can:
198
-
199
- 1. **Use `--verify` flag:** Automatically recomputes and checks content_hash integrity client-side.
200
- 2. **Recompute locally:** The policy engine is deterministic. Same input → same hash.
201
- 3. **Check receipt signatures** (when available): `GET /api/receipt-signing-key`
202
-
203
- The `--verify` flag checks content_hash integrity automatically. On mismatch it exits 1 with `VERIFY_FAILED`.
204
-
205
- ## Token Redaction
206
-
207
- Bearer tokens are **never** emitted in CLI output. All stdout/stderr is scrubbed
208
- for token values and `Bearer <token>` patterns before printing.
209
-
210
- ## Environment Variables
211
-
212
- | Variable | Description |
213
- |----------|-------------|
214
- | `ATF_API_KEY` | API key (sent as `x-api-key` header or Bearer token) |
215
- | `ATF_BASE_URL` | Override default base URL |
216
- | `ATF_TIMEOUT_MS` | Override default timeout (milliseconds, default: `20000`) |
217
- | `NO_COLOR` | Disable ANSI colors when set |
218
-
219
- ## Requirements
220
-
221
- - Node.js 18+
222
- - **Zero** runtime dependencies
223
-
224
- ## Development
225
-
226
- ```bash
227
- # Build
228
- node build.mjs
229
-
230
- # Test (all offline no network calls)
231
- node --test tests/*.mjs
232
-
233
- # Pack (dry run verify included files)
234
- npm pack --dry-run
235
- ```
236
-
237
- ## Publishing
238
-
239
- ```bash
240
- # 1. Build
241
- node build.mjs
242
-
243
- # 2. Run all tests
244
- node --test tests/*.mjs
245
-
246
- # 3. Inspect the tarball
247
- npm pack --dry-run
248
- # Expected files: LICENSE, README.md, dist/index.js, package.json
249
-
250
- # 4. Publish to npm (requires npm login)
251
- npm publish --access public
252
-
253
- # 5. Verify install (from a clean machine or CI)
254
- npx @trucore/atf@1.0.0 version
255
- npx @trucore/atf@1.0.0 health
256
- ```
257
-
258
- ## License
259
-
260
- MIT
1
+ # @trucore/atf
2
+
3
+ > Agent Transaction Firewall CLI — simulate, verify, and execute on-chain transactions trustlessly.
4
+
5
+ ## One-Liner
6
+
7
+ ```bash
8
+ npx @trucore/atf@1.3.0 simulate --preset swap_small --verify --pretty
9
+ ```
10
+
11
+ That's it. No install, no config, no API key required.
12
+
13
+ ## What It Does
14
+
15
+ 1. Sends a deterministic preset transaction to the ATF public API
16
+ 2. Returns **allowed** or **denied** with a reason and receipt hash
17
+ 3. Verifies **content_hash** integrity client-side — don't trust TruCore, verify
18
+ 4. Executes **real on-chain Solana swaps** (Jupiter DEX) gated by ATF policy
19
+ 5. **Profile-based config** — switch between mainnet/devnet, Helius RPC, keypairs
20
+ 6. **Transaction tooling** — sign, send, confirm, and verify receipts offline
21
+
22
+ ## Install (optional)
23
+
24
+ ```bash
25
+ npm install -g @trucore/atf@1.3.0
26
+ ```
27
+
28
+ Or use directly with `npx` (always pin the version):
29
+
30
+ ```bash
31
+ npx @trucore/atf@1.3.0 simulate --preset swap_small
32
+ ```
33
+
34
+ ## Quickstart: Devnet Burner
35
+
36
+ ```bash
37
+ npx @trucore/atf@1.3.0 swap --burner --devnet --in SOL --out USDC --amount-in 0.01 --execute --yes --confirm
38
+ ```
39
+
40
+ ## Quickstart: Helius Profile Setup
41
+
42
+ ```bash
43
+ npx @trucore/atf@1.3.0 config init --yes
44
+ npx @trucore/atf@1.3.0 profile create devnet
45
+ npx @trucore/atf@1.3.0 profile use devnet
46
+ npx @trucore/atf@1.3.0 config set solana_cluster devnet
47
+ npx @trucore/atf@1.3.0 config set rpc_url helius
48
+ export HELIUS_API_KEY=your_key_here
49
+ npx @trucore/atf@1.3.0 rpc ping
50
+ ```
51
+
52
+ ## Commands
53
+
54
+ ### `health`
55
+
56
+ Check API health and round-trip latency.
57
+
58
+ ```bash
59
+ npx @trucore/atf@1.3.0 health
60
+ npx @trucore/atf@1.3.0 health --pretty
61
+ npx @trucore/atf@1.3.0 health --base-url http://localhost:3000
62
+ ```
63
+
64
+ **Output shape:**
65
+
66
+ ```json
67
+ { "ok": true, "base_url": "https://api.trucore.xyz", "latency_ms": 42, "response": { "status": "ok" } }
68
+ ```
69
+
70
+ ### `simulate`
71
+
72
+ Run a transaction simulation against the ATF API.
73
+
74
+ ```bash
75
+ npx @trucore/atf@1.3.0 simulate --preset swap_small --verify
76
+ npx @trucore/atf@1.3.0 simulate --preset swap_too_large --pretty
77
+ npx @trucore/atf@1.3.0 simulate --json '{"chain_id":1,"value_eth":"0.5"}' --base-url http://localhost:3000
78
+ ```
79
+
80
+ **Output shape:**
81
+
82
+ ```json
83
+ { "ok": true, "base_url": "https://api.trucore.xyz", "preset": "swap_small", "verified": true, "response": { "decision": "allowed", "reasons": [], "receipt_hash": "a1b2...64hex", "content_hash": "c3d4...64hex" } }
84
+ ```
85
+
86
+ ### `approve`
87
+
88
+ Approve a pending intent (requires authentication).
89
+
90
+ ```bash
91
+ npx @trucore/atf@1.3.0 approve --intent abc123 --token mytoken
92
+ npx @trucore/atf@1.3.0 approve --intent abc123 --token mytoken --pretty
93
+ ```
94
+
95
+ **Output shape:**
96
+
97
+ ```json
98
+ { "ok": true, "base_url": "https://api.trucore.xyz", "intent": "abc123", "response": { "intent_id": "abc123", "status": "approved" } }
99
+ ```
100
+
101
+ ### `version`
102
+
103
+ Show rich version information (CLI version, Node version, build info).
104
+
105
+ ```bash
106
+ npx @trucore/atf@1.3.0 version
107
+ npx @trucore/atf@1.3.0 version --pretty
108
+ ```
109
+
110
+ **Output shape:**
111
+
112
+ ```json
113
+ { "ok": true, "cli_version": "1.3.0", "node_version": "v22.0.0", "platform": "linux", "arch": "x64", "default_base_url": "https://api.trucore.xyz", "build_commit": "abc1234", "build_date": "2025-01-01T00:00:00Z" }
114
+ ```
115
+
116
+ ### `swap`
117
+
118
+ Execute a **real on-chain Solana swap** (Jupiter DEX) gated by ATF policy evaluation.
119
+
120
+ > **⚠ WARNING:** This command signs transactions with your local keypair.
121
+ > Use a burner wallet for demos. Start with a tiny amount (e.g. 0.001 SOL).
122
+
123
+ **Dry run (no funds move):**
124
+
125
+ ```bash
126
+ npx @trucore/atf@1.3.0 swap \
127
+ --in SOL --out USDC \
128
+ --amount-in 0.001 \
129
+ --slippage-bps 50 \
130
+ --keypair ~/.config/solana/id.json \
131
+ --dry-run
132
+ ```
133
+
134
+ **Real transaction (mainnet):**
135
+
136
+ ```bash
137
+ npx @trucore/atf@1.3.0 swap \
138
+ --in SOL --out USDC \
139
+ --amount-in 0.001 \
140
+ --slippage-bps 50 \
141
+ --keypair ~/.config/solana/id.json \
142
+ --rpc https://api.mainnet-beta.solana.com \
143
+ --confirm
144
+ ```
145
+
146
+ **Devnet burner one-liner (generates ephemeral keypair, no files needed):**
147
+
148
+ ```bash
149
+ npx @trucore/atf@1.3.0 swap \
150
+ --burner --devnet \
151
+ --in SOL --out USDC \
152
+ --amount-in 0.01 \
153
+ --slippage-bps 100 \
154
+ --execute --yes --confirm
155
+ ```
156
+
157
+ > **⚠️ burner is devnet-only.** The `--burner` flag auto-generates an ephemeral
158
+ > keypair in memory. It forces devnet mode and will refuse any mainnet RPC. Do
159
+ > not use for real funds. Devnet swaps use a SOL transfer fallback since Jupiter
160
+ > does not support devnet.
161
+
162
+ **Output shape (success):**
163
+
164
+ ```json
165
+ {
166
+ "ok": true,
167
+ "request_id": "abc123...",
168
+ "base_url": "https://api.trucore.xyz",
169
+ "preset": null,
170
+ "verified": true,
171
+ "response": {
172
+ "decision": "allowed",
173
+ "receipt_hash": "a1b2...64hex",
174
+ "content_hash": "c3d4...64hex"
175
+ },
176
+ "execution": {
177
+ "rpc": "https://api.mainnet-beta.solana.com",
178
+ "signature": "5SiGA...",
179
+ "explorer_url": "https://solscan.io/tx/5SiGA...",
180
+ "jupiter": { "inAmount": "1000000", "outAmount": "150000", "priceImpactPct": "0.01" },
181
+ "confirmation_status": "confirmed",
182
+ "sent_at": "2026-02-28T12:00:00.000Z"
183
+ }
184
+ }
185
+ ```
186
+
187
+ **If denied:** exits 1 with `ok: false`, no on-chain transaction executed.
188
+
189
+ ### `config`
190
+
191
+ Manage CLI configuration (init, set, get, list).
192
+
193
+ ```bash
194
+ atf config init --yes # Create default config
195
+ atf config set solana_cluster devnet
196
+ atf config set rpc_url helius # Use Helius RPC (requires HELIUS_API_KEY)
197
+ atf config set tx.max_retries 5
198
+ atf config get rpc_url
199
+ atf config list # Show merged effective config
200
+ atf config list --pretty
201
+ ```
202
+
203
+ ### `profile`
204
+
205
+ Manage named configuration profiles.
206
+
207
+ ```bash
208
+ atf profile list # List all profiles
209
+ atf profile create staging # Create new profile
210
+ atf profile use staging # Switch active profile
211
+ atf profile delete staging # Delete a profile
212
+ ```
213
+
214
+ Use `--profile <name>` on any command to override the active profile for that invocation.
215
+
216
+ ### `secret`
217
+
218
+ Manage sensitive credentials (stored in `~/.config/atf/secrets.json` with `0600` permissions).
219
+
220
+ ```bash
221
+ echo "my-helius-key" | atf secret set helius
222
+ atf secret list # Shows namespaces/profiles, never values
223
+ atf secret unset helius
224
+ ```
225
+
226
+ Secrets are resolved with priority: environment variable > secrets store.
227
+
228
+ ### `rpc ping`
229
+
230
+ Check Solana RPC connectivity and latency.
231
+
232
+ ```bash
233
+ atf rpc ping # Uses profile RPC or default
234
+ atf rpc ping --devnet # Ping devnet
235
+ atf rpc ping --rpc https://custom-rpc.example.com
236
+ atf rpc ping --pretty
237
+ ```
238
+
239
+ **Output shape:**
240
+
241
+ ```json
242
+ { "ok": true, "cluster": "mainnet-beta", "rpc_host": "mainnet.helius-rpc.com", "latency_ms": 85, "version": "2.2.1", "slot": 348123456 }
243
+ ```
244
+
245
+ ### `tx sign`
246
+
247
+ Offline-sign a base64-encoded Solana transaction.
248
+
249
+ ```bash
250
+ atf tx sign --tx-base64 <base64> --keypair ~/.config/solana/id.json
251
+ atf tx sign --tx-file unsigned.bin --keypair ~/.config/solana/id.json
252
+ ```
253
+
254
+ **Output shape:**
255
+
256
+ ```json
257
+ { "ok": true, "signed_tx_base64": "..." }
258
+ ```
259
+
260
+ ### `tx send`
261
+
262
+ Sign, send, and optionally confirm a Solana transaction.
263
+
264
+ ```bash
265
+ atf tx send --tx-base64 <base64> --keypair ~/.config/solana/id.json
266
+ atf tx send --tx-base64 <base64> --keypair ~/id.json --confirm --rpc helius
267
+ ```
268
+
269
+ **Output shape:**
270
+
271
+ ```json
272
+ { "ok": true, "signature": "5SiGA...", "explorer_url": "https://solscan.io/tx/5SiGA...", "confirmation_status": "confirmed" }
273
+ ```
274
+
275
+ ### `tx status`
276
+
277
+ Poll the confirmation status of a transaction signature.
278
+
279
+ ```bash
280
+ atf tx status --sig 5SiGA...
281
+ atf tx status --sig 5SiGA... --pretty
282
+ ```
283
+
284
+ **Output shape:**
285
+
286
+ ```json
287
+ { "ok": true, "signature": "5SiGA...", "status": "finalized", "slot": 348123456, "err": null }
288
+ ```
289
+
290
+ ### `receipts verify`
291
+
292
+ Verify ATF receipt hash integrity offline.
293
+
294
+ ```bash
295
+ atf receipts verify --file receipt.json
296
+ cat receipt.json | atf receipts verify --stdin
297
+ atf receipts verify --file receipt.json --pretty
298
+ ```
299
+
300
+ **Output shape:**
301
+
302
+ ```json
303
+ { "ok": true, "content_hash_valid": true, "receipt_hash_valid": true, "file": "receipt.json" }
304
+ ```
305
+
306
+ ### `whoami`
307
+
308
+ Show current profile context, config, and CLI version.
309
+
310
+ ```bash
311
+ atf whoami
312
+ atf whoami --pretty
313
+ atf whoami --profile staging
314
+ ```
315
+
316
+ **Output shape:**
317
+
318
+ ```json
319
+ { "ok": true, "profile": "default", "atf_base_url": "https://api.trucore.xyz", "solana_cluster": "mainnet-beta", "rpc_host": "mainnet.helius-rpc.com", "commitment": "confirmed", "explorer": "solscan", "cli_version": "1.3.0" }
320
+ ```
321
+
322
+ ### `ls`
323
+
324
+ Alias for `config list`.
325
+
326
+ ```bash
327
+ atf ls
328
+ atf ls --pretty
329
+ ```
330
+
331
+ ### `completion`
332
+
333
+ Generate shell completion scripts.
334
+
335
+ ```bash
336
+ atf completion bash >> ~/.bashrc
337
+ atf completion zsh >> ~/.zshrc
338
+ atf completion fish > ~/.config/fish/completions/atf.fish
339
+ atf completion powershell >> $PROFILE
340
+ ```
341
+
342
+ ## Global Options
343
+
344
+ | Flag | Description | Default |
345
+ |------|-------------|---------|
346
+ | `--base-url <url>` | API base URL | `https://api.trucore.xyz` |
347
+ | `--timeout-ms <ms>` | Request timeout in milliseconds | `20000` |
348
+ | `--format <fmt>` | Output: `json` or `pretty` | `json` |
349
+ | `--pretty` | Shorthand for `--format pretty` | `false` |
350
+ | `--no-color` | Disable ANSI colors | `false` |
351
+ | `--api-key <key>` | API key (also: `ATF_API_KEY` env var) | — |
352
+ | `--profile <name>` | Use a named config profile | `default` |
353
+
354
+ ## Simulate Options
355
+
356
+ | Flag | Description | Default |
357
+ |------|-------------|---------|
358
+ | `--preset <name>` | Built-in preset: `swap_small`, `swap_too_large`, `ttl_too_high` | — |
359
+ | `--json '<json>'` | Raw JSON transaction body | — |
360
+ | `--verify` | Verify content_hash integrity | `false` |
361
+ | `--quiet` | Suppress non-essential output | `false` |
362
+
363
+ ## Approve Options
364
+
365
+ | Flag | Description | Default |
366
+ |------|-------------|---------|
367
+ | `--intent <id>` | Intent ID to approve (required) | — |
368
+ | `--intent-id <id>` | Alias for `--intent` (backward compat) | — |
369
+ | `--token <bearer>` | Bearer token for auth (also: `ATF_API_KEY` env var) | — |
370
+
371
+ ## Swap Options
372
+
373
+ | Flag | Description | Default |
374
+ |------|-------------|---------|
375
+ | `--in <symbol\|mint>` | Input token symbol or mint address | — |
376
+ | `--out <symbol\|mint>` | Output token symbol or mint address | — |
377
+ | `--amount-in <number>` | Amount of input token (human units, e.g. 0.001) | — |
378
+ | `--slippage-bps <int>` | Slippage tolerance in basis points | `50` |
379
+ | `--keypair <path>` | Path to Solana id.json keypair file | — |
380
+ | `--rpc <url>` | Solana RPC URL (or `"helius"` to auto-build) | `https://api.mainnet-beta.solana.com` |
381
+ | `--dry-run` | Simulate + quote only; do NOT sign or send | `false` |
382
+ | `--confirm` | Poll signature status until confirmed or timeout | `false` |
383
+ | `--verify` | Verify content_hash integrity | `false` |
384
+ | `--burner` | Generate ephemeral keypair (devnet only, never printed) | `false` |
385
+ | `--devnet` | Force devnet mode (RPC, token mints, explorer links) | `false` |
386
+ | `--faucet` | Print faucet instructions + burner pubkey and exit | `false` |
387
+ | `--airdrop <sol>` | Request devnet SOL airdrop (e.g. `--airdrop 1`) | — |
388
+ | `--save-burner <path>` | Save burner keypair to disk (explicit opt-in, 0600) | — |
389
+ | `--load-burner <path>` | Load a previously saved burner keypair | — |
390
+
391
+ **Supported tokens (mainnet v1):** SOL, USDC, USDT
392
+
393
+ **Supported tokens (devnet):** SOL, USDC
394
+
395
+ ### Presets
396
+
397
+ | Preset | Description | Expected |
398
+ |--------|-------------|----------|
399
+ | `swap_small` | Small 0.01 ETH swap | ALLOWED |
400
+ | `swap_too_large` | 999,999 ETH swap | DENIED (value limit) |
401
+ | `ttl_too_high` | Swap with 24h TTL | DENIED (TTL policy) |
402
+
403
+ ## Output
404
+
405
+ All commands return a JSON envelope with `"ok": true/false`.
406
+
407
+ ### Success (JSON, default)
408
+
409
+ ```json
410
+ {
411
+ "ok": true,
412
+ "base_url": "https://api.trucore.xyz",
413
+ "preset": "swap_small",
414
+ "verified": true,
415
+ "response": {
416
+ "decision": "allowed",
417
+ "reasons": [],
418
+ "receipt_hash": "a1b2c3...64hex",
419
+ "content_hash": "d4e5f6...64hex"
420
+ }
421
+ }
422
+ ```
423
+
424
+ When `--verify` is not used, the `verified` field is `null`.
425
+ When a preset is not used, the `preset` field is `null`.
426
+ ```
427
+
428
+ ### Success (Pretty, `--pretty`)
429
+
430
+ ```
431
+ ✓ ALLOWED
432
+ Reason: All policies passed
433
+ Receipt: a1b2c3...64hex
434
+
435
+ ✓ Content hash verified
436
+ ```
437
+
438
+ ### Errors
439
+
440
+ All errors return a structured JSON envelope:
441
+
442
+ ```json
443
+ {
444
+ "ok": false,
445
+ "error": {
446
+ "code": "NETWORK_ERROR",
447
+ "message": "Network failure — fetch failed",
448
+ "details": {
449
+ "hint": "Check your network connection and base URL."
450
+ }
451
+ }
452
+ }
453
+ ```
454
+
455
+ Error codes: `USER_ERROR`, `DENIED`, `NETWORK_ERROR`, `SERVER_ERROR`, `VALIDATION_ERROR`, `AUTH_ERROR`, `VERIFY_FAILED`.
456
+
457
+ ## Exit Codes
458
+
459
+ | Code | Meaning |
460
+ |------|---------|
461
+ | 0 | Success (allowed, healthy, approved, etc.) |
462
+ | 1 | User error or denied (bad input, auth failure, transaction denied, verify failed) |
463
+ | 2 | Network / server error (unreachable, 5xx, timeout, rate limited) |
464
+
465
+ ## Trustless Verification
466
+
467
+ **Don't trust TruCore — verify.**
468
+
469
+ Every simulation produces a `content_hash` (SHA-256). You can:
470
+
471
+ 1. **Use `--verify` flag:** Automatically recomputes and checks content_hash integrity client-side.
472
+ 2. **Recompute locally:** The policy engine is deterministic. Same input → same hash.
473
+ 3. **Check receipt signatures** (when available): `GET /api/receipt-signing-key`
474
+
475
+ The `--verify` flag checks content_hash integrity automatically. On mismatch it exits 1 with `VERIFY_FAILED`.
476
+
477
+ ## Token Redaction
478
+
479
+ Bearer tokens are **never** emitted in CLI output. All stdout/stderr is scrubbed
480
+ for token values and `Bearer <token>` patterns before printing.
481
+
482
+ ## Environment Variables
483
+
484
+ | Variable | Description |
485
+ |----------|-------------|
486
+ | `ATF_API_KEY` | API key (sent as `x-api-key` header or Bearer token) |
487
+ | `ATF_BASE_URL` | Override default base URL |
488
+ | `ATF_TIMEOUT_MS` | Override default timeout (milliseconds, default: `20000`) |
489
+ | `ATF_DEVNET_RPC` | Override devnet RPC URL (default: `https://api.devnet.solana.com`) |
490
+ | `HELIUS_API_KEY` | Helius RPC API key (used when `rpc_url=helius`) |
491
+ | `NO_COLOR` | Disable ANSI colors when set |
492
+
493
+ ## Requirements
494
+
495
+ - Node.js 18+
496
+ - Runtime dependency: `tweetnacl@1.0.3` (ed25519 signing for Solana transactions)
497
+
498
+ ## Development
499
+
500
+ ```bash
501
+ # Build
502
+ node build.mjs
503
+
504
+ # Test (all offline — no network calls)
505
+ node --test tests/*.mjs
506
+
507
+ # Pack (dry run — verify included files)
508
+ npm pack --dry-run
509
+ ```
510
+
511
+ ## Publishing
512
+
513
+ ```bash
514
+ # 1. Build
515
+ node build.mjs
516
+
517
+ # 2. Run all tests
518
+ node --test tests/*.mjs
519
+
520
+ # 3. Inspect the tarball
521
+ npm pack --dry-run
522
+ # Expected files: LICENSE, README.md, dist/index.js, package.json
523
+
524
+ # 4. Publish to npm (requires npm login)
525
+ npm publish --access public
526
+
527
+ # 5. Verify install (from a clean machine or CI)
528
+ npx @trucore/atf@1.3.0 version
529
+ npx @trucore/atf@1.3.0 health
530
+ npx @trucore/atf@1.3.0 whoami
531
+ ```
532
+
533
+ ## License
534
+
535
+ MIT