Skip to content
NAVIDIFF DOCUMENTATION

Internals & gotchas

Why it feels instant

A board rebuild costs ~3s: paginated PR comments, the viewed-state GraphQL query, git ls-remote, and the coherence rules. A pin costs 4ms. So mutations never reload the board — the UI updates locally and reverts if the request fails — and those four lookups are memoised per session (server/cache.ts), invalidated by the writes that actually change them. ?fresh=1 forces a real refetch.

board (cold)   3.12s      pin      0.010s
board (warm)   0.002s     delete   0.006s

Things that will bite you if changed carelessly

  • Anchors. A review comment must land on a line that exists on the new side of the current diff. GitHub's review POST is atomic — one bad anchor kills the whole batch. validateAnchors runs first; unanchorable findings go out as one plain PR comment instead.
  • Force-push. Findings store the head SHA they were written against. On mismatch the UI blocks submit until you re-triage; verdicts are cleared because they described other code.
  • Pending drafts. Submitting creates a review with no event, which leaves it PENDING — that is the draft. GitHub allows one per user and answers 422 for a second, so findings are added to the existing draft instead.
  • Sampling honesty. Above 40 files the judge samples. The coverage bar reports read vs judged per directory, so "we looked at everything" is never implied.

Persistence

Two stores, on purpose:

  • Postgres (server/db.ts) holds sessions, files and findings. It's a cache of GitHub plus your findings — safe to reset. On Railway it's the managed Postgres; locally, docker compose up postgres. Tests never touch a real server: they run against pglite, real Postgres compiled to WASM, in-process.
  • events.jsonl (server/events.ts) is the append-only verdict log. It is deliberately not in the DB: it records judgements with no upstream to refetch from, so it lives as its own file (per-line schema version) on the /data volume. Back it up.

Auth

server/auth.ts is Better Auth with the organization plugin. The API is gated by default — a single onBeforeHandle in server/index.ts requires a GitHub session (or the shared NAVIDIFF_TOKEN) for every route except the SPA shell, /api/auth/*, and the diagnostics endpoints. See Deploying for the access model.

Ready to review a real change?

Open Navidiff