mirror of
https://github.com/Such-Software/smirk-backend-core.git
synced 2026-10-17 15:31:38 +02:00
How far back a wallet may ask THIS instance to scan on import is an operator decision — the backfill cost lands on its LWS/node. Add WALLET_RESTORE_POLICY (create-only | bounded | unlimited, default bounded) + WALLET_MAX_RESTORE_DEPTH_DAYS, advertise it via /capabilities so the wallet adapts its import UX, and enforce it at the scan path (xmr/wow register, grin scan): a too-deep start_height is a ValidationError naming the bound, never the caller's value. Create needs no check (no tip lookup). Self-sovereignty stays intact at the ecosystem level — a deeper restore means self-hosting or a looser operator. Fail-closed config validation; a unit test per policy; OpenAPI drift clean.
117 lines
5.5 KiB
Bash
117 lines
5.5 KiB
Bash
# smirk-backend-core — example environment.
|
|
#
|
|
# Copy to `.env` and fill in for your deployment. NEVER commit a real `.env`.
|
|
# Generate secrets with: openssl rand -hex 32
|
|
|
|
# ── Server ────────────────────────────────────────────────────────────────
|
|
SERVER_HOST=0.0.0.0
|
|
SERVER_PORT=8080
|
|
# Public absolute API base URL. REQUIRED when admin/erasure features are enabled:
|
|
# it is the canonical value the NIP-98 `u` tag is verified against (never the
|
|
# request Host header). Boot fails if unset while those features are on.
|
|
PUBLIC_API_URL=https://backend.example.org/api/v1
|
|
ENVIRONMENT=development
|
|
# Stable per-node identifier. Bound into signed admin/erasure actions so a proof
|
|
# captured against one node cannot be replayed across a load-balanced fleet.
|
|
INSTANCE_ID=
|
|
|
|
# ── Database ──────────────────────────────────────────────────────────────
|
|
DATABASE_URL=postgres://user:password@127.0.0.1:5432/smirk
|
|
|
|
# ── Auth (JWT) ────────────────────────────────────────────────────────────
|
|
JWT_SECRET=
|
|
JWT_EXPIRY_HOURS=24
|
|
|
|
# ── Proof-of-work signup gate (ALTCHA v2) ─────────────────────────────────
|
|
ALTCHA_HMAC_KEY=
|
|
POW_REQUIRED=false
|
|
ALTCHA_COST=100000
|
|
|
|
# ── Bitcoin ───────────────────────────────────────────────────────────────
|
|
BTC_NETWORK=mainnet
|
|
BTC_USE_LOCAL_NODE=false
|
|
BTC_RPC_URL=http://127.0.0.1:8332
|
|
BTC_RPC_USER=bitcoinrpc
|
|
BTC_RPC_PASS=
|
|
BTC_ELECTRUM_URL=
|
|
BTC_ELECTRUM_FALLBACKS=
|
|
|
|
# ── Litecoin ──────────────────────────────────────────────────────────────
|
|
LTC_NETWORK=mainnet
|
|
LTC_USE_LOCAL_NODE=false
|
|
LTC_RPC_URL=http://127.0.0.1:9332
|
|
LTC_RPC_USER=litecoinrpc
|
|
LTC_RPC_PASS=
|
|
LTC_ELECTRUM_URL=
|
|
LTC_ELECTRUM_FALLBACKS=
|
|
|
|
# ── Monero (daemon + light wallet server) ─────────────────────────────────
|
|
XMR_LWS_URL=http://127.0.0.1:8443
|
|
XMR_LWS_ADMIN_URL=http://127.0.0.1:9443
|
|
XMR_LWS_ADMIN_KEY=
|
|
XMR_DAEMON_URL=http://127.0.0.1:18081
|
|
|
|
# ── Wownero (daemon + light wallet server) ────────────────────────────────
|
|
WOW_LWS_URL=http://127.0.0.1:18443
|
|
WOW_LWS_ADMIN_URL=http://127.0.0.1:19443
|
|
WOW_LWS_ADMIN_KEY=
|
|
WOW_DAEMON_URL=http://127.0.0.1:34568
|
|
|
|
# ── Grin (wallet owner/foreign API + node API) ────────────────────────────
|
|
GRIN_OWNER_API_URL=http://127.0.0.1:3420/v3/owner
|
|
GRIN_OWNER_API_SECRET=
|
|
GRIN_WALLET_PASSWORD=
|
|
GRIN_FOREIGN_API_URL=http://127.0.0.1:3415/v2/foreign
|
|
GRIN_NODE_API_URL=http://127.0.0.1:3413/v2/owner
|
|
GRIN_NODE_API_USER=grin
|
|
GRIN_NODE_API_PASS=
|
|
GRIN_NODE_FOREIGN_API_URL=http://127.0.0.1:3413/v2/foreign
|
|
GRIN_NODE_FOREIGN_API_SECRET=
|
|
|
|
# ── Wallet restore (import) policy ────────────────────────────────────────
|
|
# How far back a wallet may ask THIS instance to scan on import. The backfill
|
|
# cost lands on your LWS/node, so it is your call; it is advertised via
|
|
# /capabilities so the wallet adapts its import UX. Self-sovereignty is
|
|
# preserved — a user needing a deeper restore runs their own instance or picks
|
|
# an operator with a looser policy.
|
|
# create-only — new wallets only (scan starts at the tip)
|
|
# bounded — restore up to WALLET_MAX_RESTORE_DEPTH_DAYS behind the tip
|
|
# unlimited — any restore height (the natural choice for self-hosting)
|
|
WALLET_RESTORE_POLICY=bounded
|
|
WALLET_MAX_RESTORE_DEPTH_DAYS=365
|
|
|
|
# ── Feature flags (each feature ships in the open core, toggled per deployment) ──
|
|
# The wallet client reads GET /api/v1/capabilities and greys out disabled features.
|
|
FEATURE_PRICES=true
|
|
PRICES_PROVIDER=coingecko
|
|
PRICES_FETCH_INTERVAL_SECS=300
|
|
# Tips are parked for the conditional-transfer redesign; off until that lands.
|
|
FEATURE_TIPS=false
|
|
|
|
# ── Admin surface (see docs; default posture is loopback/Tor) ──────────────
|
|
# Admin auth is "Sign in with Smirk": only admin PUBLIC keys are stored here,
|
|
# never a seed or private key. The allowlist is mutated CLI/loopback-only in v1.
|
|
ADMIN_ENABLED=false
|
|
ADMIN_BIND=127.0.0.1:8081
|
|
ADMIN_JWT_SECRET=
|
|
# Integrity MAC secret protecting admin/setup trust anchors against DB tampering.
|
|
# Losing this locks out admin — back it up (see docs/operations).
|
|
ADMIN_KEY_INTEGRITY_SECRET=
|
|
ADMIN_MAX_KEYS=8
|
|
ADMIN_PENDING_KEY_TTL_DAYS=7
|
|
|
|
# ── Public landing page (OFF by default; full + per-field tunable when on) ──
|
|
PUBLIC_LANDING_ENABLED=false
|
|
PUBLIC_EXPOSE_FEATURES=false
|
|
PUBLIC_EXPOSE_UPTIME=false
|
|
PUBLIC_STATS_ENABLED=false
|
|
PUBLIC_STATS_CACHE_HOURS=24
|
|
|
|
# ── Data retention / erasure ──────────────────────────────────────────────
|
|
ERASURE_ENABLED=false
|
|
ERASURE_PURGE_LOGIN_EVENTS=true
|
|
ERASURE_EXPORT_PER_DAY=3
|
|
# Log retention (auto-deletion); 0 = keep indefinitely.
|
|
RETENTION_LOGIN_EVENTS_DAYS=90
|
|
RETENTION_AUDIT_DAYS=365
|