Development setup
Toolchain
Section titled “Toolchain”- Rust stable, MSRV 1.94 (
rust-toolchain.tomlpins it) - Bun 1.4 or later: package manager, JS runtime and test runner. Node is not needed.
- Turborepo runs every task in both languages from one graph (installed by
bun install). - kind for the end-to-end tests, Helm for the chart.
-
Clone and set up.
setupinstalls the Rust toolchain components, the JS dependencies and cargo-nextest.Terminal window git clone https://github.com/Teamtem-dev/kuben.gitcd kubenbun run setup -
Run the API and the console. The API listens on
:8080in dev mode (pretty logs, insecure cookie, in-memory SQLite); Vite serves the console on:5173and proxies/apito it.Terminal window bun run devSign in as
admin@kuben.local; the dev password is printed at start. -
Before pushing, run what CI runs: rustfmt, clippy with
-D warnings, tests, doctests, the TypeScript checks, Biome, the generated-file drift check and the web build with its size budget.Terminal window bun run ci -
If you touched controllers or the API, also run the end-to-end suite against a kind cluster:
Terminal window kind create cluster --config deploy/kind.yamlbun run e2e
Repository layout
Section titled “Repository layout”Directorycrates/
Directorykuben/ the binary: CLI, serve, bootstrap, telemetry
- …
Directorykuben-api/ Axum routes, auth, audit, OpenAPI, embedded console
- …
Directorykuben-platform/ controllers, projections, leader election, supervisor
- …
Directorykuben-store/ sqlx repositories for SQLite and PostgreSQL, migrations
- …
Directorykuben-crd/ the kuben.dev types and the CRD generator
- …
Directorykuben-core/ config, ids, authz, errors shared by all crates
- …
Directoryapps/
Directoryconsole/ React 19 + TanStack, Tailwind v4 (embedded into the binary)
- …
Directorysite/ this website: Astro + Starlight
- …
Directorypackages/
Directoryapi-client/ openapi.json and the generated TypeScript types
- …
Directorycharts/kuben/ the Helm chart and generated CRDs
- …
Directoryscripts/ ci.sh, e2e.sh, budgets, scans, change detection
- …
Directorydocs/ ADRs and design documents
- …
Everyday commands
Section titled “Everyday commands”| Command | Does |
|---|---|
bun run build |
debug builds of the Rust entrypoints and the web bundle |
bun run check |
cargo check and tsc |
bun run lint |
clippy (-D warnings, pedantic) and Biome |
bun run format |
rustfmt and Biome fixes |
bun run test |
cargo-nextest and bun test, plus doctests |
bun run gen |
regenerate openapi.json, schema.d.ts and the CRDs |
bun run drift |
regenerate and fail on any difference (what CI does) |
bun turbo run test --filter=kuben-store |
one package |
bun turbo run kuben#size |
release build with the embedded console, checked against the 26 MiB budget |
- Dependencies. Rust versions live only in
[workspace.dependencies]; JS versions only in the rootpackage.jsoncatalog (packages writecatalog:). Every new crate must passcargo deny check. - Generated files are committed. After changing API types or CRDs, run
bun run genand commitpackages/api-client/openapi.json,packages/api-client/src/schema.d.tsandcharts/kuben/crds/. CI fails on drift. - Every handler has a unique
operation_idin#[utoipa::path]; the TypeScript types and the audit log are keyed by it. - CRD types stay structural: no internally tagged enums; use one-of structs with optional fields (
Source { image, git }). A test guards this. - Budgets are gates: binary ≤ 26 MiB, image ≤ 30 MiB, console JS ≤ 200 kB and CSS ≤ 25 kB (brotli). Raising a budget needs a written reason in the pull request.
- Commits follow Conventional Commits (
feat(api): …,fix(controller): …). Label pull requests (feature,bug,security,breaking); release notes are grouped by label. - Every migration exists for both backends with the same file name; a test enforces parity.
The review checklist
Section titled “The review checklist”CONTRIBUTING.md lists 18 invariants, each closing a class of bug found in the system Kuben replaces: opaque sessions and no JWT in the browser, Argon2id only, no injection through user strings, no global mutable cluster context, informers instead of polling, readiness only after sync, embedded migrations under a lock, one source of truth per datum, server-side apply with conditions, and more. Reviewers check the ones a change touches. Read it before opening a pull request.