Canonical reference for required and optional tools, platform notes, and configuration. For step-by-step setup, see the Contributor Guide.
| Tool | Version | Pinned In | Purpose |
|---|---|---|---|
| Node.js | 26.2.0 | .tool-versions (package.json engines allows ^24 || ^26) |
Angular CLI, build tooling |
| Bun | 1.3.14 | .tool-versions, package.json engines (>=1.3.14) |
Package manager, script runner |
| Go | 1.26.5 | .tool-versions (go.mod requires >=1.26.3) |
Backend compilation |
| Git | any | — | Source control, build metadata |
| Make | any | — | Build orchestration |
.tool-versions is the single source of truth for exact versions —
these numbers drift out of sync with it easily (this table itself was
stale until 2026-07-25), so if this table and .tool-versions ever
disagree, trust the file, not this page, and fix the page.
.tool-versions is the single source of truth for runtime versions.
| Manager | Install | Usage |
|---|---|---|
| mise (recommended) | brew install mise |
mise install |
| asdf | brew install asdf |
asdf install |
| Manual | Per-tool installers | Match versions in .tool-versions |
build/check-versions.cjs validates versions before tests run (pretest hook).
| Tool | Purpose | Install | When Needed |
|---|---|---|---|
| Docker / Podman / OrbStack / Colima | Run database containers | Per-tool | Backend dev with PostgreSQL |
| OpenSSL | Generate dev certs and encryption keys | Included on macOS/Linux | First-time setup |
zip |
Release packaging | brew install zip |
make release |
swag |
OpenAPI doc generation | go install github.com/swaggo/swag/cmd/swag@latest |
API docs |
quarto |
Render docs/ to standalone PDF/epub booklets |
brew install --cask quarto |
make build booklets — also needs Chrome (for mermaid diagrams), which Quarto auto-detects on dev machines and CI |
golangci-lint |
Go meta-linter (staticcheck, errcheck, unused, ineffassign) | golangci-lint.run | make lint, make check — lint hard-fails without it |
gosec |
Go security scanner | go install github.com/securego/gosec/v2/cmd/gosec@latest |
make audit backend, make audit tests |
trivy |
Vulnerability + misconfig scanner | aquasecurity/trivy | make audit backend, make audit tree |
govulncheck |
Go vuln database | go install golang.org/x/vuln/cmd/govulncheck@latest |
make audit backend, make audit summary |
zizmor |
GitHub Actions workflow SAST | brew install zizmor |
make audit actions |
osv-scanner |
Multi-lockfile dependency scanner | brew install osv-scanner |
make audit packages, make audit licenses |
gitleaks |
Secret scanner | brew install gitleaks |
make audit secrets, make audit history |
modrot |
Archived/deprecated dependency scanner | go install github.com/norman-abramovitz/modrot@latest |
make audit modrot (needs gh auth) |
semgrep |
Pattern-based SAST | brew install semgrep |
make audit semgrep (manual, needs network) |
codeql |
Deep SAST (Go + JS/TS databases) | codeql-action releases | make audit codeql (manual — CI already runs this canonically; local run is a pre-push spot-check) |
sarif-tools (sarif) |
Summarize SARIF files | pip install sarif-tools |
make audit sarif |
gh |
GitHub CLI | cli.github.com | make deps dependabot, make audit upload, make audit actions (optional, for authenticated rate limits) |
| Playwright browser binaries | E2E test runner (the @playwright/test package itself comes via bun install) |
bunx playwright install chromium (add firefox/webkit for E2E_BROWSERS=firefox/webkit/all) |
make test e2e, make check e2e |
| Command | Purpose |
|---|---|
make audit |
Default scanner set: frontend + website + backend + actions + packages + secrets |
make audit frontend |
bun audit (npm advisory DB), root workspace |
make audit website |
bun audit (npm advisory DB), website/ workspace (tools/stb isn't covered — pre-release) |
make audit backend |
gosec + trivy + govulncheck on both Go modules (src/jetstream, src/jetstream/api) |
make audit actions |
zizmor SAST over .github/workflows/; ZIZMOR_FLAGS="--persona=auditor" enables the strict rule set |
make audit packages |
osv-scanner over every lockfile and go.mod in one pass |
make audit secrets |
gitleaks scan of the working tree |
make audit summary |
High/moderate/low totals only — fast triage |
make audit tests |
gosec including _test.go files, plus a #nosec suppression report |
make audit tree |
trivy over the whole repo — covers the Dockerfiles, helm chart, and manifests under deploy/ |
make audit history |
gitleaks over the full git history (~14k commits) |
make audit licenses |
osv-scanner dependency license report |
make audit modrot |
modrot archived/deprecated dependency scan (needs gh auth) |
make audit semgrep |
semgrep SAST via semgrep ci — uses your logged-in account's policy and dashboard if you've run semgrep login, falls back to community rules otherwise. SARIF to dist/semgrep.sarif |
make audit codeql |
Local CodeQL SAST (Go + JS/TS) — manual pre-push mirror of what .github/workflows/codeql.yml runs on every push/PR. SARIF to dist/codeql-{go,js}.sarif |
make audit sarif |
sarif-tools summary across every dist/*.sarif file, local only |
make audit upload |
Push dist/*.sarif to GitHub code scanning; skips codeql-*.sarif since CI already uploads those canonically. Needs push access to the repo |
make outdated |
List outdated direct deps in both stacks |
make outdated frontend |
bun outdated |
make outdated backend |
go list -m -u all (filtered to upgradable) |
make deps dependabot |
List open dependency PRs (requires gh auth) |
make audit runs the six default scanners only (frontend, website, backend,
actions, packages, secrets). The rest are deliberately kept off the default
path:
tests— gosec findings inside_test.gofiles are advisory (test code doesn't ship), so they would add triage noise to every default run. Run it when auditing test hygiene or reviewing#nosecsuppressions.tree— scans the entire repository instead ofsrc/jetstream. It exists for the deployment surface (deploy/Dockerfiles, helm chart, CF manifests) which the backend scan doesn't reach. It is slower than the default set and its misconfig findings change rarely — run it when touching anything underdeploy/or before a release.history— walks all ~14k commits (roughly 15 seconds, vs instant for the working-tree scan). Historical findings are almost entirely pre-2020 test fixtures; this is a forensic tool, not an everyday guard. The defaultsecretsmode already catches anything you are about to commit.licenses— a compliance report, not a vulnerability source. Nothing in it is actionable on a normal development day.modrot— needsgh auth(GitHub GraphQL) + network, so it's a standalone extra rather than something everymake auditrun should depend on.semgrep,codeql— both need extra tooling (asemgrepaccount login, thecodeqlCLI + query packs) and are meant to run manually on the build machine, not on every audit invocation. CodeQL in particular already runs in CI on every push/PR — the local mode exists so you can see findings before pushing, not to replace CI.sarif,upload— these consume the other scanners'dist/*.sarifoutput; they're only meaningful after running one of the SARIF-emitting modes, so they don't belong in a default sweep either.
All audit recipes are report-only (|| true): they never fail the build, so
scanner exit codes are informational. The lint/test gates are where failures
block.
Stratos does not prescribe a container runtime. Any OCI-compatible runtime
works with the project's compose.yml:
| Runtime | Platform | Notes |
|---|---|---|
| Docker Desktop | macOS, Linux, Windows | Most common, licensing applies to large orgs |
| Podman | macOS, Linux, Windows | Rootless, daemonless, no licensing cost |
| OrbStack | macOS | Lightweight, fast, Docker-compatible |
| Colima | macOS, Linux | Minimal Docker-compatible on Lima VMs |
Stratos connects to external SQL databases. It does not bundle a database server.
| Backend | DATABASE_PROVIDER |
Local Dev | Production |
|---|---|---|---|
| SQLite | sqlite |
Default, zero setup | Not recommended |
| PostgreSQL | pgsql |
Via container | Recommended |
| MySQL / MariaDB | mysql |
Via container | Supported |
PostgreSQL 14 and later is supported — the versions the upstream
lib/pq driver tests against.
Any PostgreSQL-compatible (CockroachDB, Aurora, AlloyDB) or MySQL-compatible (MariaDB, Aurora MySQL, PlanetScale) service works with existing drivers.
| Variable | Purpose | Default |
|---|---|---|
DATABASE_PROVIDER |
Backend selection | sqlite |
DB_HOST |
Hostname | localhost |
DB_PORT |
Port | 5432 (pgsql), 3306 (mysql) |
DB_USER |
Username | — |
DB_PASSWORD |
Password | — |
DB_DATABASE_NAME |
Database name | stratos |
DB_SSL_MODE |
TLS mode | disable |
Backend reads configuration from a 5-tier lookup chain (first match wins):
- Database config store — runtime settings saved after initial setup
- Environment variables —
export KEY=valueor in container env - CF User-Provided Service — Cloud Foundry deployments only
.envfile — KEY=VALUE format in working directory/etc/secretsdirectory — one file per key (Kubernetes pattern)
All configuration keys work from any tier. Environment variables always override file-based settings.
This is app runtime config (ENCRYPTION_KEY below encrypts the app's own
database config store) — a different concern from E2E test credentials
(secrets.yaml), which have their own zero-plaintext encrypt/decrypt
workflow. See Secrets Management for that.
| Variable | Purpose | Required |
|---|---|---|
ENCRYPTION_KEY |
256-bit hex encryption key | Yes |
CONSOLE_PROXY_TLS_ADDRESS |
Listen address | No (default :5443) |
AUTH_ENDPOINT_TYPE |
local or remote |
No (default remote) |
SESSION_STORE_SECRET |
Cookie encryption | No (has default) |
LOG_LEVEL |
debug, info, warn, error |
No |
SKIP_SSL_VALIDATION |
Skip TLS checks for CF endpoints | No |
See src/jetstream/config.example for all available settings with descriptions.
| Service | Default | Override Variable |
|---|---|---|
| Frontend dev server | 5440 | FRONTEND_PORT |
| Backend (jetstream) | 5443 | BACKEND_PORT |
| E2E frontend | 5540 | Playwright config |
| E2E backend | 5543 | Playwright config |
No IDE is prescribed. Stratos works with any editor that supports LSP.
| Editor | Recommended Extensions |
|---|---|
| VS Code | Angular Language Service, Go (gopls) |
| WebStorm / GoLand | Built-in Angular + Go support |
| Neovim | angular-language-server + gopls via LSP |
Angular Language Service is included in devDependencies for template type-checking in any IDE.
| OS | Arch | Notes |
|---|---|---|
| macOS | arm64 (Apple Silicon) | Primary dev platform |
| macOS | amd64 (Intel) | Supported |
| Linux | amd64 | CI and dev |
| Linux | arm64 | Supported |
| OS | Arch | Use case |
|---|---|---|
| linux | amd64 | Cloud Foundry, Docker, most servers |
| linux | arm64 | ARM servers, Graviton |
| darwin | amd64 | macOS Intel |
| darwin | arm64 | macOS Apple Silicon |
| windows | amd64 | Windows servers |
| windows | arm64 | Windows ARM |
Platform detection uses uname -s | tr '[:upper:]' '[:lower:]' for OS and
normalizes architecture (x86_64 → amd64, aarch64 → arm64) to match
Go's GOOS/GOARCH conventions. Override with PLATFORM=os/arch.
Cross-compilation is host-arch-independent for the standard build
(CGO_ENABLED=0, no C cross-compiler involved) — an arm64 machine builds
any of the six combinations above exactly as an amd64 machine does, and
vice versa. See Development in build-and-packaging.md for how PLATFORM
interacts with make build vs make stage.
- Xcode Command Line Tools required (
xcode-select --install) for Make and Git - GNU Make 3.81+ required (ships with Xcode CLI tools)
opensslfrom Homebrew recommended over LibreSSL for cert generation- Apple Silicon (arm64) is the native build target; use
PLATFORM=linux/amd64for CF release builds
build-essentialpackage provides Make and GCC- SQLite no longer needs GCC/cgo — the backend uses the pure-Go
ncruces/go-sqlite3driver, so standardCGO_ENABLED=0builds work
GitHub Actions workflows:
| Workflow | File | Trigger |
|---|---|---|
| Frontend tests | .github/workflows/frontend_tests.yml |
Push/PR to develop/main |
| Backend tests | .github/workflows/backend_tests.yml |
Push/PR to develop/main |
| Release + all-in-one image | .github/workflows/release.yml |
Version tag |
CI workflows use outdated tool versions. Tracked in FWT-840.
| Workflow | Component | CI Version | Should Be |
|---|---|---|---|
| frontend_tests | Node.js | 16 | 24 |
| backend_tests | Go | 1.21.0 | 1.24.2 |
| pr | Node.js | 24 | 24 (correct) |
| pr | Go | 1.21 | 1.24.2 |
| release | Node.js | 24 | 24 (correct) |
| release | Go | 1.21 | 1.24.2 |
| All | Package manager | npm | bun |
make release cf packages the app for CF deployment but does not build.
The backend binary must be pre-built for the target Linux platform.
| Command | Output | Purpose |
|---|---|---|
make build |
dist/bin/jetstream-{os}-{arch} (all platforms) |
Frontend + all backend platforms |
make build backend PLATFORM=linux/amd64 |
dist/bin/jetstream |
Single backend platform |
make dev backend |
dist/bin/jetstream |
Host platform only (development) |
# 1. Build and package in one command (cf modifier forces linux/amd64):
make build release cf
# Or step by step:
make build cf
make release cf
# 3. Deploy
cf target -o system -s stratos
cf push -f dist/cf-package/manifest.yml -p dist/stratos-cf-<version>.zipmake release cf validates that dist/bin/jetstream is a Linux ELF binary
before packaging. If it's a macOS or Windows binary, the packaging fails with
a clear error.
make build cf produces a Linux binary natively. Or make build release cf to
build and package in one step.
The cf modifier automatically sets PLATFORM=linux/amd64:
make build release cf # linux/amd64 (default)
make build release cf PLATFORM=linux/arm64 # ARM CF deployments- Contributing Guide — step-by-step workflow
- Build and Packaging — Make targets, release process
- Secrets Management — encryption key handling