Development
Runtime is Bun; the language is TypeScript (ESM, strict, moduleResolution: Bundler).
Import local modules with the .js extension.
bun installbun run dev # in-memory backend on :8080Make targets
Section titled “Make targets”make help lists everything.
| Target | What |
|---|---|
make dev |
In-memory server, no database — data dies on restart. |
make dev-multi |
The same, serving every control-plane project. |
make dev-mongo |
Server backed by a local replica-set Mongo container. |
make dev-full |
Backend hot-reload plus the dashboard with Vite HMR. |
make dev-vector |
Everything: Mongo, embeddings, MinIO, Redis, backend, dashboard. |
make dev-tools |
Inspection UIs — Bull Board, RedisInsight, Mongo Express. |
make check |
Typecheck plus the unit suite. |
make test-mongo |
The full suite including Mongo integration tests. |
make dashboard |
Build the dashboard SPA. |
Supporting containers each have -stop (keeps data) and -rm (removes the volume) variants:
mongo, embeddings, minio, redis.
bun test # the backend suite, scanning src/bun run typecheck # root tscDashboard, which has its own Vitest suite:
cd dashboardbunx tsc -p tsconfig.app.json --noEmitbunx vitest runBoth must pass before committing dashboard changes.
Gated suites
Section titled “Gated suites”Several suites skip silently unless their environment is present, which is the easiest way to believe you ran everything when you did not. To run the whole thing you need all three at once:
export MONGO_URL='mongodb://localhost:27017/?directConnection=true'export S3_ENDPOINT=… S3_ACCESS_KEY_ID=… S3_SECRET_ACCESS_KEY=… S3_BUCKET=grovebackexport MB_TEST_REDIS_URL=redis://localhost:6379bun testmake mongo, make minio and make redis bring up the containers.
Before committing
Section titled “Before committing”bun run typecheckbun test— and the relevant gated suites if you touched Mongo, S3 or queue code.- Dashboard typecheck and Vitest, if you touched
dashboard/. - Branch off
main. Commit only when asked.
Repository conventions
Section titled “Repository conventions”- Every service method that mutates is gated with
requirePermission(ctx, '<perm>')fromsrc/authz/permissions.ts— never an ad-hoc role check. - New
AuthContextliterals, including in tests, must setpermissions: Set<string>. - Throw
ValidationError,ForbiddenError,NotFoundErrororConflictErrorfromsrc/core/errors.ts; the HTTP layer maps them to{ error: { code, message } }. - Keep new code in the surrounding style — same naming, comment density and idiom.
dashboard/dist/is git-ignored and built in Docker and CI. Never hand-edit it.
Documentation in the repo
Section titled “Documentation in the repo”Each module carries an ARCHITECTURE.md — read it before editing that module, and update it
when the module’s files or invariants change. At the root, PROGRESS.md holds the current work
state and DECISIONS.md is an append-only decision log.
Tunneling to a cluster Mongo
Section titled “Tunneling to a cluster Mongo”To inspect data in a Kubernetes-hosted Mongo, or point a local backend at it:
make mongo-tunnel # terminal 1 — port-forward, blocks until Ctrl-Cmake mongo-tunnel-uri # terminal 2 — the URI rewritten for the tunnelmongosh "$(make -s mongo-tunnel-uri)"The tunnel uses local port 27018 deliberately, since 27017 is usually the local dev Mongo.
Two notes. The URI carries directConnection=true, which matters: Mongo is a replica-set
member, and without it the driver tries to resolve the set’s internal hostnames — unreachable
through a tunnel. And mongo-tunnel-uri prints the password to your terminal only; credentials
are never fetched into the repo.
To run a local backend against that data:
MONGO_URL="$(make -s mongo-tunnel-uri)" make devThis documentation site
Section titled “This documentation site”cd docs/sitenpm installnpm run devnpm run buildAstro with Starlight. Pages are Markdown under src/content/docs/; the sidebar is declared in
astro.config.mjs.