Quick start¶
Implemented
Prerequisites¶
- Go ≥ 1.25
- Node.js ≥ 20 +
npm/pnpm - Docker + Docker Compose
psqlclientjq(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¶
Build the CLI¶
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.yamlupdated if endpoint shape changed -
asyncapi.draft.yamlupdated 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.Sanitizeapplied before any log line echoing request data - No policy constant hardcoded — all thresholds from
policy.Client -
go build ./...passes -
go vet ./...passes -
make lintpasses -
make testpasses (no infra) -
make test-integrationpasses (requires infra) -
make verify-webpasses for anypackages/web/**change - Mutating DB paths that write JSON/audit fields executed against real Postgres in tests