Repository navigation
Expand file tree
/
Copy path.env.example
More file actions
441 lines (396 loc) · 22 KB
/
Copy path.env.example
File metadata and controls
441 lines (396 loc) · 22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
# OracleDesk backend configuration. Copy to .env and fill in what you need.
# Every value here is empty or a local default. Never commit a filled-in .env.
# Variables are validated at startup (src/config/index.ts); a bad value stops
# the server with a message naming the variable.
# ── Server ─────────────────────────────────────────────────────────────────
NODE_ENV=development
PORT=8000
# Postgres and Redis. These defaults match docker-compose.yml (local only,
# not secrets). Point them at your own servers for anything shared.
DATABASE_URL=postgresql://oracledesk:oracledesk@127.0.0.1:5433/oracledesk
# Alternatively, mount the URL from a file: DATABASE_URL_FILE=/run/secrets/database_url
# Every secret below also accepts <NAME>_FILE (env/file provider) — see #145.
# ── Secret loading (#145) ──────────────────────────────────────────────────
# env: process environment (default); file: <NAME>_FILE mounts; vault: Vault KV v2.
SECRETS_PROVIDER=env
# Refresh interval for file/vault providers (minimum 30000 ms).
SECRETS_REFRESH_MS=300000
# How long a rotated JWT_SECRET remains valid for already-issued tokens.
JWT_PREVIOUS_SECRET_GRACE_SECS=86400
# Required only when SECRETS_PROVIDER=vault.
VAULT_ADDR=
VAULT_TOKEN_FILE=
VAULT_KV_PATH=
REDIS_URL=redis://127.0.0.1:6379
# Comma-separated browser origins allowed to call the API.
CORS_ORIGINS=http://localhost:3000
# ── Auth ───────────────────────────────────────────────────────────────────
# JWT signing secret, at least 32 characters. Required in production. If
# empty in development, a random one is generated per process.
JWT_SECRET=
# Stellar secret seed (S…) that signs SEP-10 login challenges. Use a fresh
# key that holds no funds and is not the agent key. Required in production;
# generated per process in development if empty.
AUTH_SIGNING_SECRET=
# Domain shown in the challenge transaction (the frontend's host).
AUTH_HOME_DOMAIN=localhost
AUTH_WEB_AUTH_DOMAIN=
# Comma-separated G… addresses seeded as super admins on first deploy.
# After the RBAC tables exist, the database is authoritative and this list is
# not consulted per request.
ADMIN_ADDRESSES=
# Sensitive admin actions need a wallet proof no older than this (seconds).
STEP_UP_MAX_AGE_SECONDS=300
# ── Auth: challenge abuse resistance (#50) ─────────────────────────────────
# Max outstanding (unexpired, unused) challenges per address / per network.
AUTH_MAX_OUTSTANDING_PER_ADDRESS=5
AUTH_MAX_OUTSTANDING_PER_IP=30
# Above this many challenges issued per minute, clients must solve a
# hashcash-style proof of work (SAT-style). 0 disables the throttle.
AUTH_POW_THRESHOLD_PER_MIN=600
AUTH_POW_BITS=18
AUTH_POW_TTL_SECONDS=60
# How long a signed challenge stays valid, in seconds.
AUTH_CHALLENGE_TTL_SECONDS=300
# Salt for hashing client IPs. Generated per process if empty; set explicitly
# to keep hashes stable across restarts.
AUTH_IP_HASH_SALT=
# Express `trust proxy` setting (e.g. "1", "loopback", "true"). Set this when
# the app runs behind a load balancer so client IPs are read correctly.
TRUST_PROXY=
# Redis socket timeouts (ms) for the fail-closed auth store.
REDIS_COMMAND_TIMEOUT_MS=500
REDIS_CONNECT_TIMEOUT_MS=2000
# ── Auth: SEP-45 contract-account login (#47) ──────────────────────────────
# Enable login for smart-wallet (C…) accounts.
SEP45_ENABLED=false
# The deployed web_auth_verify contract id (C…). Required when enabled.
WEB_AUTH_CONTRACT_ID=
# Soroban RPC used for SEP-45 simulation; defaults to STELLAR_RPC_URL.
SEP45_RPC_URL=
# Public keys of previous server signing keys that may still verify
# challenges they issued, as G…[@ISO-8601-retirement]. Needed during a
# signing-key rotation overlap.
AUTH_PREVIOUS_SIGNING_KEYS=
# ── Stellar network ────────────────────────────────────────────────────────
STELLAR_RPC_URL=https://soroban-testnet.stellar.org
STELLAR_NETWORK_PASSPHRASE=Test SDF Network ; September 2015
# Contract ids. Empty means "use src/generated/deployments.testnet.json".
MARKET_CORE_CONTRACT_ID=
TREASURY_CONTRACT_ID=
RESOLVER_CONTRACT_ID=
REASONING_REGISTRY_CONTRACT_ID=
USDC_CONTRACT_ID=
# Recipient of premium (daily pass) payments, G… or C…. Empty means the
# treasury contract, which makes subscription revenue agent trading capital.
# That is a product decision; see docs/STATUS.md.
PAYMENTS_RECIPIENT=
# Daily pass price in 7-decimal USDC base units (5000000 = 0.50 USDC).
DAILY_PASS_PRICE_RAW=5000000
# ── Server-issued payment intents (#52) ───────────────────────────────────
PAYMENT_INTENT_TTL_SECONDS=900
PAYMENT_INTENT_MAX_OPEN=3
PAYMENT_INTENT_CONFIRM_ENABLED=true
PAYMENT_INTENT_CONFIRM_CRON=*/20 * * * * *
PAYMENT_INTENT_CONFIRM_BATCH=20
PAYMENT_INTENT_MAX_ATTEMPTS=60
PAYMENT_INTENT_RETRY_BASE_MS=5000
PAYMENT_INTENT_RETRY_MAX_MS=300000
PAYMENT_INTENT_LATE_GRACE_SECONDS=120
# ── Agent execution ────────────────────────────────────────────────────────
# dry-run (default): every write is built and simulated, never signed or sent.
# live: writes are signed with AGENT_SECRET_KEY and submitted. Testnet only;
# the server refuses live mode on any other network.
CHAIN_EXECUTION_MODE=dry-run
# WARNING: testnet only. The agent's secret seed (S…). It controls treasury
# trades up to the treasury's caps. Never put a mainnet key here.
AGENT_SECRET_KEY=
# Source-account sequencing (#36). Live writes take a fenced per-account lock
# in Redis before allocating a sequence number. The TTL must cover simulate +
# sign + sendTransaction; the heartbeat renews it while the transaction is in
# flight; waiters give up (with a retryable error) after the wait timeout.
SEQ_LOCK_TTL_MS=45000
SEQ_LOCK_HEARTBEAT_MS=15000
SEQ_LOCK_WAIT_MS=120000
# Write retry policy (#40). Live writes are retried only when the failure is
# provably not applied (transient RPC, bad sequence, insufficient fee, expiry,
# resource/state). Ambiguous outcomes and contract/auth/balance errors are never
# retried. Backoff is jittered exponential, capped by the deadline.
CHAIN_RETRY_MAX_ATTEMPTS=3
CHAIN_RETRY_BASE_MS=250
CHAIN_RETRY_MAX_MS=5000
CHAIN_RETRY_DEADLINE_MS=30000
# Fee bump sponsorship (#38). When an outbox row stays pending past
# FEE_BUMP_AFTER_LEDGERS, its stored inner envelope is wrapped unchanged in a
# fee bump paid by FEE_PAYER_SECRET (testnet only, must differ from
# AGENT_SECRET_KEY and AUTH_SIGNING_SECRET). The inclusion fee escalates by
# FEE_BUMP_MULTIPLIER up to FEE_BUMP_MAX_STROOPS and stops after
# FEE_BUMP_MAX_ATTEMPTS or at the inner transaction's maxTime.
FEE_BUMP_ENABLED=false
# WARNING: testnet only. A distinct funded account's secret seed (S…).
FEE_PAYER_SECRET=
FEE_BUMP_AFTER_LEDGERS=3
FEE_BUMP_MULTIPLIER=2
FEE_BUMP_MAX_STROOPS=10000000
FEE_BUMP_MAX_ATTEMPTS=3
# Resolution spec committed at market creation (signer mode). Empty signers
# means the agent account is the only signer.
RESOLUTION_SIGNERS=
RESOLUTION_THRESHOLD=1
RESOLUTION_DISPUTE_WINDOW_SECS=86400
# ── Price-mode markets (#90) ─────────────────────────────────────────────────
# Reflector (SEP-40) feed registry. JSON keyed by network passphrase → asset
# symbol → feed. Addresses are never hard-coded: every entry carries a `source`
# citation (doc URL or on-chain lookup). Empty disables price mode, so every
# CRYPTO market falls back to signer mode.
# {"Test SDF Network ; September 2015":{"BTC":{"reflector":"C…","asset":{"kind":"other","symbol":"BTC"},"quote":"USD","maxStaleness":900,"source":"https://reflector.network/docs"}}}
REFLECTOR_FEEDS_JSON={}
# resolve_price retries PriceUnavailable/StalePrice until this deadline, then
# logs an ERROR PRICE_RESOLUTION_STUCK for a guardian to void the market.
PRICE_RESOLUTION_MAX_WAIT_SECS=86400
PRICE_RESOLUTION_POLL_MS=300000
# Failure breaker: N chain-write failures within the window pause the agent (#79)
AGENT_FAILURE_THRESHOLD=5
AGENT_FAILURE_WINDOW_MS=1800000
# ── Dynamic Fee Policies (#39) ─────────────────────────────────────────────
# JSON override of per-operation class inclusion fee policies (percentile, floor, cap, budget in stroops).
# Classes: market_create, trade, trace_publish, maintenance.
# Example: FEE_POLICY_JSON={"trade":{"percentile":"p80","floor":"10000","cap":"2000000","budget":"25000000"}}
FEE_POLICY_JSON=
FEE_STATS_CACHE_MS=10000
FEE_STATS_MAX_AGE_MS=60000
# ── Explicit Timebounds & Rebuilds (#42) ───────────────────────────────────
# Transaction timeouts in seconds per operation class
TIMEOUT_MARKET_CREATE_SECONDS=60
TIMEOUT_TRADE_SECONDS=30
TIMEOUT_TRACE_PUBLISH_SECONDS=45
TIMEOUT_MAINTENANCE_SECONDS=30
# Auth entry expiration ledger margin added past the transaction deadline
AUTH_EXPIRY_MARGIN_LEDGERS=12
# Maximum times an expired transaction may be safely rebuilt and resubmitted
MAX_REBUILD_COUNT=2
# ── Channel Accounts (#37) ────────────────────────────────────────────────
# Comma-separated Stellar secret keys (S...) for parallel transaction submission
CHANNEL_SECRET_KEYS=
# Optional path to a file containing channel secret seeds (mode 0600)
CHANNELS_SECRETS_FILE=
# Minimum balance in XLM before a channel account is paused from rotation
CHANNEL_MIN_BALANCE_XLM=5
# Maximum time in milliseconds to wait for a channel lease
CHANNEL_ACQUIRE_TIMEOUT_MS=5000
# Duration in milliseconds of an exclusive channel lease
CHANNEL_LEASE_MS=60000
# Transaction outbox (#35): every live write persists its signed envelope and
# hash before submission; a recovery worker resolves non-terminal rows at boot
# and on this interval (one instance at a time via a Redis lock).
OUTBOX_POLL_MS=5000
# How long a write waits inline for confirmation before returning CHAIN_PENDING
# and leaving resolution (and the completion handler) to the worker.
OUTBOX_INLINE_WAIT_MS=30000
# Contract spec compatibility gate (#34): at boot the backend fetches each
# deployed contract's wasm hash and embedded spec and diffs them against the
# synced bindings. Empty derives from CHAIN_EXECUTION_MODE: live → enforce
# (refuse to start on breaking drift), dry-run → warn. off skips the check.
SPEC_COMPAT_ENFORCE=
# Accept a well-formed inbound X-Request-Id; set false without a trusted proxy.
TRUST_INBOUND_REQUEST_ID=true
# Event indexer (Stellar RPC getEvents poller).
INDEXER_ENABLED=true
INDEXER_POLL_MS=5000
# Health probes (#111): /livez (process only) and /readyz (dependencies).
# HEALTH_CRITICAL: comma list of database,redis,rpc,indexer that fail readiness.
HEALTH_CRITICAL=database,redis
HEALTH_PROBE_TIMEOUT_MS=1500
HEALTH_CACHE_TTL_MS=2000
INDEXER_MAX_LAG_LEDGERS=120
INDEXER_MAX_STALENESS_MS=60000
LIVENESS_MAX_LOOP_DELAY_MS=2000
# Drain + close must fit the 15 s forced-exit window.
SHUTDOWN_DRAIN_MS=5000
# ── LLM providers (market and trace generation) ────────────────────────────
ANTHROPIC_API_KEY=
GEMINI_API_KEY=
# ── IPFS (Pinata) ──────────────────────────────────────────────────────────
PINATA_API_KEY=
PINATA_SECRET_API_KEY=
IPFS_GATEWAY_URL=https://gateway.pinata.cloud/ipfs
# pinata (default) or local (development only; stores bytes in .ipfs-local/).
IPFS_TRANSPORT=pinata
IPFS_LOCAL_DIR=.ipfs-local
# ── Data sources ───────────────────────────────────────────────────────────
NEWSAPI_KEY=
FRED_API_KEY=
# Signal store (#73): re-fetch a source once its last successful fetch is
# older than this; raw provider payloads are kept this many days.
SIGNAL_REFRESH_MINUTES=15
SIGNAL_RAW_RETENTION_DAYS=7
# ── Trader forecaster (#75) ────────────────────────────────────────────────
# The trader's own probability: an LLM estimate (never shown the price) and a
# base-rate model, combined by inverse variance in log-odds and shrunk toward
# 0.5. Samples > 1 take the median and add the spread to the uncertainty.
FORECAST_LLM_SAMPLES=1
FORECAST_SHRINK=0.15
FORECAST_MAX_MARKETS_PER_CYCLE=5
FORECAST_MAX_LLM_CALLS_PER_CYCLE=10
FORECAST_CACHE_TTL_HOURS=6
# ── Semantic dedup (#69) ───────────────────────────────────────────────────
# none keeps the lexical duplicate check. gemini uses GEMINI_API_KEY, openai
# uses OPENAI_API_KEY (and OPENAI_BASE_URL). Needs the pgvector extension.
EMBEDDING_PROVIDER=none
# Defaults: gemini text-embedding-004, openai text-embedding-3-small.
EMBEDDING_MODEL=
# Must equal the markets.questionEmbedding column, vector(768).
EMBEDDING_DIM=768
# Provisional: recalibrate with `npm run calibrate:dedup` on your model.
DEDUP_SIM_THRESHOLD=0.85
DEDUP_DATE_WINDOW_DAYS=3
# ── Calibration (#68) ──────────────────────────────────────────────────────
# Slices with fewer resolved markets return insufficientData.
MIN_CALIBRATION_MARKETS=20
# time | last | first: how a market's weight is split between its traces.
CALIBRATION_WEIGHTING=time
# Shrink the trader's probability toward 0.5 by the fitted factor (needs 50+ markets).
CALIBRATION_SHRINKAGE_ENABLED=false
# ── Build metadata (#66) ───────────────────────────────────────────────────
# Commit recorded in trace provenance. Optional; set by CI or the deploy.
GIT_SHA=
# ── LLM budgets and shared guards (#71) ────────────────────────────────────
# Per UTC day, across every provider and instance (state lives in Redis).
LLM_DAILY_TOKEN_BUDGET=2000000
# USD micro-units (1_000_000 = $1); an estimate from a static price table.
LLM_DAILY_COST_BUDGET_MICROS=20000000
# Percent of both budgets reserved for admin-triggered generation; cron work
# stops at budget - reserve.
LLM_ADMIN_RESERVE_PCT=10
LLM_ANTHROPIC_RPM=12
LLM_GEMINI_RPM=15
LLM_BREAKER_FAILURE_THRESHOLD=3
LLM_BREAKER_OPEN_MS=3600000
# closed: refuse LLM calls when Redis is down (recommended in production).
# open: fall back to a per-process limiter and log a warning.
LLM_REDIS_FAIL_MODE=closed
# ── LLM router (#157) ──────────────────────────────────────────────────────
# OpenAI or any OpenAI-compatible endpoint. The router can use them in a task
# policy even if Anthropic/Gemini are configured.
OPENAI_API_KEY=
OPENAI_BASE_URL=
# Optional JSON policy overriding some/all tasks, e.g.
# {"market_generation":[{"provider":"anthropic","model":"claude-sonnet-4-6",
# "temperature":0.2,"maxTokens":4096,"timeoutMs":60000}]}
# Or a path to a JSON file. Missing tasks keep the built-in default policy.
LLM_POLICY=
LLM_POLICY_FILE=
# ── IPFS content store (#100) ──────────────────────────────────────────────
# Per-object cap and total Postgres budget for verified pinned bytes.
IPFS_CACHE_MAX_OBJECT_BYTES=262144
IPFS_CACHE_BUDGET_BYTES=268435456
# ── Transparency reports (#159) ────────────────────────────────────────────
REPORTS_ENABLED=false
REPORT_CRON=10 0 * * *
# dry-run: pin + persist, never publish on-chain. live: publish with the agent.
REPORT_MODE=dry-run
# URL placed in the report's method.doc field.
REPORT_METHOD_DOC=https://github.com/OracleDesk/oracledesk-backend/blob/main/docs/transparency-reports.md
# ── Treasury admin console (#156) ──────────────────────────────────────────
# Lifetime of a prepared unsigned transaction.
TREASURY_OP_TTL_SECONDS=3600
# Optional stricter backend policy for withdraw operations.
TREASURY_WITHDRAW_MIN_SIGNERS=0
# Trader sizing (#76): share of the treasury's daily and per-market headroom
# (basis points) the trader leaves unused, for races with market creation and
# daily-window rollover between the budget read and the submit.
TREASURY_HEADROOM_SAFETY_BPS=500
# ── Resilience & Timeouts ──────────────────────────────────────────────────
TIMEOUT_RPC_READ_MS=8000
TIMEOUT_RPC_WRITE_MS=45000
TIMEOUT_RPC_EVENTS_MS=15000
TIMEOUT_LLM_MS=60000
TIMEOUT_IPFS_PIN_MS=20000
TIMEOUT_IPFS_FETCH_MS=15000
TIMEOUT_DATASOURCE_MS=10000
# Concurrency bulkheads
BULKHEAD_LLM=2
BULKHEAD_IPFS=4
BULKHEAD_RPC_READ=16
BULKHEAD_RPC_WRITE=4
BULKHEAD_RPC_EVENTS=4
BULKHEAD_DATASOURCE=8
BULKHEAD_QUEUE=32
# Deadlines & caps
HTTP_REQUEST_TIMEOUT_MS=30000
CYCLE_DEADLINE_MS=600000
IPFS_MAX_BYTES=2097152
# ── Trace Audit (Registry Verification) ────────────────────────────────────
TRACE_AUDIT_ENABLED=true
TRACE_AUDIT_CRON=40 */2 * * *
TRACE_AUDIT_RECHECK_HOURS=168
TRACE_AUDIT_MAX_RPC=500
TRACE_AUDIT_MAX_FETCHES=100
TRACE_AUDIT_MAX_BYTES=2097152
# Trace publication queue (#131): pins traces, waits for the market to be
# on-chain, publishes once, and confirms via the indexer's TracePublished event.
TRACE_PUBLISH_ENABLED=true
TRACE_PUBLISH_CRON=*/30 * * * * *
TRACE_PUBLISH_MAX_ATTEMPTS=8
TRACE_CONFIRM_TIMEOUT_MS=600000
# ── Market seed policy (#82) ───────────────────────────────────────────────
# Amounts are 7-decimal base units (10000000 = 1 USDC).
LP_LOSS_BUDGET_RAW=250000000
MM_DAILY_SHARE_BPS=4000
MAX_SEED_FRACTION_BPS=500
MAX_UNRESOLVED_SEEDED_RAW=10000000000
# Base seed per category in USDC; scaled by time to close, never above 2x the LLM's suggestion.
SEED_CATEGORY_BASE_USDC={"FED":300,"ECB":250,"MACRO":200,"CRYPTO":200,"ELECTION":200,"GEOPOLITICAL":150,"POLITICS":150,"SPORTS":120,"ENTERTAINMENT":100}
# ── Market correlations (#80) ──────────────────────────────────────────────
# Price series are resampled onto this grid; a pair needs MIN_OVERLAP intervals
# where both markets traded, and PRIOR_KAPPA is the pseudo-count of the
# shrinkage toward the category prior.
CORRELATION_GRID_SECS=3600
CORRELATION_WINDOW_DAYS=14
CORRELATION_MIN_OVERLAP=12
CORRELATION_PRIOR_KAPPA=20
# ── Market lifecycle reconciler (#83) ──────────────────────────────────────
# Compares markets.status/price/close time/hashes with market-core every ~10
# minutes (one instance, advisory lock), repairs the safe classes, reports the rest.
RECONCILE_ENABLED=true
RECONCILE_MAX_MARKETS=200
RECONCILE_CONCURRENCY=4
RECONCILE_MAX_RPC_CALLS=400
RECONCILE_INDEXER_LAG_LEDGERS=20
# ── Copy Trading ───────────────────────────────────────────────────────────
COPY_TRADE_TTL_MINUTES=30
COPY_TRADE_MAX_PENDING=5
# ── Seed / snapshot (#147) ─────────────────────────────────────────────────
# The seed refuses production and non-local databases. Set to 1 only when you
# intentionally seed a remote development database.
SEED_ALLOW_REMOTE=0
# Base id for seeded on-chain market/trace rows, and the starting ledger.
SEED_ONCHAIN_BASE=1000000
SEED_BASE_LEDGER=6000000
# Optional comma-separated real testnet ids to link (read-only).
SEED_TESTNET_MARKET_IDS=
# Required by scripts/snapshot-export.ts; never commit the value.
SNAPSHOT_SALT=
# ── Event bus and socket fan-out (#93) ─────────────────────────────────────
# Redis Streams between the indexer and the socket.io fan-out. Set false to use
# an in-process bus (one instance only, no Redis needed for events).
EVENT_BUS_ENABLED=true
# Approximate stream cap; chain_events remains the durable history.
EVENT_BUS_MAXLEN=100000
# Defaults to <hostname>-<pid>.
INSTANCE_ID=
# ── Dispute monitor and guardian alerts (#92) ──────────────────────────────
DISPUTE_MONITOR_ENABLED=true
# Confidence needed for an AGREE or DISAGREE verdict.
DISPUTE_AGREE_MIN_CONFIDENCE=0.8
# Markets with at least this much liquidity (USDC) need a cited primary,
# non-news source before the independent review may say AGREE.
DISPUTE_HIGH_VALUE_LIQUIDITY=10000
# The resolver admin account that may call cancel_proposal / guardian_void_market.
# Unset: the admin dispute transaction endpoints return 503 GUARDIAN_NOT_CONFIGURED.
RESOLVER_GUARDIAN_ADDRESS=
# Comma-separated JSON webhooks, signed with ALERT_WEBHOOK_SECRET (HMAC-SHA256,
# header X-OracleDesk-Signature). These URLs contain tokens and are never logged.
ALERT_WEBHOOK_URLS=
ALERT_SLACK_WEBHOOK_URL=
ALERT_WEBHOOK_SECRET=