Add Unauthorized and PermissionDenied convenience constructors to complete the set of the five most-used error codes (InvalidInput, NotFound, Internal, Unauthorized, PermissionDenied). All roadmap items from v0.9.0 resolved. API committed as stable.
74 lines
5.3 KiB
Markdown
74 lines
5.3 KiB
Markdown
# Changelog
|
|
|
|
All notable changes to this module will be documented in this file.
|
|
|
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
and this module adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
|
## [1.0.0] — 2026-05-08
|
|
|
|
### Added
|
|
|
|
- `Unauthorized(msg string, args ...any) *Err` — convenience constructor for
|
|
`ErrUnauthorized`; completes the set of the five most-used codes alongside
|
|
`InvalidInput`, `NotFound`, `Internal`, and `PermissionDenied`
|
|
- `PermissionDenied(msg string, args ...any) *Err` — convenience constructor for
|
|
`ErrPermissionDenied`
|
|
|
|
### Unchanged
|
|
|
|
All existing API (`Code`, `Err`, `New`, `Wrap`, `InvalidInput`, `NotFound`,
|
|
`Internal`, `WithContext`, `WithError`, `WithPlatformCode`, `ErrorCode`,
|
|
`ErrorContext`, `MarshalJSON`) is API-compatible with v0.10.0.
|
|
|
|
[1.0.0]: https://code.nochebuena.dev/go/xerrors/releases/tag/v1.0.0
|
|
|
|
## [0.10.0] - 2026-03-25
|
|
|
|
### Added
|
|
|
|
- `(*Err).WithPlatformCode(code string) *Err` — chainable builder method to attach a platform-level error code; returns the receiver for chaining
|
|
- `(*Err).PlatformCode() string` — getter that returns the platform code, or an empty string if none was set
|
|
- `platformCode` field in `MarshalJSON` output — serialised as `"platformCode"` and omitted when empty (`omitempty`)
|
|
|
|
### Design Notes
|
|
|
|
- Platform codes operate at the domain/system layer and are intentionally decoupled from the transport-level `Code`. `Code` drives HTTP status mapping and gRPC status codes; `PlatformCode` is a stable semantic identifier for the consuming application (e.g. a frontend performing i18n).
|
|
- Platform codes are **optional**. Errors that do not have a user-actionable meaning (500 internal errors, infrastructure failures, authentication rejections) should not carry one.
|
|
- No existing behaviour changed — `Code`, `Error`, `Unwrap`, `WithContext`, `MarshalJSON` (for errors without a platform code) are all backwards-compatible.
|
|
|
|
[0.10.0]: https://code.nochebuena.dev/go/xerrors/compare/v0.9.0...v0.10.0
|
|
|
|
## [0.9.0] - 2026-03-18
|
|
|
|
### Added
|
|
|
|
- `Code` — string type alias for machine-readable error categories with stable wire values aligned to gRPC canonical status names
|
|
- Thirteen typed `Code` constants: `ErrInvalidInput` (`INVALID_ARGUMENT`), `ErrUnauthorized` (`UNAUTHENTICATED`), `ErrPermissionDenied` (`PERMISSION_DENIED`), `ErrNotFound` (`NOT_FOUND`), `ErrAlreadyExists` (`ALREADY_EXISTS`), `ErrGone` (`GONE`), `ErrPreconditionFailed` (`FAILED_PRECONDITION`), `ErrRateLimited` (`RESOURCE_EXHAUSTED`), `ErrCancelled` (`CANCELLED`), `ErrInternal` (`INTERNAL`), `ErrNotImplemented` (`UNIMPLEMENTED`), `ErrUnavailable` (`UNAVAILABLE`), `ErrDeadlineExceeded` (`DEADLINE_EXCEEDED`)
|
|
- `Code.Description() string` — human-readable description for each code; unknown codes return their raw string value
|
|
- `Err` struct — structured error type carrying a `Code`, human-readable message, optional cause, and optional key-value context fields
|
|
- `New(code Code, message string) *Err` — primary factory constructor; no cause set
|
|
- `Wrap(code Code, message string, err error) *Err` — factory constructor that wraps an existing error as the cause
|
|
- `InvalidInput(msg string, args ...any) *Err` — convenience constructor for `ErrInvalidInput`; message formatted with `fmt.Sprintf`
|
|
- `NotFound(msg string, args ...any) *Err` — convenience constructor for `ErrNotFound`
|
|
- `Internal(msg string, args ...any) *Err` — convenience constructor for `ErrInternal`
|
|
- `(*Err).WithContext(key string, value any) *Err` — chainable builder method to attach a key-value context field; overwrites existing value for the same key
|
|
- `(*Err).WithError(err error) *Err` — chainable builder method to set or replace the cause
|
|
- `(*Err).Error() string` — implements the `error` interface; format: `"CODE: message → cause"`
|
|
- `(*Err).Unwrap() error` — implements `errors.Unwrap`, enabling `errors.Is` and `errors.As` to walk the full cause chain
|
|
- `(*Err).Code() Code` — returns the typed error code
|
|
- `(*Err).Message() string` — returns the human-readable message
|
|
- `(*Err).Fields() map[string]any` — returns a safe shallow copy of all attached context fields; always non-nil
|
|
- `(*Err).Detailed() string` — verbose debug string including code, message, cause, and fields
|
|
- `(*Err).ErrorCode() string` — duck-type bridge satisfying logz's internal `errorWithCode` interface; enables automatic `error_code` log field enrichment without importing logz
|
|
- `(*Err).ErrorContext() map[string]any` — duck-type bridge satisfying logz's internal `errorWithContext` interface; returns the live internal map (read-only)
|
|
- `(*Err).MarshalJSON() ([]byte, error)` — implements `json.Marshaler`; output: `{"code":"...","message":"...","fields":{...}}`
|
|
|
|
### Design Notes
|
|
|
|
- Error codes are string type aliases with stable wire values — safe to serialize, persist, and compare across service versions; HTTP status mapping is deliberately excluded and belongs in the transport layer.
|
|
- `*Err` satisfies `errors.Unwrap`, `json.Marshaler`, and two private duck-type interfaces (`ErrorCode`, `ErrorContext`) that logz inspects via `errors.As`, decoupling the two packages without any import between them.
|
|
- Zero external dependencies — stdlib only (`encoding/json`, `fmt`); Tier 0 of the micro-lib stack.
|
|
|
|
[0.9.0]: https://code.nochebuena.dev/go/xerrors/releases/tag/v0.9.0
|