Quasar is the canonical Common Lisp control plane and runtime for the Quasar investigation workspace, with the React/Cytoscape UI tracked directly under frontend/ in this monorepo. The UI is a presentation and standalone-web layer; it is not the complete Quasar or StarIntel capability set.
The full deployment is layered:
Quasar UI (`frontend/`, sourced from quasar-ui)
browser UI / graph renderer / standalone subset
|
| versioned commands, projections, capability discovery
v
quasar
canonical Common Lisp control plane and runtime
|
| embedded durable document/graph persistence
v
Tek9 -> LMDB
|
| StarIntel APIs and service adapters
v
starintel-server
persistent ingest / search / routing / RabbitMQ services
|
+-----------------------------+
| |
v v
star-bbpd other actor services
external recon actors collectors / analyzers / tools
star-bbpd, for example, is an external Python/Pykka actor service that consumes RabbitMQ targets, runs reconnaissance tools such as Subfinder, Nmap, Httpx, Katana and DNS workflows, and publishes derived StarIntel documents and relations. Those capabilities are not reimplemented inside the browser UI.
See Architecture, the Tek9 storage ADR, the UI migration ledger, and the capability boundary for the detailed ownership split.
- React, Cytoscape, routing, responsive presentation, editing buffers, hover, menus, and animation remain in the browser.
- Common Lisp owns canonical documents, named graph definitions, committed graph presentation state, revisions, transactions, and the operation journal.
- Tek9 is the canonical local embedded document/graph store and LMDB is the durable engine beneath it. The active Lisp workspace remains a compatibility working cache during Phase 1 of issue #24.
- Cytoscape is a presentation projection. PouchDB is populated only when an explicit CouchDB synchronization needs browser-local staging. Migrated document and graph writes never fall back to PouchDB.
- WebSocket callbacks authenticate and validate requests, then enqueue commands on the Sento control-plane actor. They never mutate workspace state directly.
- CLOG serves the production bundle and issues the browser session token.
- StarLang remains a Common Lisp subsystem and
starlang.loadis excluded from the normal browser capability set. - Runtime and external-service controls discover capabilities rather than
assuming
starintel-server, BBPD, or other actor services are always present.
Node.js 22.12 or newer, SBCL, Quicklisp, LMDB, SQLite, OpenSSL, libffi, and RabbitMQ C libraries are required. The supported Nix shell supplies the native libraries and runtime tools:
nix develop
bash scripts/bootstrap-lisp-deps
npm ci
npm run devscripts/bootstrap-lisp-deps is the canonical source for git-pinned Common Lisp
source dependencies such as CLOG and Tek9. It installs CLOG into Quicklisp
local-projects and keeps Tek9 as the sibling repository
$HOME/starintel/tek9. Set QUASAR_TEK9_PATH to use another workspace root.
The bootstrap refuses to overwrite a dirty existing checkout. CI calls the same
script rather than carrying a second set of dependency pins.
On Linux hosts with Nix available, plain npm run dev and
./scripts/run-production automatically re-enter this repository's pinned Nix
shell so CLOG, Tek9, and the other CFFI systems can resolve their native
libraries. Other platforms use the libraries installed on the host.
One root npm ci installs the complete npm workspace. npm run dev supervises
the Common Lisp control plane, WebSocket endpoint, CLOG host, and Vite without
using npx or downloading undeclared packages. The local endpoints are:
- React/Vite:
http://127.0.0.1:5173 - CLOG production host:
http://127.0.0.1:8080 - control-plane WebSocket:
ws://127.0.0.1:8081
Development builds log uncaught browser errors, rejected promises, and React
component stacks. Open http://127.0.0.1:5173/?debug=1 to additionally trace
WebSocket lifecycle, command IDs, revisions, and pending-request counts without
logging payloads or credentials. Use ?debug=0 to disable that transport trace.
./scripts/run-control-plane starts only the Lisp/CLOG/WebSocket side. The
development scripts explicitly enable unauthenticated local mode; production
does not.
The default durable local workspace path follows XDG:
$XDG_DATA_HOME/quasar/tek9/, or ~/.local/share/quasar/tek9/ when
XDG_DATA_HOME is unset. Tests and deployments can override the path or inject
an existing store.
Run commands from the repository root:
npm run check # format, lint, types, boundaries, static syntax
npm run test # Common Lisp + all frontend unit/integration tests
npm run smoke # real Vite/CLOG/WebSocket command exchange
npm run test:e2e # Playwright against the complete real stack
npm run smoke:production # fresh install, package, serve, route/PWA/security smokePlaywright uses an isolated authorized workspace per test and covers desktop, mobile, real UI mutation, graph membership, reload, and authoritative snapshot restore. The production smoke verifies hashed assets, nested SPA routes, manifest/service worker paths, session and Origin rejection, workspace isolation, capability denial, malformed requests, and message-size limits.
Build and start the packaged server from a fresh dependency state:
nix develop
bash scripts/bootstrap-lisp-deps
./scripts/run-productionThe script runs the root npm ci, builds frontend/dist, creates the
quasar-server executable, and starts it at http://127.0.0.1:8080. Use
./scripts/run-production --build-only when packaging without starting it.
Production serves the application at /; Vite, React Router, CLOG, the PWA
manifest, and service-worker scope use that same base path.
Commands and responses use quasar.control.v1 envelopes with correlated IDs,
stable error codes, and workspace metadata. Successful mutations first apply to
an isolated candidate. One Tek9/LMDB transaction then commits only the affected
document/graph records, workspace revision/settings metadata, graph topology and
adjacency, and one journal entry before the live workspace is replaced,
acknowledged, or broadcast.
StarIntel documents and relation documents are the intelligence records. A
named graph stores membership plus committed positions, viewport, layout, and
groups. Optional graph node/edge records are view records whose document and
endpoint references are validated; they are not a second intelligence corpus.
The all-documents graph projects the full corpus with documentIds: null.
Selection, pan/zoom frames, and editing state remain browser-local.
Implemented durable commands include:
workspace.snapshot,workspace.transactiondocument.list,document.get,document.create,document.update,document.deletegraph.snapshot,graph.workspace.put,graph.workspace.delete,graph.workspace.activategraph.node.*,graph.edge.*- capability-gated
starlang.statusandstarlang.load
Transaction child events have unique operation IDs, a shared transaction ID, one committed revision, stable order, event index, and event count. File imports are fully prevalidated in the browser, then large corpora are sent as ordered, size-bounded chunks below the WebSocket security limit. Lisp still stages those chunks in an isolated heap-resident candidate during this phase; the final import commit is atomic and durable in Tek9. Durable streaming staging and bounded-memory reads/imports remain follow-on work under issue #24.
Actor/research execution and optional browser network integrations have not all moved behind Common Lisp or their owning StarIntel service commands yet. PouchDB remains a CouchDB ingress/egress staging layer used only during explicit synchronization; pulled documents are validated and committed through the control plane before becoming authoritative. Browser settings still support existing local integrations, and settings transfer filters credential fields. These adapters must not be used as fallback authority for document or graph mutations.
Missing backend or external capabilities reduce the advertised capability set; they do not silently become browser implementations with weaker semantics.