0010. Standard ServeMux and hand-written DTOs with a contract test
Context
The REST API is described by api/openapi.yaml (OpenAPI 3.1), which is the authoritative contract. The server is written in Go and the web UI in TypeScript.
Since Go 1.22 the standard net/http.ServeMux matches methods and path parameters in its patterns. Go code generators for OpenAPI support version 3.1 only partly. The TypeScript generator openapi-typescript supports 3.1.
Decision
- Routing uses the standard library
ServeMux. Each domain package suppliesapi.Modulevalues withapi.Routeentries (method, pattern, operation ID, permission, authentication mode, handler).internal/httpservermounts all modules under/api/v1and enforces authentication, CSRF and permission centrally, so no package edits a shared router file. - Request and response types (DTOs) are written by hand in
internal/api/dto. A contract test (internal/api/dto/contract_test.go) checks that Go types and OpenAPI schemas match field by field. - The UI generates its TypeScript types from
api/openapi.yamlwithopenapi-typescript.
Consequences
Positive
- Fewer dependencies and no generated Go code to review.
- The access decision of every route is declared next to the route, and a test enumerates all patterns.
- A drift between code and contract fails a test.
Negative
- DTOs and schemas are maintained by hand on both sides; the contract test is the safety net.
- No generated Go server stubs or clients.
Alternatives considered
- A router library: adds a dependency for functions the standard library now provides.
- Go code generators from the OpenAPI document: support for OpenAPI 3.1 is only partial.