BINADocs
justbina.com
Esc
  • Try “quote gate”, “bulletin”, or “CLEARY_LLM_MODEL”.
ExplanationExplanation · Understanding-oriented

Architecture and the legal record

One process, one append-only log, hash-addressed originals and a SQLite projection you can always rebuild.

BINA is a single Node.js process. It owns the HTTP API, the ingest scheduler and webhook delivery. That simplicity is a design choice: with one writer, the order of events is never in question, and the record a lawyer cites is easy to audit.

#Three stores, two of them authoritative

StorePathRole
Event logdata/events.jsonlAuthoritative. Append-only, fsynced per line. Every counsel event and extraction outcome.
Originalsdata/raw/<sha256>.gzAuthoritative. The fetched bytes of every source, addressed by hash and never deleted.
Derived databasedata/reference.dbA projection. Rebuilt by replaying the log; never cited.

Reports cite hashes, so a reader can fetch the exact bytes a recital was parsed from. Because the database is derived, a corrupted or deleted SQLite file is not data loss — replayRadarEvents folds the log back into the tables at startup.

#Write path

Every state-changing radar route follows the same order:

request → validate → store.recordRadarEvent()  → apply to SQLite → respond
                         (fsync to events.jsonl)

If the process dies between the log write and the SQLite write, the next start replays the event and the derived tables catch up. A torn last line in the log is ignored.

#Request path

console (React, :5173) ──/api──▶ node:http (:8787)
                                    │ Host / Origin guard
                                    │ optional review password
                                    │ optional operator token → attribution
                                    ▼
                              route table (server/index.mjs)
                                    ▼
                        server/radar/*  ←→  SQLite projection

There is no HTTP framework and no ORM. Routes are pathname matches in one handler; SQL is inline in the modules that use it.

#Where the code lives

AreaFiles
Routesserver/index.mjs
Level tableserver/radar/levels.mjs
Validationserver/radar/contract.mjs
Quote verificationserver/radar/text.mjs
Ingestserver/radar/ingest.mjs, sources.mjs
Bulletin / reportserver/radar/bulletin.mjs, report.mjs, export.mjs
Extractionserver/radar/llm.mjs, extract.mjs, dspy.mjs
DMA / cartelserver/radar/dma.mjs, dma-seeds.mjs, cartel.mjs, legal-map.mjs
Signals / researchserver/radar/signals.mjs, claimant-research.mjs, population.mjs
Watchlistserver/radar/watchlist.mjs
Teststest/radar.test.mjs

#Stack

Node ESM (.mjs), node:http, better-sqlite3 (WAL, synchronous = FULL), React 19 console on Vite 6, and Node's built-in test runner. The only model dependency is the Vercel AI SDK, restricted to grounded extraction proposals.

#Deployment shape

Locally, the API binds 127.0.0.1 only. The team review workspace serves the console from Vercel and forwards /api/* to a container with a persistent data volume. Bulk ingest, registry enrichment and webhook delivery run in the local publisher; the hosted workspace answers 501 for those.

#Webhooks

Radar events go outward as HMAC-SHA256-signed webhooks with a 300-second replay window: radar.document.published (a new level 1 or 2 document after an ingest) and radar.watchlist.matched. Targets are SSRF-guarded: no plain http and no private addresses unless CLEARY_WEBHOOK_ALLOW_PRIVATE=1.

BINA · private enforcement radar. Nothing in these docs is legal advice; BINA does not make legal decisions.