This is the practical kickoff. It turns the design in docs/ into an ordered list of tasks you can hand to Claude Code one at a time. Don't try to build everything at once — each task is scoped to be a single focused Claude Code session with clear acceptance criteria.
# 1. Generate the empty monorepo tree
./scaffold.sh
# 2. Set up env (dev values only)
cp .env.example .env
# 3. Start dependencies (you'll need Docker)
docker compose -f infra/compose/deps.yml up -d # created in Task 2 belowOpen Claude Code in the repo root so it reads CLAUDE.md automatically. That file already encodes the hard rules — Claude Code will follow them.
- Work one task at a time, in order. Each builds on the previous.
- Paste the task's prompt, let it work, then verify the acceptance criteria before moving on.
- After each task: review the diff, run the tests, commit. Small commits.
- If Claude Code drifts from the architecture, point it back to the relevant doc (
docs/02-architecture.md,docs/04-security.md, etc.).
Prompt to Claude Code:
Set up the root monorepo tooling:
package.jsonwith pnpm workspaces,pnpm-workspace.yaml,turbo.json, roottsconfigbase inpackages/tsconfig, Biome (or ESLint+Prettier) config, andpyproject.tomlwith uv workspaces forlibs/. Add root scripts:build,test,lint,typecheckwired through Turborepo. Don't add app code yet.
Acceptance: pnpm install succeeds; pnpm turbo run lint runs (even with nothing to lint); the Python workspace resolves with uv sync.
Prompt:
Implement the skeletons of
packages/types(export shared TS types + a few base Zod schemas likeOrgId,UserId,Permission),packages/config(typed env loading validated with Zod), andpackages/security(Argon2id hash/verify wrappers via@node-rs/argon2, JWT verify helpers viajose, and anassertOrgAccess(jwtOrgId, resourceOrgId)guard). Write unit tests forpackages/security— including a test proving a wrongorg_idis rejected.
Acceptance: packages/security has passing unit tests; hashing uses Argon2id; no plaintext anywhere; @nebula/config fails loudly on a missing required env var.
Prompt:
Create
infra/compose/deps.ymlwith Postgres 16, Redis 7, MinIO, NATS (JetStream), Meilisearch, Keycloak, and Traefik. Use the variables from.env.example. Add healthchecks and a shared network. Createinfra/compose/dev.ymlthat extends deps and will later add our services. Document the ports ininfra/README.md.
Acceptance: docker compose -f infra/compose/deps.yml up -d brings all dependencies up healthy; MinIO console, Keycloak admin, and Meilisearch are reachable locally.
Prompt:
Build
core/nucleo-auth(NestJS): a reusable module that validates a Keycloak-issued JWT, extractssub,org_id,roles,scopes, and exposes a guard. It must NEVER readorg_idfrom the request body/headers. Buildcore/nucleo-events(a thin NATS client wrapper for publish/subscribe with typed payloads from@nebula/types). Buildcore/nucleo-audit(append-only audit log persisted to Postgres). Hexagonal structure. Unit + integration tests with Testcontainers.
Acceptance: a request with a forged org_id in the body is ignored in favor of the JWT's; audit entries are append-only; integration tests pass against real Postgres/NATS via Testcontainers.
Prompt:
Configure Keycloak as Atlas: a
nebularealm, annebula-appsOIDC client, organizations modeled as Keycloak groups (or realm-per-tenant — propose the trade-off first), base rolesowner/admin/member/guest, Argon2id as the password hashing algorithm, and TOTP MFA enabled. Build a thinapps/atlas/bff(NestJS) exposing register/login/refresh/invite endpoints that delegate to Keycloak, plus org membership management. Write the cross-tenant isolation test scaffold here (it will be reused everywhere).
Acceptance: a user can register, log in (with MFA), and receive a JWT containing org_id; passwords are Argon2id in Keycloak; two orgs exist and are distinct. See docs/services/atlas.md.
Prompt:
Establish the multi-tenant Postgres convention: a migration toolchain (e.g., node-pg-migrate or Prisma migrate — propose one), a base pattern where every tenant-scoped table has
org_idand Row-Level Security policies, and a helper inpackages/config/corethat sets the currentorg_idper request/connection. Write an integration test proving org A cannot read org B's rows even with a crafted query through the app layer.
Acceptance: RLS is enforced; the cross-tenant isolation integration test passes; the pattern is documented for reuse by future services.
Prompt:
Add
infra/observability/with Prometheus, Grafana, Loki, and Tempo configs, wired intoinfra/compose/dev.yml. Add a shared NestJS module (and Python equivalent inlibs/nebula_common) that exposes/healthand/metricsand emits OpenTelemetry traces with a propagatedtrace_id. Makenucleo-auth/nucleo-audituse it.
Acceptance: Grafana shows metrics from at least one Núcleo service; a request produces a trace visible in Tempo; every service has /health and /metrics.
Prompt:
Create
.github/workflows/ci.yml: install (pnpm+uv cached), lint, typecheck, run affected tests via Turborepo, and a security stage (gitleaks,pnpm audit/pip-audit, Semgrep or CodeQL, Trivy on built images). Block the merge if the cross-tenant isolation tests or security stage fail.
Acceptance: opening a PR runs the full pipeline; a committed fake secret is caught by gitleaks; the isolation tests run in CI.
Do not start Vega/Helios until all of these are true:
-
docker compose -f infra/compose/dev.yml upworks on a clean machine. - A user registers → logs in with MFA → gets a valid JWT with
org_id. - Two organizations are isolated in Postgres (RLS), proven by a passing test.
- Argon2id confirmed; zero passwords in logs.
- Every Núcleo service exposes
/healthand/metrics; traces visible in Tempo. - CI pipeline (lint, typecheck, tests, security) is green on
main.
When the checklist passes, move to F1 (Vega + Helios). The first task there:
Build
services/vega-storageperdocs/services/vega.md: file upload (multipart via MinIO presigned URLs), folders, versioning, and sharing withviewer/editor/ownerpermissions enforced throughnucleo-policy. Encryption at rest with a per-org key. Include the mandatory cross-tenant isolation test for files.
Then apps/vega (Next.js UI) and apps/helios (dashboard). Follow docs/05-roadmap.md from there.
- Keep
CLAUDE.mdupdated as conventions solidify — it's the steering wheel. - Prefer asking Claude Code to write the test first for anything touching permissions or tenancy.
- For each new service, tell it to read
docs/06-folder-structure.mdand follow the hexagonal convention. - When integrating a third party (Keycloak, OnlyOffice, Stalwart, LiveKit), ask it to isolate the integration behind an interface so it's swappable (the ADRs require an exit plan).