chore: initial foundation — server skeleton, autodocs, CI

- minimal Axum server exposing GET /health
- OpenAPI contract generated from handlers (gen_openapi -> openapi.json),
  drift-gated in CI so the spec can never silently diverge from the code
- CI: secret-scan + gitleaks, openapi drift gate, fmt/clippy/build/test/doc-test, cargo-deny
- Cargo.lock tracked for reproducible builds; publish=false; pinned toolchain
- README, SECURITY.md, deny.toml, .env.example
This commit is contained in:
jwinterm
2026-06-22 06:18:57 -04:00
commit 143f00701b
17 changed files with 4958 additions and 0 deletions
+104
View File
@@ -0,0 +1,104 @@
# 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=
# ── 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