Skip to content

Quick start

Implemented

Prerequisites

  • Go ≥ 1.25
  • Node.js ≥ 20 + npm / pnpm
  • Docker + Docker Compose
  • psql client
  • jq (recommended)

Five-command setup

# 1. clone
git clone <repo-url> && cd GPUasService

# 2. env
cp doc/operations/local-dev/env.local.example .env.local

# 3. infra (postgres, redis, nats, temporal, keycloak)
make dev-infra

# 4. schema + seed
make db-init && make seed

# 5. API hot-reload via air
make dev-api

Open http://localhost:8443/healthz — should return ok.

Get a dev bearer token

curl -s -X POST http://localhost:8080/realms/gpuaas/protocol/openid-connect/token \
  -d "grant_type=password&client_id=gpuaas-api&client_secret=dev-client-secret&username=dev-user&password=dev123" \
  | jq -r .access_token

Dev users:

User Password Roles
dev-user dev123 user
dev-admin admin123 user, admin

First request

TOKEN=$(./scripts/dev-token.sh dev-user)
curl -s http://localhost:8443/api/v1/me -H "Authorization: Bearer $TOKEN" | jq .

Run all workers

# in separate terminals (or `make dev-up` to start everything at once)
make dev-worker-billing
make dev-worker-provisioning
make dev-worker-notification
make dev-worker-outbox

Frontend

cd packages/web
pnpm install
pnpm dev      # http://localhost:3000

Build the CLI

make build-cli
./bin/gpuaas auth login --personal --username dev-user
./bin/gpuaas catalog list

Run tests

make test                  # unit, no infra
make test-integration      # requires `make dev-infra`
make verify-web            # pnpm typecheck + web tests
make lint                  # golangci-lint

Make a change end-to-end

flowchart LR
    A[1. Pick / create<br/>a task] --> B[2. Read AGENTS.md<br/>+ relevant doc/architecture]
    B --> C[3. Edit OpenAPI<br/>or AsyncAPI first]
    C --> D[4. make codegen]
    D --> E[5. Write _test.go<br/>before service code]
    E --> F[6. Implement service<br/>+ handler]
    F --> G[7. make test +<br/>make test-integration]
    G --> H[8. Definition of Done<br/>checklist]
    H --> I[9. Open PR]

Definition of Done checklist

Every PR must satisfy:

  • openapi.draft.yaml updated if endpoint shape changed
  • asyncapi.draft.yaml updated if event payload changed
  • Service function implemented; domain sentinel errors defined
  • HTTP handler follows the standard shape (corrID + claims at top)
  • Unit tests: happy path + all domain error paths
  • HTTP handler tested via httptest (auth, validation, success)
  • Outbox row written in same DB transaction as domain mutation
  • Audit log row written for privileged mutations
  • middleware.Sanitize applied before any log line echoing request data
  • No policy constant hardcoded — all thresholds from policy.Client
  • go build ./... passes
  • go vet ./... passes
  • make lint passes
  • make test passes (no infra)
  • make test-integration passes (requires infra)
  • make verify-web passes for any packages/web/** change
  • Mutating DB paths that write JSON/audit fields executed against real Postgres in tests

Where to look next