Development Workflow
This page is the hands-on tutorial for working in the monorepo day to day: installing, building, running tests, and standing up the full local dev stack. It assumes you’ve read the repo tour and have the workspace laid out at ~/development/opsdna-workspace/opsdna.
The repo is a Bun-workspaces + Turborepo monorepo. All top-level commands are Turbo tasks run from the repo root (build depends on upstream ^build, typecheck on ^build, test on build — see turbo.json), so you rarely need to think about build order: Turbo does, and its cache makes repeat runs near-instant.
The workflow is this scripted because of correctness culture: the same commands you run locally are exactly what CI runs, so a green local run is a real signal, not a vibe (see Verify and CI).
Setup and daily commands
Check your Bun
The repo pins bun@1.3.14 (packageManager in the root package.json).
which bun && bun --version # must be 1.3.14If Homebrew’s /opt/homebrew/bin/bun (1.2.5) is ahead of ~/.bun/bin/bun (1.3.14) on your PATH, fresh worktrees fail with misleading “Cannot find module” errors. Fix your PATH or invoke ~/.bun/bin/bun explicitly.
Install and build
cd ~/development/opsdna-workspace/opsdna
bun install
bun run build
bun run typecheck
bun run testRun a single package’s scripts
bun run --cwd packages/persistence test
bun run --cwd packages/persistence migrate:statusPer-package runs are fine for iteration, but they are not a substitute for the root gates before pushing — cross-package type errors, bundle budgets, and fixture registries only show up at the root (see Verify and CI).
Stand up the local dev stack
bun run dev:stackWhat dev:stack gives you
scripts/dev/local-stack.ts boots three things and wires them together — no AWS, no internet required:
browser ──▶ apps/portal dev server (TanStack Start, dev_local auth)
│ forwards a dev session token
▼
apps/api dev server (Bun.serve, offline auth, port 4399)
│
▼
Docker Postgres 18 (real roles, FORCE RLS, grants, seeded demo org)The offline API ignores the dev token and resolves the seeded demo org → tenant, so the whole loop works with zero credentials. Environment comes from a root .env (copy .env.dev.example); nothing local touches AWS SSM or Secrets Manager. To exercise the production WorkOS JWT path instead, set OPSDNA_AUTH_MODE=workos plus real WORKOS_* env vars.
Useful companions, all from package.json:
bun run dev:api # just the API dev server
bun run dev:tenant-bootstrap # bootstrap a local tenant
bun run dev:db-clean # reset the local database
bun run db:migrate # packages/persistence migrate:latest
bun run db:migrate:statusWorking on schema
Read DATA-MODEL.md first — always. Migrations are forward-only: never edit a migration’s SQL after it has been applied anywhere (CI has an immutability gate, and prod has been burned by checksum drift before). And remember that the default test lane runs on pglite, which silently accepts things real Postgres rejects — schema changes must also pass the real-Postgres integration lane described in Verify and CI.
If you share a checkout with automated agent sessions, they can stash-and-checkout over your uncommitted work without warning. Do real edits in an isolated git worktree.
Next: Verify and CI for the pre-push gate, then Branching and releases for how code reaches staging and prod. Domain background lives in /entity-model.