2026-05-29 15:45:12 +00:00
# Changelog — einherjar/core
All notable changes to this module are documented here.
Format follows [Keep a Changelog ](https://keepachangelog.com/en/1.1.0/ ).
This module adheres to [Semantic Versioning ](https://semver.org/spec/v2.0.0.html ).
---
2026-08-08 00:42:17 -06:00
## [1.1.2] — 2026-08-08
Patch — coordinated framework version alignment.
### Changed
- Bumped `contracts` to v1.1.2. No code or API changes.
2026-08-07 23:31:15 -06:00
## [1.1.1] — 2026-08-07
Patch — coordinated framework version alignment.
### Changed
- Bumped `contracts` to v1.1.1 (framework version alignment). No code or API changes.
2026-08-07 18:47:18 -06:00
## [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.New` takes
`logz.Config` ; the `launcher` and `logz` package docs showed `logz.New(logz.Options{…})` ,
which does not compile. Both corrected to `logz.Config` , verified by compiling the example
patterns against the real API.
### Changed
- Bumped `contracts` to v1.1.0 (framework version alignment).
2026-05-29 15:45:12 +00:00
## [1.0.0] — 2026-05-28
### Added
#### `launcher`
- `Launcher` interface — `Append` , `BeforeStart` , `Run` , `Shutdown`
- `New(logger logging.Logger, opts ...Options) Launcher` — constructs the lifecycle
orchestrator; takes `contracts/logging.Logger` (not the concrete `logz` type)
- `Hook` type (`func() error` ) — assembly-phase callback registered via `BeforeStart`
- `Config` struct — `ComponentStopTimeout time.Duration` with `env:"EINHERJAR_COMPONENT_STOP_TIMEOUT" envDefault:"15s"` (`caarlos0/env` syntax)
- Startup banner — printed to stdout before any slog output; disabled via
`EINHERJAR_BANNER=off` or `EINHERJAR_BANNER=false`
- Components accepted as `lifecycle.Component` from `contracts` — not a locally
defined interface; any type that satisfies `contracts/lifecycle.Component` is
directly compatible
#### `logz`
- `Config` struct — `Level slog.Level` , `JSON bool` , `StaticArgs []any` , `Writer io.Writer`
- `Level` and `JSON` carry `env` and `envDefault` tags (`caarlos0/env` syntax); `StaticArgs` and `Writer` are programmatic-only fields without tags
- Env vars: `EINHERJAR_LOG_LEVEL` (default `INFO` ), `EINHERJAR_LOG_JSON` (default `false` )
- `New(cfg Config) logging.Logger` — returns `contracts/logging.Logger` ; the
concrete `slogLogger` struct is unexported
- Error enrichment — when the error passed to `Logger.Error` satisfies
`errs.CodedError` or `errs.ContextualError` (from `contracts/errs` ), the
corresponding `error_code` field and context key-value pairs are automatically
appended to the log record; this replaces the private duck-typed bridge used in
micro-lib's `logz`
- Context helpers — `WithRequestID` , `GetRequestID` , `WithField` , `WithFields`
- `Logger.WithContext(ctx)` — extracts `request_id` and extra fields from context
and attaches them to every subsequent log record
#### `xerrors`
- `Code` type (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)
- `Code.Description()` — human-readable description for each code
- `Err` struct — `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)` and
`var _ errs.ContextualError = (*Err)(nil)` — formalises the duck-type bridge
from micro-lib into an explicit, verifiable contract
#### `valid`
- `Validator` interface — `Struct(v any) error`
- `New(opts ...Option) Validator` — constructs a validator backed by
`go-playground/validator/v10` (backend is hidden; never exposed in the public API)
- `MessageProvider` interface — `Message(field, tag, param string) string`
- `DefaultMessages` — built-in English message provider
- `SpanishMessages` — opt-in Spanish message provider
- `Option` type and `WithMessageProvider(mp MessageProvider) Option`
- `FieldLevel` interface — passed to custom validator functions; exposes `Field() reflect.Value` , `Param() string` , `FieldName() string` ; go-playground backend never visible
- `WithCustomValidator(tag string, fn func(FieldLevel) bool) Option` — registers a custom validation tag at construction time; panics on empty or conflicting tag
- `OverrideProvider(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 `DefaultMessages` and `SpanishMessages` — 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: `ErrInvalidInput` for constraint failures, `ErrInternal` for
non-struct arguments — both returned as `*xerrors.Err`
### Design Notes
1. **Contracts as the source of truth.** `launcher` accepts `lifecycle.Component`
and `logging.Logger` from `contracts` . It does not define its own lifecycle
interface. Any type that satisfies the contracts interface is directly compatible —
no adapters needed.
2. **Duck typing replaced by explicit interfaces.** micro-lib's `logz` detected
enrichable errors via private `errorWithCode` /`errorWithContext` interfaces.
`core/logz` detects them via `contracts/errs.CodedError` and `contracts/errs.ContextualError` .
The decoupling (logz does not import xerrors) is preserved; the contract is now
visible. See [ADR-002 ](docs/adr/ADR-002-logz-contracts-errs.md ).
3. **Complete gRPC error code set.** micro-lib's `xerrors` had 13 codes. `core/xerrors`
adds the three missing gRPC codes (`OUT_OF_RANGE` , `ABORTED` , `DATA_LOSS` ) and
provides a named convenience constructor for every code — `New()` and `Wrap()` are
reserved for edge cases.
4. **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 ](docs/adr/ADR-001-core-module-composition.md ).
5. **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.
---
[1.0.0]: https://code.nochebuena.dev/einherjar/core/releases/tag/v1.0.0