spec_to_rest
Gochi

PostgreSQL

Edit on GitHub

Reference for the go-chi-postgres deployment target

Last updated:

This page documents what the compiler emits when a spec is compiled against the go-chi-postgres target. It is the concrete companion to the target-agnostic Code Generation Pipeline research doc.

The canonical source of truth is the emitter at codegen/go/EmitGo.scala, which renders the Handlebars templates under codegen/resources/templates/go/chi/. Running

sbt "cli/run compile --framework chi --db postgres --ignore-verify --out /tmp/out fixtures/spec/url_shortener.spec"

produces the tree this page describes. If this page and the emitter disagree, the emitter wins; file an issue or PR to correct the doc. The full byte-level shape of the output for url_shortener.spec is checked in under fixtures/golden/codegen/go/chi/postgres/url_shortener/ and asserted by EmitGoTest.

At a glance

AspectValue
LanguageGo 1.22
Frameworkchi v5 (net/http)
ORM / driverBun (uptrace/bun) + bun/driver/pgdriver
Migration toolgolang-migrate (raw SQL under migrations/)
DatabasePostgreSQL 16+
Validationgo-playground/validator/v10 struct tags
Configcaarlos0/env/v11 (env vars)
HTTP servernet/http w/ chi middleware (RequestID, Logger, Recoverer, …)
Logginglog/slog (JSON handler)

Project layout

.
├── go.mod
├── cmd/server/main.go              # entrypoint, chi router wiring
├── internal/
│   ├── config/config.go            # env-driven Config struct
│   ├── database/database.go        # bun.NewDB connect + ping
│   ├── models/{entity}.go          # struct + create/read DTOs + ErrorResponse
│   ├── handlers/
│   │   ├── common.go               # writeJSON / writeError helpers
│   │   └── {entity_plural}.go      # chi handler funcs (1 per operation)
│   └── services/
│       ├── common.go               # ErrNotFound sentinel
│       └── {entity}.go             # Bun query-builder business logic
├── migrations/
│   ├── 001_initial_schema.up.sql
│   └── 001_initial_schema.down.sql
├── Dockerfile                      # multi-stage build → distroless
├── docker-compose.yml              # app + db services
├── Makefile                        # build / run / test / migrate-up
├── .env.example
├── .gitignore
├── .dockerignore
├── README.md
├── .github/workflows/ci.yml
├── tests/health_test.go
└── openapi.yaml                    # target-agnostic OpenAPI 3.1

Type mapping

Spec typeGo typePostgreSQL column
StringstringTEXT
Intint64BIGINT
Floatfloat64DOUBLE PRECISION
BoolboolBOOLEAN
DateTimetime.TimeTIMESTAMPTZ
Datetime.TimeDATE
UUIDuuid.UUIDUUID
Decimaldecimal.DecimalNUMERIC
Bytes[]byteBYTEA
Moneyint64BIGINT
Option[T]*Tnullable column
Set[T][]TJSONB
Seq[T][]TJSONB

The mapping is in profile/TypeMap.scala.

Operation routing

RouteKind.classify (target-agnostic) maps each operation to one of create, read, list, delete, redirect, other. The Go emitter renders the matching handler/service template. Operations whose body shape does not match the entity's field set route to other and emit a stub the user fills in (the spec contract is preserved by the verify gate, so the stub still has a known interface).

Dafny → Go integration

When compile --framework chi --db postgres --with-synthesis is invoked and the verified-body cache is populated, the compiler:

  1. Routes through dafny translate -go (via TargetLanguage.Go).
  2. Lays the produced Go files under internal/dafnykernel/.
  3. Emits operation bindings of the form dafnykernel.{OperationName}.

The kernel is only emitted when at least one operation is classified as LLM_SYNTHESIS; otherwise the Go project is purely CRUD/Bun.

CI gate

.github/workflows/go-build.yml is a {postgres, sqlite, mysql} matrix. On every PR that touches the Go templates, profile, emitter, or the shared migration renderer it re-runs compile --framework chi --db <dialect>, then go mod tidy && go vet && go build against the emitted project and a golang-migrate round-trip (up → down -all → up) against a real postgres:17 / mysql:8.4 service (SQLite uses a file) — so the emitted migrations/*.sql is proven to apply and reverse on every supported dialect, not just that the Go code compiles.

Test generation

Conformance / property / stateful test generation (--with-tests) is available for go-chi-* on every dialect (postgres, sqlite, mysql), emitted in the target's own language: go test + rapid property tests, not Python. testgen plugs the Go renderers into the shared Backend.scala seam (ExprBackend / StrategyBackend / HarnessTemplates); the same spec-derived derivation engine feeds the Python (fastapi) path, which stays the byte-identical differential oracle (#278, #279, #280; closes #265).

--with-tests emits under tests/ (Go package tests, build-tagged conformance): behavioral (<svc>_behavioral_test.go, positive-ensures under rapid.Check), stateful (<svc>_stateful_test.go, random operation sequences asserting invariants per step), and structural-lite (<svc>_structural_test.go, fuzzes every non-stub operation with type-valid input and asserts no 5xx — schemathesis's core check minus full schema validation; fail-loud stubs are honest-skipped exactly as the Python schemathesis renderer excludes them, recorded in tests/_testgen_skips.json). The /__test_admin__/* reset/state/seed router is a spec-derived internal/testadmin/admin_conformance.go (build tag conformance); the normal build links an always-present !conformance no-op stub, so the plain go build matrix is unaffected and the test-admin code never ships in production binaries.

Run it against a server built with the conformance tag:

go build -tags conformance -o server ./cmd/server
ENABLE_TEST_ADMIN=1 ./server &
bash tests/run_conformance.sh smoke      # or: go test -tags conformance ./tests/...

go-chi -> conformance suite runs this in CI (go-build.yml) across all four fixtures × postgres/sqlite, mirroring the python-build.yml pattern. (The spec-to-rest test CLI wrapper still drives only the Python runner; see CLI Reference.)

On this page