Repository navigation
v1.5.4
The clone-and-host release. Four independent verification passes ran against this tree β a clean-clone install test, a full Docker hosting pass, an adversarial review of every change since 1.5.3, and a docs-vs-reality audit β and everything they found is fixed here. The result: git clone, one command, and a running instance, with an API key, a self-hosted OpenAI-compatible endpoint, or no AI at all.
The quick start works again
npm install on a fresh clone failed outright β an ERESOLVE conflict between eslint 10 and eslint-plugin-jsx-a11y (whose latest release declares peers only through eslint 9). The Dockerfile and CI already passed --legacy-peer-deps; humans following the README had no such luck, so the very first documented command exited 1. A committed .npmrc now makes npm install and npm ci work exactly as the docs write them. Verified: clone β install β boot β /healthz β clean SIGTERM, on the released tree.
The README also gains the fastest path, which existed all along but was never mentioned: CI publishes multi-arch images to ghcr.io/arvarik/contrack, so one docker run hosts the app with no toolchain and no build.
The app runs the moment it starts β keys optional
- With one API key (Gemini, OpenAI, or Anthropic): everything works, models chosen automatically.
- With a self-hosted OpenAI-compatible endpoint (Ollama, vLLM, LM Studio): connect it in Settings β AI β no key anywhere. Fixed in 1.5.3, verified end-to-end again for this release from a fresh clone with zero keys.
- With nothing: contact management and semantic search run on the built-in local embedding model, offline.
Startup no longer cries wolf about it: an OpenAI-only install used to boot to "GEMINI_API_KEY is not configured!" because only the AI_PROVIDER key was checked. Boot now names the providers actually configured β and with none, says what to do instead of implying something is broken.
Hosting fixes
- The seed scripts wrote to the wrong database on any
DATA_DIRinstall (Docker included) β both hardcodedcurator.dbin the working directory while the server reads$DATA_DIR/curator.db. They now resolve the path exactly as the server does. - The configuration guide told Docker users to mount the project root β advice that would shadow the built app inside the image. It now documents the real contract: mount
/app/data, which holds the database, uploads, backups, and the embedding-model cache, and is the entire persistence story. - Seeding docs promised a destructive ~50-contact import.
npm run seedinserts one example contact, skips a non-empty database, and deletes nothing β ever. Corrected everywhere; demo data lives atnpm run db:seed. docker-compose.ymlforwarded only eight environment variables, so documented settings likeBACKUP_KEEPwere silently ignored on the Docker path. The optional tuning variables now pass through.
The ops surface is documented where users look
Everything shipped in 1.5.3's stability work now appears in the guides, not just the changelog: a new "Running as a Service" section covers GET /healthz (pre-auth by design β health checks hold no secrets), the Docker HEALTHCHECK, SIGTERM drain semantics (safe docker stop), the 65-second keep-alive and why it prevents proxy 502s, and exactly what the production CSP blocks. The API reference gains /healthz, the 1 MB body limit with its single 50 MB import exemption, the true pre-auth surface, and fourteen endpoints that previously existed only in code.
Also: APP_URL was documented and read by nothing β removed; DISABLE_BACKGROUND_JOBS and NODE_ENV were the reverse β documented. Both wrong README test counts fixed (the suite is 518 tests across 38 files, keys never required). Vite's per-boot config warning and Docker's false "secrets" build warning are gone.
Verified
Docker pass on this tree, all proven with evidence: image builds clean, boots with zero env vars, HEALTHCHECK reaches healthy, CSP + security headers serve the bundle, 413 enforcement works, docker stop completes in 0.2 s with exit 0 and a WAL-checkpointed database, data survives recreation, gated mode keeps /healthz open while /api returns 401. Fresh-clone pass: install, 518/518 tests, lint clean, zero-config boot, stub-endpoint AI round-trip. Adversarial review: CSP audited against every client asset and connection, body limits audited against every route, the AI-module split verified drift-free (13/13 exports, 25/25 call sites).
Full changelog: v1.5.3...v1.5.4