Skip to content

Development

Runtime is Bun; the language is TypeScript (ESM, strict, moduleResolution: Bundler). Import local modules with the .js extension.

Terminal window
bun install
bun run dev # in-memory backend on :8080

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.

Terminal window
bun test # the backend suite, scanning src/
bun run typecheck # root tsc

Dashboard, which has its own Vitest suite:

Terminal window
cd dashboard
bunx tsc -p tsconfig.app.json --noEmit
bunx vitest run

Both must pass before committing dashboard changes.

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:

Terminal window
export MONGO_URL='mongodb://localhost:27017/?directConnection=true'
export S3_ENDPOINT=S3_ACCESS_KEY_ID=S3_SECRET_ACCESS_KEY=S3_BUCKET=groveback
export MB_TEST_REDIS_URL=redis://localhost:6379
bun test

make mongo, make minio and make redis bring up the containers.

  1. bun run typecheck
  2. bun test — and the relevant gated suites if you touched Mongo, S3 or queue code.
  3. Dashboard typecheck and Vitest, if you touched dashboard/.
  4. Branch off main. Commit only when asked.
  • Every service method that mutates is gated with requirePermission(ctx, '<perm>') from src/authz/permissions.ts — never an ad-hoc role check.
  • New AuthContext literals, including in tests, must set permissions: Set<string>.
  • Throw ValidationError, ForbiddenError, NotFoundError or ConflictError from src/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.

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.

To inspect data in a Kubernetes-hosted Mongo, or point a local backend at it:

Terminal window
make mongo-tunnel # terminal 1 — port-forward, blocks until Ctrl-C
make mongo-tunnel-uri # terminal 2 — the URI rewritten for the tunnel
mongosh "$(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:

Terminal window
MONGO_URL="$(make -s mongo-tunnel-uri)" make dev
Terminal window
cd docs/site
npm install
npm run dev
npm run build

Astro with Starlight. Pages are Markdown under src/content/docs/; the sidebar is declared in astro.config.mjs.