Prepares the daemon to be reachable off loopback as part of the
server-client migration (see the approved implementation plan). Today it
trusts any caller that can reach the port; this makes every route except
health checks and login require a bearer session token.
- New frontend.worker.db-worker-node-auth: scrypt-hashed username/password
credential persisted at <root-dir>/db-worker-auth.json (mode 0600),
bootstrapped from LOGSEQ_DAEMON_USERNAME/PASSWORD on first launch since
there's no interactive setup yet. In-memory bearer sessions with
constant-time comparison, a failed-login lockout, and list/revoke by
device. The daemon now refuses to start with no credential configured at
all -- not just when binding beyond loopback -- since without one no
token could ever be issued.
- db_worker_node.cljs: POST /v1/auth/login and GET/DELETE
/v1/auth/sessions; every other route requires Authorization: Bearer
except /healthz, which stays open (readiness polling happens before any
session exists) but now omits :pid/:root-dir from its payload. Adds a
Host-header allowlist ahead of auth to guard against DNS rebinding, and
configurable --host/--port/--allowed-origin/--allowed-host in place of
the hardcoded 127.0.0.1 bind and single CORS origin.
- EventSource can't send custom headers, so /v1/events accepts the bearer
token as a query param instead; persist_db/remote.cljs's events-url
carries it there now (interim until the Fase 4 WebSocket migration).
- Electron always sent :auth-token nil (verified by reading db_worker.cljs
-- one of the plan's open questions). daemon/spawn-server! now seeds a
per-root-dir local device credential
(<root-dir>/db-worker-local-credential.json, reused across restarts) via
LOGSEQ_DAEMON_USERNAME/PASSWORD, and cli/server.cljs logs in once the
spawned or reused daemon is ready, threading the resulting token through
ensure-server! to Electron's runtime config.
Not done: the OCaml CLI (cli/lib/transport.ml) also calls /v1/invoke
directly and will start receiving 401s once this ships -- confirmed with
the user to leave that gap for now rather than touch the OCaml toolchain
in this pass.
Verified with clojure -M:cljs compile app db-worker-node electron (0
warnings) and the full logseq.db-worker.daemon-test,
logseq.cli.server-test, frontend.worker.db-worker-node-test,
electron.db-worker-manager-test suites (113 tests, 480 assertions, 0
failures) plus frontend.state-test and frontend.persist-db.remote-test.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds dev-only counters, with no behavior change, to answer the open
questions from the migration plan before touching the transport:
- frontend.state/get-invoke-stats: per-thread-api-method count/total-ms/
max-ms for every <invoke-db-worker call, to census how many invokes a
typical navigation generates and their latency distribution.
- db-worker-node: per-repo in-flight /v1/invoke counter that logs a new
concurrency high-water mark, to check whether concurrent client writes
actually overlap before deciding on a write queue.
- subs-loader/get-stats: dedup-hit vs new-entry counts for load!, and
batch-size distribution per slot kind at flush, to check whether
in-flight snapshot requests are already deduplicated and whether the
{:children 25 :resources 25} limits are worth raising for network RTT.
Verified with clojure -M:cljs compile app and compile db-worker-node
(0 warnings on both).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Establishes version control for the personal Logseq DB fork before
starting the server-client architecture migration and domain features
described in docs/agent-guide and the approved implementation plan.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>