@buildaureon/sdk 0.1.8 → 0.1.10

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.
@@ -1,400 +1,400 @@
1
- # Production Integration Guide
2
-
3
- Integrate `@buildaureon/sdk` into server-side agents and automated rebalancing loops against the live AUREON API.
4
-
5
- **Automation note:** SDK integrations support **Automatic mode only** (`automationMode: "auto"` — the default). Do not build Manual Approve agent loops with the SDK; use the operator utility for Manual workflows.
6
-
7
- ---
8
-
9
- ## 1. End-to-end agent loop
10
-
11
- ```mermaid
12
- flowchart TD
13
- Init[1_issued_API_key_client] --> Sync[2_sync_Capital_Book]
14
- Sync --> Empty{vault empty?}
15
- Empty -->|yes| FourOhNine[restore 409]
16
- FourOhNine --> Prep[prepareVaultDeposit unsigned]
17
- Prep --> User[user/host signs when they use it]
18
- Empty -->|no| Obj[create Auto objective]
19
- Obj --> Loop[5_watchdog_heartbeat]
20
- Loop -->|breach| Plan[6_restore_plan]
21
- Plan --> Restore[7_restoreObjective]
22
- Restore --> Loop
23
- ```
24
-
25
- ### Step 1 — Client
26
-
27
- ```ts
28
- import { createAureonClient, resolveAureonNetworkFromEnv } from "@buildaureon/sdk";
29
-
30
- const resolved = resolveAureonNetworkFromEnv();
31
- export const aureon = createAureonClient({
32
- network: resolved.network,
33
- baseUrl: resolved.baseUrl,
34
- apiKey: process.env.AUREON_API_KEY!, // issued Developers key
35
- timeoutMs: 30_000,
36
- maxRetries: 2,
37
- retryDelayMs: 500,
38
- });
39
-
40
- const me = await aureon.me();
41
- console.log("operating as", me.walletAddress);
42
- ```
43
-
44
- Optional Bearer (usually unnecessary with an issued key):
45
-
46
- ```ts
47
- import {
48
- createAureonClient,
49
- createSessionTokenProvider,
50
- resolveAureonNetworkFromEnv,
51
- } from "@buildaureon/sdk";
52
-
53
- const resolved = resolveAureonNetworkFromEnv();
54
- const session = createSessionTokenProvider(process.env.AUREON_TOKEN ?? null);
55
- export const aureon = createAureonClient({
56
- network: resolved.network,
57
- baseUrl: resolved.baseUrl,
58
- apiKey: process.env.AUREON_API_KEY ?? null,
59
- getAccessToken: session.getAccessToken,
60
- });
61
- ```
62
-
63
- ### Step 2 — Sync Capital Book
64
-
65
- ```ts
66
- const { portfolio, chainId } = await aureon.syncPortfolio();
67
- console.log({
68
- chainId,
69
- positions: portfolio.positions.length,
70
- totalNotionalUsd: portfolio.totalNotionalUsd,
71
- });
72
- ```
73
-
74
- Prefer `syncPortfolio()` over hand-seeded books in production. Use `setPortfolio` only for controlled rehearsals.
75
-
76
- ### Step 3 — Empty vault is first use (do not fund for the user)
77
-
78
- Automatic restore on an empty vault must **409**. That is the same path as testnet. The SDK/MCP process does **not** broadcast a deposit. When the user actually uses the product, their host wallet signs `prepareVaultDeposit` steps.
79
-
80
- ```ts
81
- import type { VaultPrepareResult } from "@buildaureon/sdk";
82
-
83
- const status = await aureon.getVaultStatus();
84
- if (status.empty) {
85
- // restoreObjective must 409 here — do not treat that as a bug
86
- const prep = await aureon.prepareVaultDeposit({ symbol: "USDG", amount: "0.05" });
87
- // prep.steps are UNSIGNED. Return them. The user broadcasts when they fund.
88
- return prep;
89
- }
90
- ```
91
-
92
- Typical broadcast (viem sketch):
93
-
94
- ```ts
95
- // host-owned — not part of the SDK
96
- await walletClient.sendTransaction({
97
- to: step.to,
98
- data: step.data,
99
- value: step.value ? BigInt(step.value) : 0n,
100
- });
101
- ```
102
-
103
- ### Step 4 — Create an Automatic objective
104
-
105
- ```ts
106
- const objective = await aureon.createObjective({
107
- name: "Maintain 20% WETH",
108
- kind: "balanced_portfolio",
109
- targetWeight: 0.2,
110
- tolerance: 0.03,
111
- targetSymbol: "WETH",
112
- // automationMode defaults to "auto" — keep it that way for SDK agents
113
- priority: "medium",
114
- });
115
- ```
116
-
117
- **Locks:** `targetSymbol` and `automationMode` cannot change after create. Recreate the objective to change token or mode.
118
-
119
- ### Step 5 — Watchdog heartbeat
120
-
121
- ```ts
122
- async function heartbeat() {
123
- const refreshed = await aureon.refreshWatchdog();
124
- console.log("breaches", refreshed.breaches.length);
125
-
126
- for (const breach of refreshed.breaches) {
127
- const plan = await aureon.getRestorePlan(breach.objectiveId);
128
- console.log("plan", plan.kind, plan);
129
-
130
- const receipt = await aureon.restoreObjective(breach.objectiveId);
131
- console.log({
132
- settlement: receipt.settlement, // "vault" | "staged"
133
- status: receipt.status,
134
- tx: receipt.transactionHash,
135
- });
136
- }
137
-
138
- const health = await aureon.getHealth();
139
- return health;
140
- }
141
- ```
142
-
143
- ### Step 6 — Verify
144
-
145
- ```ts
146
- await aureon.getHealth(objective.id);
147
- await aureon.getTimeline(objective.id);
148
- await aureon.listExecutions(objective.id);
149
- ```
150
-
151
- Always branch UI/agent copy on `receipt.settlement`.
152
-
153
- ---
154
-
155
- ## 2. Recommended objective kinds for agents
156
-
157
- | Kind | Typical use |
158
- | --- | --- |
159
- | `balanced_portfolio` | Hold `targetSymbol` near a weight band |
160
- | `stable_allocation` | Keep a stable sleeve near a weight |
161
- | `risk_ceiling` | Cap portfolio risk score |
162
- | `reward_reinvestment` | Sweep rewards into a sleeve |
163
-
164
- Start with one Automatic `balanced_portfolio` objective and a funded vault before adding more policies.
165
-
166
- ---
167
-
168
- ## 2b. Green vs plan paradox demo (Update 2)
169
-
170
- Most dashboards celebrate green PnL. AUREON separates book performance from plan adherence:
171
-
172
- ```ts
173
- // Baseline
174
- const before = await aureon.getAllocationVsTarget();
175
- console.log(before.rows); // current vs target per objective
176
-
177
- // Controlled shock — keep violation visible
178
- await aureon.applyMarketEvent({
179
- symbol: "NVDA",
180
- priceChangeRatio: 0.45,
181
- autoRestore: false,
182
- });
183
-
184
- const after = await aureon.getAllocationVsTarget();
185
- console.log(after.paradox.message);
186
- // "Book is up (5.0%), but 1 objective is off-plan."
187
- ```
188
-
189
- Run the full script: `pnpm example:green-vs-plan` (requires `AUREON_API_KEY`).
190
-
191
- ---
192
-
193
- ## 2c. AI → objective → portfolio (Update 3)
194
-
195
- Most AI agents can transact but forget what the user wanted. AUREON registers intent as a persistent objective, then reads the portfolio through that policy:
196
-
197
- ```ts
198
- const flow = await aureon.applyFinancialIntent({
199
- brief: "Keep about 20% of the portfolio in stable assets",
200
- kind: "stable_allocation",
201
- targetWeight: 0.2,
202
- tolerance: 0.02,
203
- });
204
-
205
- console.log(flow.intent.policySummary);
206
- console.log(flow.objective.id);
207
- console.log(flow.health?.state);
208
- console.log(flow.message);
209
- ```
210
-
211
- For demos, `parseFinancialIntent(brief)` converts a user sentence into structured fields (rule-based, not production NLU).
212
-
213
- Run the full script: `pnpm example:ai-to-objective-to-portfolio`.
214
-
215
- Then use `getAllocationVsTarget()` (Update 2) to compare objective vs actual over time.
216
-
217
- ---
218
-
219
- ## 2d. Drift → detection → restore (Update 4)
220
-
221
- Update 2 stops at the paradox — book up, plan off-target, no restore. Update 4 closes the loop:
222
-
223
- ```ts
224
- const flow = await aureon.runDriftRestoreDemo();
225
-
226
- console.log(flow.rule.summary);
227
- console.log(flow.phases.aligned.health.state);
228
- console.log(flow.phases.drift.health.state);
229
- console.log(flow.phases.restored?.receipt?.settlement);
230
- console.log(flow.message);
231
- ```
232
-
233
- For read-only monitoring without mutating the book, use `getDriftRestoreFlow()` — it joins objectives, health, allocation rows, restore plans (when off-plan), and the latest execution receipt.
234
-
235
- Run the full script: `pnpm example:drift-detect-restore`.
236
-
237
- ---
238
-
239
- ## 2e. Receipt → verification (Update 5)
240
-
241
- Update 4 returns a receipt after restore. Update 5 teaches that **"transaction successful" is a claim**, not proof:
242
-
243
- ```ts
244
- const flow = await aureon.runReceiptVerificationDemo();
245
-
246
- console.log(flow.phases.claimed.result);
247
- console.log(flow.phases.validation.valid);
248
- console.log(flow.proofTier);
249
- console.log(flow.phases.settlement?.verifiedOnChain);
250
- console.log(flow.message);
251
- ```
252
-
253
- Proof tiers: **claim_only** (validation failed) → **schema_valid** (honest receipt shape) → **chain_verified** (independent settlement record for vault).
254
-
255
- For read-only checks on existing executions, use `getReceiptVerificationFlow(executionId?)`.
256
-
257
- Run the full script: `pnpm example:receipt-verification`.
258
-
259
- Forward link: Update 6 — Claude/Cursor + AUREON agent-in-host demo.
260
-
261
- ---
262
-
263
- ## 2f. Portfolio watch while away (Update 6)
264
-
265
- Consumer hook: *“Imagine telling your AI: watch my portfolio while I'm away.”*
266
-
267
- ```ts
268
- const flow = await aureon.runPortfolioWatchDemo({ host: "cursor" });
269
-
270
- console.log(flow.userBrief);
271
- console.log(flow.phases.register.automationMode);
272
- console.log(flow.phases.whileAway?.autoRestored);
273
- for (const line of flow.phases.briefing.summaryLines) {
274
- console.log(line);
275
- }
276
- ```
277
-
278
- Update 4 uses `autoRestore: false` (manual restore demo). Update 6 uses **`autoRestore: true`** — Automatic mode acts while the operator is away.
279
-
280
- For read-only briefing on existing Automatic objectives: `getPortfolioWatchFlow()`.
281
-
282
- Run the full script: `pnpm example:portfolio-watch`.
283
-
284
- Forward link: Update 7 — full AUREON loop.
285
-
286
- ---
287
-
288
- ## 2g. Full AUREON loop (Update 7)
289
-
290
- Positioning hook: *"We're not building another portfolio tracker."*
291
-
292
- ```ts
293
- const flow = await aureon.runFullAureonLoopDemo();
294
-
295
- console.log(flow.phases.intent.policySummary);
296
- console.log(flow.phases.planCheck.afterShock.paradox.detected);
297
- console.log(flow.phases.driftRestore.settlement);
298
- console.log(flow.phases.verification.proofTier);
299
- console.log(flow.message);
300
- ```
301
-
302
- One composite closes the content arc: **intent → plan check → restore → receipt verification**. A tracker stops at marks; AUREON registers policy, exposes green-vs-plan failure (`autoRestore: false`), restores, then validates the receipt.
303
-
304
- For read-only joins on existing objectives with receipts: `getFullAureonLoopFlow()`.
305
-
306
- Run the full script: `pnpm example:full-aureon-loop`.
307
-
308
- ---
309
-
310
- ### PM2
311
-
312
- ```js
313
- module.exports = {
314
- apps: [
315
- {
316
- name: "aureon-agent-loop",
317
- script: "./dist/index.js",
318
- instances: 1,
319
- autorestart: true,
320
- env: {
321
- NODE_ENV: "production",
322
- // omit AUREON_API_URL for local mainnet 8788 / 4663
323
- // AUREON_NETWORK: "testnet" // public host, still 46630
324
- // AUREON_API_KEY from secret store / PM2 ecosystem secrets
325
- },
326
- },
327
- ],
328
- };
329
- ```
330
-
331
- ### systemd
332
-
333
- ```ini
334
- [Unit]
335
- Description=AUREON Automatic restore agent
336
- After=network.target
337
-
338
- [Service]
339
- Type=simple
340
- User=node
341
- WorkingDirectory=/home/node/app
342
- ExecStart=/usr/bin/node dist/index.js
343
- Restart=on-failure
344
- RestartSec=10
345
- Environment=NODE_ENV=production
346
-
347
- [Install]
348
- WantedBy=multi-user.target
349
- ```
350
-
351
- ### Logging
352
-
353
- ```ts
354
- import { createAureonClient } from "@buildaureon/sdk";
355
-
356
- const aureon = createAureonClient({
357
- apiKey: process.env.AUREON_API_KEY!,
358
- logger: {
359
- debug: (msg, ctx) => console.debug(msg, ctx),
360
- info: (msg, ctx) => console.info(msg, ctx),
361
- warn: (msg, ctx) => console.warn(msg, ctx),
362
- error: (msg, ctx) => console.error(msg, ctx),
363
- },
364
- });
365
- ```
366
-
367
- Never log API keys, Bearer tokens, or private keys.
368
-
369
- ---
370
-
371
- ## 4. Frontend / SPA notes
372
-
373
- - Do not ship issued API keys in public browser bundles.
374
- - Prefer a backend proxy for agent credentials.
375
- - Keep `refreshWatchdog` / `restoreObjective` loops on the server.
376
- - Browser operator UX is the utility app (wallet session), not the SDK agent path.
377
-
378
- ---
379
-
380
- ## 5. Troubleshooting
381
-
382
- | Symptom | Likely cause | Fix |
383
- | --- | --- | --- |
384
- | 401 invalid key | Wrong / paused / revoked key | Rotate in Developers |
385
- | 401 need issued key | Env bootstrap key alone | Use an issued Developers key |
386
- | Vault empty / cannot restore | First use — no user deposit yet | `prepareVaultDeposit` (unsigned). User/host broadcasts when they fund. Agents do not. |
387
- | Update rejects symbol/mode | Locked at create | Recreate objective |
388
- | Restore receipt `staged` | Ledger-local path | Do not claim on-chain |
389
- | Health still violated after restore | Prices / sizing / liquidity | Re-read plan, vault balances, timeline |
390
- | Network / timeout | RPC or API latency | Raise `timeoutMs`, set `maxRetries` |
391
-
392
- ---
393
-
394
- ## 6. Related docs
395
-
396
- - [Auth](./auth.md)
397
- - [Architecture](./architecture.md)
398
- - [Client API](./client-api.md)
399
- - [Error model](./error-model.md)
400
- - [Security](./security.md)
1
+ # Production Integration Guide
2
+
3
+ Integrate `@buildaureon/sdk` into server-side agents and automated rebalancing loops against the live AUREON API.
4
+
5
+ **Automation note:** SDK integrations support **Automatic mode only** (`automationMode: "auto"` — the default). Do not build Manual Approve agent loops with the SDK; use the operator utility for Manual workflows.
6
+
7
+ ---
8
+
9
+ ## 1. End-to-end agent loop
10
+
11
+ ```mermaid
12
+ flowchart TD
13
+ Init[1_issued_API_key_client] --> Sync[2_sync_Capital_Book]
14
+ Sync --> Empty{vault empty?}
15
+ Empty -->|yes| FourOhNine[restore 409]
16
+ FourOhNine --> Prep[prepareVaultDeposit unsigned]
17
+ Prep --> User[user/host signs when they use it]
18
+ Empty -->|no| Obj[create Auto objective]
19
+ Obj --> Loop[5_watchdog_heartbeat]
20
+ Loop -->|breach| Plan[6_restore_plan]
21
+ Plan --> Restore[7_restoreObjective]
22
+ Restore --> Loop
23
+ ```
24
+
25
+ ### Step 1 — Client
26
+
27
+ ```ts
28
+ import { createAureonClient, resolveAureonNetworkFromEnv } from "@buildaureon/sdk";
29
+
30
+ const resolved = resolveAureonNetworkFromEnv();
31
+ export const aureon = createAureonClient({
32
+ network: resolved.network,
33
+ baseUrl: resolved.baseUrl,
34
+ apiKey: process.env.AUREON_API_KEY!, // issued Developers key
35
+ timeoutMs: 30_000,
36
+ maxRetries: 2,
37
+ retryDelayMs: 500,
38
+ });
39
+
40
+ const me = await aureon.me();
41
+ console.log("operating as", me.walletAddress);
42
+ ```
43
+
44
+ Optional Bearer (usually unnecessary with an issued key):
45
+
46
+ ```ts
47
+ import {
48
+ createAureonClient,
49
+ createSessionTokenProvider,
50
+ resolveAureonNetworkFromEnv,
51
+ } from "@buildaureon/sdk";
52
+
53
+ const resolved = resolveAureonNetworkFromEnv();
54
+ const session = createSessionTokenProvider(process.env.AUREON_TOKEN ?? null);
55
+ export const aureon = createAureonClient({
56
+ network: resolved.network,
57
+ baseUrl: resolved.baseUrl,
58
+ apiKey: process.env.AUREON_API_KEY ?? null,
59
+ getAccessToken: session.getAccessToken,
60
+ });
61
+ ```
62
+
63
+ ### Step 2 — Sync Capital Book
64
+
65
+ ```ts
66
+ const { portfolio, chainId } = await aureon.syncPortfolio();
67
+ console.log({
68
+ chainId,
69
+ positions: portfolio.positions.length,
70
+ totalNotionalUsd: portfolio.totalNotionalUsd,
71
+ });
72
+ ```
73
+
74
+ Prefer `syncPortfolio()` over hand-seeded books in production. Use `setPortfolio` only for controlled rehearsals.
75
+
76
+ ### Step 3 — Empty vault is first use (do not fund for the user)
77
+
78
+ Automatic restore on an empty vault must **409**. That is the same path as testnet. The SDK/MCP process does **not** broadcast a deposit. When the user actually uses the product, their host wallet signs `prepareVaultDeposit` steps.
79
+
80
+ ```ts
81
+ import type { VaultPrepareResult } from "@buildaureon/sdk";
82
+
83
+ const status = await aureon.getVaultStatus();
84
+ if (status.empty) {
85
+ // restoreObjective must 409 here — do not treat that as a bug
86
+ const prep = await aureon.prepareVaultDeposit({ symbol: "USDG", amount: "0.05" });
87
+ // prep.steps are UNSIGNED. Return them. The user broadcasts when they fund.
88
+ return prep;
89
+ }
90
+ ```
91
+
92
+ Typical broadcast (viem sketch):
93
+
94
+ ```ts
95
+ // host-owned — not part of the SDK
96
+ await walletClient.sendTransaction({
97
+ to: step.to,
98
+ data: step.data,
99
+ value: step.value ? BigInt(step.value) : 0n,
100
+ });
101
+ ```
102
+
103
+ ### Step 4 — Create an Automatic objective
104
+
105
+ ```ts
106
+ const objective = await aureon.createObjective({
107
+ name: "Maintain 20% WETH",
108
+ kind: "balanced_portfolio",
109
+ targetWeight: 0.2,
110
+ tolerance: 0.03,
111
+ targetSymbol: "WETH",
112
+ // automationMode defaults to "auto" — keep it that way for SDK agents
113
+ priority: "medium",
114
+ });
115
+ ```
116
+
117
+ **Locks:** `targetSymbol` and `automationMode` cannot change after create. Recreate the objective to change token or mode.
118
+
119
+ ### Step 5 — Watchdog heartbeat
120
+
121
+ ```ts
122
+ async function heartbeat() {
123
+ const refreshed = await aureon.refreshWatchdog();
124
+ console.log("breaches", refreshed.breaches.length);
125
+
126
+ for (const breach of refreshed.breaches) {
127
+ const plan = await aureon.getRestorePlan(breach.objectiveId);
128
+ console.log("plan", plan.kind, plan);
129
+
130
+ const receipt = await aureon.restoreObjective(breach.objectiveId);
131
+ console.log({
132
+ settlement: receipt.settlement, // "vault" | "staged"
133
+ status: receipt.status,
134
+ tx: receipt.transactionHash,
135
+ });
136
+ }
137
+
138
+ const health = await aureon.getHealth();
139
+ return health;
140
+ }
141
+ ```
142
+
143
+ ### Step 6 — Verify
144
+
145
+ ```ts
146
+ await aureon.getHealth(objective.id);
147
+ await aureon.getTimeline(objective.id);
148
+ await aureon.listExecutions(objective.id);
149
+ ```
150
+
151
+ Always branch UI/agent copy on `receipt.settlement`.
152
+
153
+ ---
154
+
155
+ ## 2. Recommended objective kinds for agents
156
+
157
+ | Kind | Typical use |
158
+ | --- | --- |
159
+ | `balanced_portfolio` | Hold `targetSymbol` near a weight band |
160
+ | `stable_allocation` | Keep a stable sleeve near a weight |
161
+ | `risk_ceiling` | Cap portfolio risk score |
162
+ | `reward_reinvestment` | Sweep rewards into a sleeve |
163
+
164
+ Start with one Automatic `balanced_portfolio` objective and a funded vault before adding more policies.
165
+
166
+ ---
167
+
168
+ ## 2b. Green vs plan paradox demo (Update 2)
169
+
170
+ Most dashboards celebrate green PnL. AUREON separates book performance from plan adherence:
171
+
172
+ ```ts
173
+ // Baseline
174
+ const before = await aureon.getAllocationVsTarget();
175
+ console.log(before.rows); // current vs target per objective
176
+
177
+ // Controlled shock — keep violation visible
178
+ await aureon.applyMarketEvent({
179
+ symbol: "NVDA",
180
+ priceChangeRatio: 0.45,
181
+ autoRestore: false,
182
+ });
183
+
184
+ const after = await aureon.getAllocationVsTarget();
185
+ console.log(after.paradox.message);
186
+ // "Book is up (5.0%), but 1 objective is off-plan."
187
+ ```
188
+
189
+ Run the full script: `pnpm example:green-vs-plan` (requires `AUREON_API_KEY`).
190
+
191
+ ---
192
+
193
+ ## 2c. AI → objective → portfolio (Update 3)
194
+
195
+ Most AI agents can transact but forget what the user wanted. AUREON registers intent as a persistent objective, then reads the portfolio through that policy:
196
+
197
+ ```ts
198
+ const flow = await aureon.applyFinancialIntent({
199
+ brief: "Keep about 20% of the portfolio in stable assets",
200
+ kind: "stable_allocation",
201
+ targetWeight: 0.2,
202
+ tolerance: 0.02,
203
+ });
204
+
205
+ console.log(flow.intent.policySummary);
206
+ console.log(flow.objective.id);
207
+ console.log(flow.health?.state);
208
+ console.log(flow.message);
209
+ ```
210
+
211
+ For demos, `parseFinancialIntent(brief)` converts a user sentence into structured fields (rule-based, not production NLU).
212
+
213
+ Run the full script: `pnpm example:ai-to-objective-to-portfolio`.
214
+
215
+ Then use `getAllocationVsTarget()` (Update 2) to compare objective vs actual over time.
216
+
217
+ ---
218
+
219
+ ## 2d. Drift → detection → restore (Update 4)
220
+
221
+ Update 2 stops at the paradox — book up, plan off-target, no restore. Update 4 closes the loop:
222
+
223
+ ```ts
224
+ const flow = await aureon.runDriftRestoreDemo();
225
+
226
+ console.log(flow.rule.summary);
227
+ console.log(flow.phases.aligned.health.state);
228
+ console.log(flow.phases.drift.health.state);
229
+ console.log(flow.phases.restored?.receipt?.settlement);
230
+ console.log(flow.message);
231
+ ```
232
+
233
+ For read-only monitoring without mutating the book, use `getDriftRestoreFlow()` — it joins objectives, health, allocation rows, restore plans (when off-plan), and the latest execution receipt.
234
+
235
+ Run the full script: `pnpm example:drift-detect-restore`.
236
+
237
+ ---
238
+
239
+ ## 2e. Receipt → verification (Update 5)
240
+
241
+ Update 4 returns a receipt after restore. Update 5 teaches that **"transaction successful" is a claim**, not proof:
242
+
243
+ ```ts
244
+ const flow = await aureon.runReceiptVerificationDemo();
245
+
246
+ console.log(flow.phases.claimed.result);
247
+ console.log(flow.phases.validation.valid);
248
+ console.log(flow.proofTier);
249
+ console.log(flow.phases.settlement?.verifiedOnChain);
250
+ console.log(flow.message);
251
+ ```
252
+
253
+ Proof tiers: **claim_only** (validation failed) → **schema_valid** (honest receipt shape) → **chain_verified** (independent settlement record for vault).
254
+
255
+ For read-only checks on existing executions, use `getReceiptVerificationFlow(executionId?)`.
256
+
257
+ Run the full script: `pnpm example:receipt-verification`.
258
+
259
+ Forward link: Update 6 — Claude/Cursor + AUREON agent-in-host demo.
260
+
261
+ ---
262
+
263
+ ## 2f. Portfolio watch while away (Update 6)
264
+
265
+ Consumer hook: *“Imagine telling your AI: watch my portfolio while I'm away.”*
266
+
267
+ ```ts
268
+ const flow = await aureon.runPortfolioWatchDemo({ host: "cursor" });
269
+
270
+ console.log(flow.userBrief);
271
+ console.log(flow.phases.register.automationMode);
272
+ console.log(flow.phases.whileAway?.autoRestored);
273
+ for (const line of flow.phases.briefing.summaryLines) {
274
+ console.log(line);
275
+ }
276
+ ```
277
+
278
+ Update 4 uses `autoRestore: false` (manual restore demo). Update 6 uses **`autoRestore: true`** — Automatic mode acts while the operator is away.
279
+
280
+ For read-only briefing on existing Automatic objectives: `getPortfolioWatchFlow()`.
281
+
282
+ Run the full script: `pnpm example:portfolio-watch`.
283
+
284
+ Forward link: Update 7 — full AUREON loop.
285
+
286
+ ---
287
+
288
+ ## 2g. Full AUREON loop (Update 7)
289
+
290
+ Positioning hook: *"We're not building another portfolio tracker."*
291
+
292
+ ```ts
293
+ const flow = await aureon.runFullAureonLoopDemo();
294
+
295
+ console.log(flow.phases.intent.policySummary);
296
+ console.log(flow.phases.planCheck.afterShock.paradox.detected);
297
+ console.log(flow.phases.driftRestore.settlement);
298
+ console.log(flow.phases.verification.proofTier);
299
+ console.log(flow.message);
300
+ ```
301
+
302
+ One composite closes the content arc: **intent → plan check → restore → receipt verification**. A tracker stops at marks; AUREON registers policy, exposes green-vs-plan failure (`autoRestore: false`), restores, then validates the receipt.
303
+
304
+ For read-only joins on existing objectives with receipts: `getFullAureonLoopFlow()`.
305
+
306
+ Run the full script: `pnpm example:full-aureon-loop`.
307
+
308
+ ---
309
+
310
+ ### PM2
311
+
312
+ ```js
313
+ module.exports = {
314
+ apps: [
315
+ {
316
+ name: "aureon-agent-loop",
317
+ script: "./dist/index.js",
318
+ instances: 1,
319
+ autorestart: true,
320
+ env: {
321
+ NODE_ENV: "production",
322
+ // omit AUREON_API_URL for official API https://api.aureonlabs.network
323
+ // AUREON_NETWORK: "testnet" // stay on testnet on the same official host
324
+ // AUREON_API_KEY from secret store / PM2 ecosystem secrets
325
+ },
326
+ },
327
+ ],
328
+ };
329
+ ```
330
+
331
+ ### systemd
332
+
333
+ ```ini
334
+ [Unit]
335
+ Description=AUREON Automatic restore agent
336
+ After=network.target
337
+
338
+ [Service]
339
+ Type=simple
340
+ User=node
341
+ WorkingDirectory=/home/node/app
342
+ ExecStart=/usr/bin/node dist/index.js
343
+ Restart=on-failure
344
+ RestartSec=10
345
+ Environment=NODE_ENV=production
346
+
347
+ [Install]
348
+ WantedBy=multi-user.target
349
+ ```
350
+
351
+ ### Logging
352
+
353
+ ```ts
354
+ import { createAureonClient } from "@buildaureon/sdk";
355
+
356
+ const aureon = createAureonClient({
357
+ apiKey: process.env.AUREON_API_KEY!,
358
+ logger: {
359
+ debug: (msg, ctx) => console.debug(msg, ctx),
360
+ info: (msg, ctx) => console.info(msg, ctx),
361
+ warn: (msg, ctx) => console.warn(msg, ctx),
362
+ error: (msg, ctx) => console.error(msg, ctx),
363
+ },
364
+ });
365
+ ```
366
+
367
+ Never log API keys, Bearer tokens, or private keys.
368
+
369
+ ---
370
+
371
+ ## 4. Frontend / SPA notes
372
+
373
+ - Do not ship issued API keys in public browser bundles.
374
+ - Prefer a backend proxy for agent credentials.
375
+ - Keep `refreshWatchdog` / `restoreObjective` loops on the server.
376
+ - Browser operator UX is the utility app (wallet session), not the SDK agent path.
377
+
378
+ ---
379
+
380
+ ## 5. Troubleshooting
381
+
382
+ | Symptom | Likely cause | Fix |
383
+ | --- | --- | --- |
384
+ | 401 invalid key | Wrong / paused / revoked key | Rotate in Developers |
385
+ | 401 need issued key | Env bootstrap key alone | Use an issued Developers key |
386
+ | Vault empty / cannot restore | First use — no user deposit yet | `prepareVaultDeposit` (unsigned). User/host broadcasts when they fund. Agents do not. |
387
+ | Update rejects symbol/mode | Locked at create | Recreate objective |
388
+ | Restore receipt `staged` | Ledger-local path | Do not claim on-chain |
389
+ | Health still violated after restore | Prices / sizing / liquidity | Re-read plan, vault balances, timeline |
390
+ | Network / timeout | RPC or API latency | Raise `timeoutMs`, set `maxRetries` |
391
+
392
+ ---
393
+
394
+ ## 6. Related docs
395
+
396
+ - [Auth](./auth.md)
397
+ - [Architecture](./architecture.md)
398
+ - [Client API](./client-api.md)
399
+ - [Error model](./error-model.md)
400
+ - [Security](./security.md)