Coordinated framework release. Documentation-only code change plus the shared
version bump.
- core/launcher/doc.go, core/logz/doc.go: logz.New(logz.Options{...}) ->
logz.Config (Options was retired per ADR-003; the constructor takes Config).
- go.mod: contracts -> v1.1.0 (via go get + go mod tidy).
Verified by compiling the example patterns against the real API. Badge -> v1.1.0.
6.7 KiB
Changelog — einherjar/core
All notable changes to this module are documented here. Format follows Keep a Changelog. This module adheres to Semantic Versioning.
[1.1.0] — 2026-08-07
Coordinated framework release. Documentation fix plus the framework version bump.
Fixed
- Package doc examples referenced the retired
logz.Options.logz.Newtakeslogz.Config; thelauncherandlogzpackage docs showedlogz.New(logz.Options{…}), which does not compile. Both corrected tologz.Config, verified by compiling the example patterns against the real API.
Changed
- Bumped
contractsto v1.1.0 (framework version alignment).
1.0.0 — 2026-05-28
Added
launcher
Launcherinterface —Append,BeforeStart,Run,ShutdownNew(logger logging.Logger, opts ...Options) Launcher— constructs the lifecycle orchestrator; takescontracts/logging.Logger(not the concretelogztype)Hooktype (func() error) — assembly-phase callback registered viaBeforeStartConfigstruct —ComponentStopTimeout time.Durationwithenv:"EINHERJAR_COMPONENT_STOP_TIMEOUT" envDefault:"15s"(caarlos0/envsyntax)- Startup banner — printed to stdout before any slog output; disabled via
EINHERJAR_BANNER=offorEINHERJAR_BANNER=false - Components accepted as
lifecycle.Componentfromcontracts— not a locally defined interface; any type that satisfiescontracts/lifecycle.Componentis directly compatible
logz
Configstruct —Level slog.Level,JSON bool,StaticArgs []any,Writer io.WriterLevelandJSONcarryenvandenvDefaulttags (caarlos0/envsyntax);StaticArgsandWriterare programmatic-only fields without tags- Env vars:
EINHERJAR_LOG_LEVEL(defaultINFO),EINHERJAR_LOG_JSON(defaultfalse)
New(cfg Config) logging.Logger— returnscontracts/logging.Logger; the concreteslogLoggerstruct is unexported- Error enrichment — when the error passed to
Logger.Errorsatisfieserrs.CodedErrororerrs.ContextualError(fromcontracts/errs), the correspondingerror_codefield and context key-value pairs are automatically appended to the log record; this replaces the private duck-typed bridge used in micro-lib'slogz - Context helpers —
WithRequestID,GetRequestID,WithField,WithFields Logger.WithContext(ctx)— extractsrequest_idand extra fields from context and attaches them to every subsequent log record
xerrors
Codetype (stable string wire values, gRPC-aligned)- 16 error code constants — complete gRPC canonical set plus
ErrGone(HTTP 410)- New over micro-lib:
ErrOutOfRange(gRPC OUT_OF_RANGE, HTTP 400),ErrAborted(gRPC ABORTED, HTTP 409),ErrDataLoss(gRPC DATA_LOSS, HTTP 500)
- New over micro-lib:
Code.Description()— human-readable description for each codeErrstruct —code,message,err(cause),fields(context),platformCode- Base constructors:
New(code, message),Wrap(code, message, err) - 16 convenience constructors (one per code):
InvalidInput,OutOfRange,Unauthorized,PermissionDenied,NotFound,AlreadyExists,Aborted,Gone,PreconditionFailed,RateLimited,Cancelled,Internal,DataLoss,NotImplemented,Unavailable,DeadlineExceeded - Builder methods:
WithContext,WithError,WithPlatformCode - Accessors:
Code(),Message(),Fields(),PlatformCode(),Detailed() - Standard interfaces:
error,Unwrap,json.Marshaler - Compile-time assertions:
var _ errs.CodedError = (*Err)(nil)andvar _ errs.ContextualError = (*Err)(nil)— formalises the duck-type bridge from micro-lib into an explicit, verifiable contract
valid
Validatorinterface —Struct(v any) errorNew(opts ...Option) Validator— constructs a validator backed bygo-playground/validator/v10(backend is hidden; never exposed in the public API)MessageProviderinterface —Message(field, tag, param string) stringDefaultMessages— built-in English message providerSpanishMessages— opt-in Spanish message providerOptiontype andWithMessageProvider(mp MessageProvider) OptionFieldLevelinterface — passed to custom validator functions; exposesField() reflect.Value,Param() string,FieldName() string; go-playground backend never visibleWithCustomValidator(tag string, fn func(FieldLevel) bool) Option— registers a custom validation tag at construction time; panics on empty or conflicting tagOverrideProvider(handlers map[string]func(field, param string) string, base MessageProvider) MessageProvider— composes a tag→message handler map with a fallback; use for custom tag messages without re-implementing built-ins- Full built-in tag coverage in
DefaultMessagesandSpanishMessages— all go-playground/validator tags have specific messages (fields, network, strings, format, comparisons, other; ~150 tags total) - Field names in error context prefer the json struct tag, falling back to the Go field name
- Error codes:
ErrInvalidInputfor constraint failures,ErrInternalfor non-struct arguments — both returned as*xerrors.Err
Design Notes
-
Contracts as the source of truth.
launcheracceptslifecycle.Componentandlogging.Loggerfromcontracts. It does not define its own lifecycle interface. Any type that satisfies the contracts interface is directly compatible — no adapters needed. -
Duck typing replaced by explicit interfaces. micro-lib's
logzdetected enrichable errors via privateerrorWithCode/errorWithContextinterfaces.core/logzdetects them viacontracts/errs.CodedErrorandcontracts/errs.ContextualError. The decoupling (logz does not import xerrors) is preserved; the contract is now visible. See ADR-002. -
Complete gRPC error code set. micro-lib's
xerrorshad 13 codes.core/xerrorsadds the three missing gRPC codes (OUT_OF_RANGE,ABORTED,DATA_LOSS) and provides a named convenience constructor for every code —New()andWrap()are reserved for edge cases. -
One module, four sub-packages. The consolidation eliminates four-way version coordination for a set of packages that always ship and upgrade together. See ADR-001.
-
Startup banner. The launcher prints an ASCII art banner to stdout before any structured log output. It is disabled via
EINHERJAR_BANNER=off, not via code changes, so production deployments can suppress it without modifying the service.