Documentation
¶
Overview ¶
Package contract defines Gombit's Huma DTO conventions, the D10 success and error envelopes, and draft §41 application error category mapping.
Public API routes are Huma-typed handlers. Request and response shapes come from Go structs and Huma validation tags — there is no bespoke Bind layer.
Success:
{"data": ...}
{"data": ..., "meta": {"page": 1, "per_page": 20, "total": 125}}
Use contract.DataMeta[T, PageMeta] (or another concrete meta type) so OpenAPI emits a real meta schema. Validation failures (Huma Install path):
{"error":{"code":"validation_error","message":"...","fields":{...},"request_id":"..."}}
Application errors (return contract.NotFound / New / ... via WithContext):
{"error":{"code":"not_found","message":"...","request_id":"..."}}
OpenAPI 3.1 is served at /openapi.json. Interactive docs are at /docs when enabled. Use OpenAPIJSON / WriteOpenAPI to persist the live spec.
See docs/contract.md and docs/openapi.md.
Index ¶
- Constants
- func CodeFor(cat Category) string
- func FieldsFromErrors(errs ...error) map[string][]string
- func HumaConfig(title, version string) huma.Config
- func HumaConfigFor(title, version string, docsEnabled bool) huma.Config
- func Install(opts InstallOptions)
- func OpenAPIJSON(api huma.API) ([]byte, error)
- func StatusFor(cat Category) int
- func WriteOpenAPI(path string, api huma.API) error
- func WriteOpenAPIFile(path string, spec []byte) error
- type Category
- type Data
- type DataMeta
- type ErrorBody
- type ErrorEnvelope
- func Authentication(message string) *ErrorEnvelope
- func Authorization(message string) *ErrorEnvelope
- func Conflict(message string) *ErrorEnvelope
- func DependencyUnavailable(message string) *ErrorEnvelope
- func Internal(message string) *ErrorEnvelope
- func New(cat Category, message string) *ErrorEnvelope
- func NotFound(message string) *ErrorEnvelope
- func RateLimited(message string) *ErrorEnvelope
- func Validation(message string, fields map[string][]string) *ErrorEnvelope
- func WithContext(ctx context.Context, err *ErrorEnvelope) *ErrorEnvelope
- type InstallOptions
- type PageMeta
Constants ¶
const ( // OpenAPIPath is the Huma OpenAPI prefix. Clients fetch /openapi.json. OpenAPIPath = "/openapi" // DocsPath is the FastAPI-style interactive docs UI. DocsPath = "/docs" )
const CodeValidationError = "validation_error"
CodeValidationError is the stable D10 code for request validation failures.
Variables ¶
This section is empty.
Functions ¶
func CodeFor ¶
CodeFor returns the stable D10 error.code for a category. Validation keeps the M3-1 / D10 name "validation_error"; other categories use the category string. Unknown categories map to "internal".
func FieldsFromErrors ¶
FieldsFromErrors maps Huma validation detail errors into D10 field errors.
Body locations lose the leading "body." prefix so JSON field names match the request body. Query, path, and header locations keep their prefixes.
func HumaConfig ¶
HumaConfig returns the default Huma configuration for a Gombit app.
Interactive docs are enabled at /docs (Swagger UI). The schema browser stays disabled. Pass docsEnabled=false to omit the docs route (production default).
func HumaConfigFor ¶
HumaConfigFor returns Huma configuration with docs explicitly enabled or not.
func Install ¶
func Install(opts InstallOptions)
Install replaces Huma's default RFC 9457 Problem Details errors with the D10 envelope. It is safe to call more than once; only the first call applies.
Install only classifies errors built through Huma's NewError hooks (request validation). Application errors from New / NotFound / etc. set status and code via StatusFor / CodeFor and are not reclassified.
func OpenAPIJSON ¶
OpenAPIJSON marshals the Huma-generated OpenAPI 3.1 document.
func StatusFor ¶
StatusFor returns the HTTP status for a §41 category. Unknown categories map to 500 Internal Server Error.
func WriteOpenAPI ¶
WriteOpenAPI writes the Huma-generated OpenAPI document to path.
func WriteOpenAPIFile ¶
WriteOpenAPIFile writes a pre-marshaled OpenAPI document to path.
Types ¶
type Category ¶
type Category string
Category is a draft §41 framework error category. Transport adapters map categories to HTTP status codes via StatusFor; they do not leak into service layer return types as raw status integers.
const ( CategoryValidation Category = "validation" CategoryAuthentication Category = "authentication" CategoryAuthorization Category = "authorization" CategoryNotFound Category = "not_found" CategoryConflict Category = "conflict" CategoryRateLimited Category = "rate_limited" CategoryInternal Category = "internal" )
type Data ¶
type Data[T any] struct { Data T `json:"data"` }
Data is the D10 success envelope without meta: {"data": ...}.
type DataMeta ¶
DataMeta is the D10 success envelope with typed meta: {"data": ..., "meta": ...}.
Use a concrete meta type so OpenAPI emits a real schema (not empty object). Prefer a pointer meta value so omitempty drops absent meta:
contract.DataMeta[[]Widget, PageMeta]{Data: items, Meta: &contract.PageMeta{...}}
A non-nil zero PageMeta still serializes (omitempty does not treat structs as empty).
type ErrorBody ¶
type ErrorBody struct {
Code string `json:"code"`
Message string `json:"message"`
Fields map[string][]string `json:"fields,omitempty"`
RequestID string `json:"request_id,omitempty"`
}
ErrorBody is the D10 error object nested under "error".
type ErrorEnvelope ¶
type ErrorEnvelope struct {
Body ErrorBody `json:"error"`
// contains filtered or unexported fields
}
ErrorEnvelope is the D10 error response body and a huma.StatusError.
It intentionally does not implement huma.ContentTypeFilter so responses keep Content-Type application/json instead of application/problem+json.
func Authentication ¶
func Authentication(message string) *ErrorEnvelope
Authentication returns an authentication category error (HTTP 401). Wrap with WithContext in handlers to attach request_id.
func Authorization ¶
func Authorization(message string) *ErrorEnvelope
Authorization returns an authorization category error (HTTP 403). Wrap with WithContext in handlers to attach request_id.
func Conflict ¶
func Conflict(message string) *ErrorEnvelope
Conflict returns a conflict category error (HTTP 409). Wrap with WithContext in handlers to attach request_id.
func DependencyUnavailable ¶
func DependencyUnavailable(message string) *ErrorEnvelope
DependencyUnavailable returns a dependency_unavailable error (HTTP 503). Wrap with WithContext in handlers to attach request_id.
func Internal ¶
func Internal(message string) *ErrorEnvelope
Internal returns an internal category error (HTTP 500). Wrap with WithContext in handlers to attach request_id.
func New ¶
func New(cat Category, message string) *ErrorEnvelope
New builds a D10 ErrorEnvelope from a §41 category and message.
Callers should wrap with WithContext so request_id is populated:
return nil, contract.WithContext(ctx, contract.New(contract.CategoryNotFound, "missing"))
func NotFound ¶
func NotFound(message string) *ErrorEnvelope
NotFound returns a not_found category error (HTTP 404). Wrap with WithContext in handlers to attach request_id.
func RateLimited ¶
func RateLimited(message string) *ErrorEnvelope
RateLimited returns a rate_limited category error (HTTP 429). Wrap with WithContext in handlers to attach request_id.
func Validation ¶
func Validation(message string, fields map[string][]string) *ErrorEnvelope
Validation returns a validation category error (HTTP 422, code validation_error). Wrap with WithContext in handlers to attach request_id.
func WithContext ¶
func WithContext(ctx context.Context, err *ErrorEnvelope) *ErrorEnvelope
WithContext returns err with request_id filled from Install's RequestID reader when available. Application handlers should wrap category errors:
return nil, contract.WithContext(ctx, contract.NotFound("missing"))
func (*ErrorEnvelope) Error ¶
func (e *ErrorEnvelope) Error() string
Error satisfies the error interface.
func (*ErrorEnvelope) GetStatus ¶
func (e *ErrorEnvelope) GetStatus() int
GetStatus returns the HTTP status for this error.
func (*ErrorEnvelope) WithFields ¶
func (e *ErrorEnvelope) WithFields(fields map[string][]string) *ErrorEnvelope
WithFields returns a shallow copy with D10 fields set. The error code stays the category code (not forced to validation_error).
func (*ErrorEnvelope) WithRequestID ¶
func (e *ErrorEnvelope) WithRequestID(requestID string) *ErrorEnvelope
WithRequestID returns a shallow copy with request_id set (for tests/helpers).
type InstallOptions ¶
type InstallOptions struct {
// RequestID reads the active request ID from a request context.
RequestID func(context.Context) string
}
InstallOptions configures Huma error installation.
type PageMeta ¶
type PageMeta struct {
Page int `json:"page"`
PerPage int `json:"per_page"`
Total int64 `json:"total"`
}
PageMeta is the conventional pagination meta object for collection responses. It is the v0.1 typed default for list endpoints; other meta shapes can use the second type parameter on DataMeta when needed.