x402 paywall pre-authorization
x402 paywall pre-authorization (PR-X)
These vars bound the "session-level pre-authorization" feature that lets an operator authorize x402 paywall payments ONCE for a given scope, then auto-pay (no per-call confirmation) until expiry / budget exhaustion / explicit revoke. The grant call itself ALWAYS goes through the unified confirm gate. After it lands a session row, in-window x402 payments matching the session's scope skip the per-call user prompt and execute directly via transfer_token. Every auto-spend writes audit metadata (session id + remaining budget) so the user can trace each charge. Wired into: - src/minara/x402-preauth-store.ts (SQLite store + cap math) - src/minara/x402-preauth-config.ts (env loader + cap helpers) - src/tools/_shared/confirm.ts (shouldAutoExecuteX402) - src/tools/trade.ts (transfer_token consults the auto-execute path; unmatched payments stay on the unified confirm gate) - src/tools/x402-preauth.ts (LLM-callable grant / list / revoke) - src/gateway/repl-commands.ts (/x402 preauth CLI surface)
X402_PREAUTH_DEFAULT_TTL_HOURS
default session expiry when the user / LLM doesn't specify one.
- What it controls: the TTL applied when
x402_preauth_grantis called withoutttl_hours. - Consumed by: src/minara/x402-preauth-config.ts.
- When to set: shorten to keep grants short-lived (e.g. 4 = 4h); raise to give long-running batch jobs more room.
- When unset: 24 hours.
- Format: positive integer (hours).
- Setting home: Not a user-facing setting
X402_PREAUTH_MAX_TTL_HOURS
hard upper bound for non-forever session TTL.
- What it controls: a grant request with
ttl_hours > this valueis rejected withfield: "ttlMs". The cap helper enforces it uniformly across the LLM tool, the REPL command, and direct store access. - When to set: shorten to enforce shorter operator trust windows; raise only when long-lived sessions are a deployment requirement.
- When unset: 168 (7 days).
- Format: positive integer (hours).
- Setting home: Not a user-facing setting
X402_PREAUTH_ALLOW_FOREVER
whether ttl_hours: "forever" (no time-based expiry) grants are allowed.
- What it controls: when
0, the LLM tool + REPL + store reject forever-grant requests withfield: "forever". The forever-budget cap is still read for documentation but never reachable. Set to0for environments that want hard-bounded expirations on every grant (audit / compliance). - When unset:
1(forever grants permitted, gated by user-explicit double-confirm in the REPL + the LLM never proposes forever automatically). - Format:
1/true/yes/on(allow) or0/false/no/off. - Setting home: Not a user-facing setting
X402_PREAUTH_MAX_PER_CALL_USDC
hard upper bound for a single auto-paid x402 payment (USDC).
- What it controls: (a) the LLM tool + REPL reject grants with
per_call_cap_usdc > this value; (b)shouldAutoExecuteX402short-circuits withamount_over_capfor any single payment above this amount, falling back to the regular two-step confirm. This is the single most important safety bound — it caps how much a single bad paywall can drain even if the user granted a higher cap inside an existing session. - When to set: shorten on shared infrastructure to limit per-call blast radius. Raise only when paywalls legitimately cost more.
- When unset: 0.5 (USDC).
- Format: positive number (USDC).
- Setting home: Not a user-facing setting
X402_PREAUTH_MAX_BUDGET_USDC
hard upper bound for a non-forever session's total budget (USDC).
- What it controls: a grant request with
total_budget_usdc > thisAND a non-nullttl_hoursis rejected. Forever-grant budgets use a separate (typically stricter) cap below. - When unset: 5 (USDC).
- Format: positive number (USDC).
- Setting home: Not a user-facing setting
X402_PREAUTH_MAX_FOREVER_BUDGET_USDC
hard upper bound for a forever-session total budget (USDC).
- What it controls: same shape as MAX_BUDGET_USDC but applies only when
ttl_hours: "forever". Independent because removing the time bound demands tighter $ control. The forever budget can be ABOVE or BELOW the time-bounded one — operators choose; the default sits higher because forever grants are usually small per-call that accumulate over months ("$0.01/call x 2000 calls"). - When unset: 20 (USDC).
- Format: positive number (USDC).
- Setting home: Not a user-facing setting
X402_PREAUTH_DISABLE
global kill switch.
- What it controls: when
1, every preauth code path short-circuits.transfer_tokenignoresx402_context, the LLM tools returndisablederrors, the REPL prints "x402 preauth disabled by env" and refuses to grant. All x402 payments fall back to the regular two-step confirm flow. - When to set: incident response (suspected runaway paywall), compliance audit windows where every payment must be logged with explicit user confirm, or operators who never want this feature at all.
- When unset:
0(preauth machinery active). - Format:
1/true/yes/onto disable; anything else (default) keeps it on. - Setting home: Not a user-facing setting
OpenClaw workspace integration
The agent reads + writes a workspace dir at ~/.minara/workspace/ (override via --workspace) containing markdown files modelled on OpenClaw's AGENTS.default schema: SOUL.md (identity), AGENTS.md (rules), IDENTITY.md, USER.md, MEMORY.md (curated long-term), HEARTBEAT.md (between-session memo), BOOTSTRAP.md (first-run only), and memory/YYYY-MM-DD-*.md (daily logs). Templates ship under src/workspace/templates/. minara setup seeds them on first run. The seed is idempotent and never overwrites a file the user has already edited.
WORKSPACE_HEARTBEAT_ENABLED
per-turn HEARTBEAT.md state writer.
- What it controls: when on, after every turn the agent writes
<workspace>/HEARTBEAT.mdwithlast_seen,session_id,surface,turn_count,last_user_query, plus heuristicopen_loopsextracted from the reply. The writer preserves any user-edited## Schedulesection verbatim across writes. - When to disable: read-only workspace mounts, CI runs, privacy- sensitive contexts where you don't want a session memo on disk.
- When unset: ON.
- Format:
0/false/no/offto disable; anything else (default) keeps it on. - Setting home: Settings → Preferences (schema key)
WORKSPACE_DAILY_LOG_ENABLED
append per-session daily logs.
- What it controls: when on, each cadence flushes every unjournaled
chat_turnsrow after a durable SQLite watermark into<workspace>/memory/YYYY-MM-DD-<session>.md. Rows retain their real session id, surface, and runtime source; correlation ids are never used as session ids. Per-session files avoid multi-process append races. - When to enable: long-running deployments where you want the agent to accumulate working memory you can later promote to MEMORY.md.
- When unset: OFF (the workspace stays small until explicitly opted in).
- Format:
1/true/yes/onto enable. - Setting home: Settings → Preferences (schema key)
WORKSPACE_DAILY_LOG_INTERVAL
turns between daily-log appends.
- What it controls: cadence for flushing the
chat_turnsbacklog above. Every due flush writes all rows after the watermark, so increasing the interval delays persistence but does not sample or drop intervening turns. - When unset: 5 turns.
- Format: positive integer.
- Setting home: Not a user-facing setting
WORKSPACE_DREAM_ENABLED
periodic MEMORY.md consolidation.
- What it controls: when on, a setInterval task wakes every
WORKSPACE_DREAM_INTERVAL_HOURS, reads recent daily logs frommemory/, and asks the active LLM to extract durable facts / preferences / decisions. The result lands as a## Dreamed YYYY-MM-DDsection appended to MEMORY.md (append-only — user edits are never overwritten). Automation-origin journal turns remain auditable on disk but are removed before the LLM prompt, so Autopilot, strategy, workflow, or unknown perps runs cannot become user preferences. - When to enable: long-running deployments where the operator wants long-term memory to evolve from short-term logs without manual curation. Costs LLM calls — keep off in cost-sensitive contexts.
- When unset: OFF.
- Format:
1/true/yes/onto enable. - Setting home: Settings → Preferences (schema key)
WORKSPACE_DREAM_INTERVAL_HOURS
dream consolidation cadence.
- What it controls: hours between dreaming runs. The scheduler skips a tick when the previous run is still in flight, so a slow LLM call can't pile up. Has no effect when
WORKSPACE_DREAM_ENABLEDis off. - When unset: 24 (one consolidation pass per day).
- Format: positive number (hours, can be fractional).
- Setting home: Not a user-facing setting
WORKSPACE_DREAM_TOTAL_INPUT_BYTES
global byte budget for the dream prompt input (across all daily logs combined).
- What it controls: caps the total bytes shipped to the LLM in one dream pass. Daily logs are kept as a contiguous newest-first suffix under the budget, so the model always sees a chronologically continuous slice with the most recent activity included. Defends against a long window of dense logs blowing past the model's context window. Per-file content is still tail-truncated to 64 KB (the per-file cap), and the most recent log is always kept even if alone exceeds this budget. Has no effect when
WORKSPACE_DREAM_ENABLEDis off. - When unset: 262144 (256 KB).
- Format: positive integer (bytes).
- Setting home: Not a user-facing setting
WORKSPACE_DREAM_LOCK_TTL_MS
TTL for the dream lockfile.
- What it controls: how long a
<workspace>/.dreaming.lockfile is honored before it's considered stale and reclaimable by another process. Should reflect the longest reasonable duration for a single dream pass (LLM call + IO), NOT the interval between passes. The lock prevents the REPL and HTTP gateway from both consolidating the same logs into MEMORY.md when their tick windows overlap. NFS workspaces are not supported (the underlyingO_EXCLsemantics are not guaranteed atomic across all NFS clients) — keep dreaming on a single host. Has no effect whenWORKSPACE_DREAM_ENABLEDis off. - When unset: 1800000 (30 minutes).
- Format: positive integer (milliseconds).
- Setting home: Not a user-facing setting
REPORT_BUNDLE_CHART_PNGS
fall back to PNG-bundled charts in deep-research HTML / PDF reports instead of interactive ECharts.
- What it controls: when set, the gateway's deep-research branch passes
["html", "pdf", "charts"]torenderDeepResearchReportsobundleChartPngsruns and the HTML embeds eachchart://<id>as a static<img src="charts/<id>.png">tag (rendered server-side via headless playwright). When unset, the default since v7, the gateway passes["html", "pdf"]only and every chart:// link expands to the canonical ECharts embed pattern (<div class="echart-host">+ inline<script>hydrated from the echarts CDN). Default produces interactive charts with zoom + tooltip + saveAsImage PNG download. - Which skill / tool consumes it: the deep-research pipeline (
src/gateway/api.tshandleChatStreamdeep-research branch). - When to set it: operators who export reports for offline distribution (where the echarts CDN is unreachable) or who cannot tolerate the ~120 KB CDN script being fetched on open. Trade-off: PNG-bundled charts are static — no zoom, no tooltip, no PNG download button. Headless playwright must be installed (already a project dep) so chart materialisation can run.
- When unset: interactive ECharts (CDN-hydrated). Open the HTML in a browser with network access to see charts; offline charts degrade to a small "chart unavailable" placeholder per the embed script's try/catch.
- Format: 1 / true (enable) — any other value, or unset, disables.
- Setting home: Settings → Preferences (schema key)
WALLET DEPOSIT WATCH
Real-time deposit-detection SSE endpoint (POST /v1/wallet/deposits/watch). Powers the green-flip in the Portfolio DepositModal for perps USDC/Arbitrum addresses. Two chain transports; the agent picks at boot: 1. Alchemy (preferred) — set ALCHEMY_API_KEY. Uses alchemy_getAssetTransfers (purpose-built incoming-transfer query) + alchemy_pendingTransactions WS subscription for real mempool sighting. Free tier: 300M CU / month. 2. Public RPC fallback — when no ALCHEMY_API_KEY. Polls eth_getLogs every 5s for the USDC Transfer event filtered to the deposit address. No mempool visibility (the pending event is not emitted in this mode). What it controls: WALLET_DEPOSIT_WATCH_ENABLED — master switch for the SSE endpoint. Default ON in dev so the feature works out of the box; set to false / 0 to disable cleanly. When off, the web-ui's DepositStatus pill shows "Live updates unavailable" and the user can still copy the address normally. Which skill / tool consumes it: apps/agent/src/wallet-watch/* and the api.ts handleWalletDepositsWatch handler.
WALLET_DEPOSIT_WATCH_ENABLED
WALLET_DEPOSIT_WATCH_ENABLED=true
- Setting home: Settings → Preferences (schema key)
ALCHEMY_API_KEY
Alchemy API key for Arbitrum. One key works across all Alchemy chains. Optional — without it the watcher falls back to the public Arbitrum RPC (no mempool detection). ALCHEMY_API_KEY=abc123...
- Setting home: Settings → API Keys
ALCHEMY_NETWORK
Alchemy network enum string. arb-mainnet is the only one we care about today (perps wallet deposits = USDC on Arbitrum). Override only if you point ALCHEMY_API_KEY at a testnet for end-to-end QA. ALCHEMY_NETWORK=arb-mainnet
- Setting home: Not a user-facing setting
ARBITRUM_RPC_URL
Public Arbitrum RPC URL — used when ALCHEMY_API_KEY is unset.
- Default: https://arb1.arbitrum.io/rpc (Arbitrum Foundation).
- Operators can swap for a paid HTTPS endpoint without enabling
- Alchemy if they only need post-confirmation detection.
- ARBITRUM_RPC_URL=https://arb1.arbitrum.io/rpc
- Setting home: Not a user-facing setting
SOLANA_RPC_URL
Public Solana RPC URL — used by the spot deposit watcher for the Solana chain. Non-EVM, so Alchemy isn't auto-wired; this URL is tried first, then the foundation-grade public list (api.mainnet- beta.solana.com, solana-rpc.publicnode.com, …) in order. The transport polls getSignaturesForAddress on the user's USDC token accounts every 5 seconds and flips to credited on the confirmed commitment.
- Default: https://api.mainnet-beta.solana.com (Solana Foundation).
- Operators on a hosted RPC (Helius, QuickNode, Triton, Alchemy
- Solana) can swap here for higher rate limits.
- SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
- Setting home: Not a user-facing setting
DEPOSIT_WATCH_TIMEOUT_MS
How long a watch session lingers before auto-close (ms). Default 20 minutes — long enough for slow chain confirmation but caps resource use on a forgotten-open modal. DEPOSIT_WATCH_TIMEOUT_MS=1200000
- Setting home: Not a user-facing setting