feat: add WithPlatformCode for domain-level error identity (v0.10.0) (#2)

feat: add WithPlatformCode for domain-level error identity

Adds an optional PlatformCode field to *Err, decoupled from the
transport-level Code. Code drives HTTP/gRPC status mapping;
PlatformCode is a stable domain identifier for consuming applications
(e.g. a frontend performing i18n) to map errors to localised messages.

Platform codes are optional — errors without a user-actionable meaning
(500s, infrastructure failures, auth rejections) carry none.

Fully backwards-compatible: no existing signatures or JSON output changed
for errors without a platform code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Reviewed-on: #2
Reviewed-by: Rene Nochebuena <rene@noreply.nochebuena.dev>
Co-authored-by: Claude Code <claude@nochebuena.dev>
Co-committed-by: Claude Code <claude@nochebuena.dev>
This commit was merged in pull request #2.
This commit is contained in:
2026-03-25 16:42:15 -06:00
committed by NOCHEBUENADEV
parent 3cc36801a1
commit 5381bccbf7
3 changed files with 123 additions and 13 deletions

View File

@@ -13,18 +13,22 @@ import (
// interfaces that logz uses internally to enrich log records — without either
// package importing the other.
//
// Use the builder methods [Err.WithContext] and [Err.WithError] to attach
// additional information after construction:
// Use the builder methods [Err.WithContext], [Err.WithError], and
// [Err.WithPlatformCode] to attach additional information after construction:
//
// err := xerrors.New(xerrors.ErrInvalidInput, "validation failed").
// WithContext("field", "email").
// WithContext("rule", "required").
// WithError(cause)
//
// err := xerrors.New(xerrors.ErrNotFound, "employee not found").
// WithPlatformCode("EMPLOYEE_NOT_FOUND")
type Err struct {
code Code
message string
err error
fields map[string]any
code Code
message string
err error
fields map[string]any
platformCode string
}
// New creates an Err with the given code and message. No cause is set.
@@ -80,6 +84,27 @@ func (e *Err) WithError(err error) *Err {
return e
}
// WithPlatformCode sets a platform-level error code and returns the receiver
// for chaining. Platform codes are domain-specific identifiers (e.g.
// "EMPLOYEE_NOT_FOUND") that operate independently of the transport-level
// [Code]. They are intended for consuming applications — such as a frontend —
// that need to map errors to localised user-facing messages without relying on
// the generic transport code.
//
// Platform codes are optional. Errors that do not have a user-actionable
// meaning (e.g. 500 internal errors, infrastructure failures) should not carry
// one; the consuming application renders a generic fallback in those cases.
func (e *Err) WithPlatformCode(code string) *Err {
e.platformCode = code
return e
}
// PlatformCode returns the platform-level error code, or an empty string if
// none was set.
func (e *Err) PlatformCode() string {
return e.platformCode
}
// Error implements the error interface.
// Format: "INVALID_ARGUMENT: username is required → original cause"
func (e *Err) Error() string {
@@ -151,15 +176,18 @@ func (e *Err) ErrorContext() map[string]any {
}
// MarshalJSON implements [json.Marshaler].
// Output: {"code":"NOT_FOUND","message":"user not found","fields":{"id":"42"}}
// Output: {"code":"NOT_FOUND","platformCode":"EMPLOYEE_NOT_FOUND","message":"...","fields":{...}}
// platformCode and fields are omitted when empty.
func (e *Err) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Code string `json:"code"`
Message string `json:"message"`
Fields map[string]any `json:"fields,omitempty"`
Code string `json:"code"`
PlatformCode string `json:"platformCode,omitempty"`
Message string `json:"message"`
Fields map[string]any `json:"fields,omitempty"`
}{
Code: string(e.code),
Message: e.message,
Fields: e.fields,
Code: string(e.code),
PlatformCode: e.platformCode,
Message: e.message,
Fields: e.fields,
})
}