Commit Graph
3 Commits
Author SHA1 Message Date
jwinterm 4c83e53839 feat(config): effective config via ArcSwap + DB overlay at boot (Stage 2)
Wire the settings overlay into the live config path:
- AppState.config: Config -> Arc<ArcSwap<Config>> (hot-swappable effective config) +
  config_base: Arc<Config> (immutable env-only). New AppState::cfg() accessor; every
  config read goes through it (state.cfg().field), so a runtime-safe operator edit is
  seen on the next request. One Config type, no parallel path.
- Boot (main.rs): load_settings_overlay -> Config::apply_overlay(validate) -> build
  every client/worker/router from the EFFECTIVE config. A persisted overlay that no
  longer validates is ignored (boot env-only + loud log), never bricks. Env-only when
  ADMIN_KEY_INTEGRITY_SECRET is unset.
- Migrated ~59 state.config.X reads to state.cfg().X across api/*; bound guards where a
  reference outlives the statement; integrity_secret returns owned String.
- Test harness builds AppState with ArcSwap + config_base (arc-swap dev-dep).

Behavior-preserving: with no operator_settings rows, effective == env config.
cargo check --all-targets clean; lib tests 256/0.
2026-07-18 06:00:16 -04:00
jwinterm f1872c781c feat(relay): advertise the relay via /capabilities + NIP-05 relay hints
So clients can discover + connect to the relay (and self-adapt when it's off):

- /capabilities: features.nostr_relay + a messaging{ relay_url, write_policy,
  inbound_pow_bits, supported_nips } object, with the same config-presence
  downgrade as chains/nostr_identity (advertised only when enabled AND a URL is
  configured — never advertise a relay clients can't reach). OpenAPI regenerated.
- nip05.rs: /.well-known/nostr.json relay hints are now config-driven — this
  instance's own relay (the user's DM inbox) first when enabled, then the public
  interop relays (damus/nos.lol) so cross-wallet delivery still works. Replaces
  the hardcoded-only default.
2026-07-02 07:00:02 -04:00
jwinterm fb3c547d93 feat: website auth, username + key registration, NIP-05 directory
- api/website.rs: sign-in-with-wallet (dapp connect). challenge bound to origin
  + short TTL; verify is single-use (remove-before-verify, race-safe), expiry-
  checked, signature via Result<(),AppError> verifiers (no oracle), resolves an
  EXISTING user by the proven key's pubkey_hash (never mints identity), mints a
  Platform::Web session.
- api/users.rs: username set/get + by-username lookup (JWT-gated, 409 on taken,
  constant-shape lookup); per-asset key registration bound to the JWT user
  (no spoofable user_id) + public key-directory reads.
- api/nip05.rs: /.well-known/nostr.json directory (username -> nostr_pubkey).
- Wired into api/mod.rs; website+users nested at /api/v1, nip05 at root; all
  paths/schemas registered (openapi.json now 17 endpoints).
- main.rs: periodic GC of expired web challenges (bounds the in-memory store).

Adversarially reviewed (register_key authz + website identity-binding both
hold; no critical/high). 69 tests green. Deferred LOW: per-IP rate-limit on the
website routes lands with the router-assembly unit.
2026-06-22 18:13:47 -04:00