Skip to content

v1.0.2

Choose a tag to compare

@n-ae n-ae released this 18 Jul 11:34

Patch release closing the v1.0.2 priority list from
docs/assessment-maintainable-architect-v4-head-2026-07-18.md, a
cross-review of v1.0.1 + post-tag HEAD combining an external review and
an independent Codex direct review
(docs/repository-assessment-head-codex-2026-07-18.md). No breaking
changes; module path unchanged.

Fixed:

  • Panic-recovery log fields (stack trace included) were dropped for a
    panic recovered after the response was already committed, or after a
    successful Hijack, because field selection was keyed off the stale
    HTTP status of the prior response rather than the panic itself.
    Fields are now derived from the recovered error's own severity;
    http_status is no longer reported for these two cases since no
    error response was actually rendered, and response_committed_status
    / hijacked remain the transport-level truth in its place.
  • safeJSONMarshal now validates that a nil-error json.Marshal
    result is actually valid JSON. Under legacy GODEBUG=panicnil=1
    semantics, a custom MarshalJSON that does a literal panic(nil)
    was invisible to recover(), so json.Marshal could return a
    truncated, invalid body with a nil error - silently reported as a
    fully successful response.
  • A marshaler panic carrying an error value is now wrapped with %w
    instead of flattened with %v, so errors.Is/errors.As can still
    reach it through RenderErr.
  • RFC 9457 problem titles no longer render empty for a nonstandard
    status (e.g. a custom code mapped to 499): http.StatusText
    returning "" now falls back to the package's own occurrence-
    invariant per-code text, matching the JSON/HTML fallback bodies.

Changed:

  • New/Wrap normalize an empty ErrorCode to ErrCodeInternal
    instead of letting "" ride through to the wire as the
    machine-readable classification key. RegisterStatusCode and
    RendererConfig.StatusCodes now reject an empty code key at
    registration.
  • Both GitHub Actions workflows declare permissions: contents: read
    explicitly rather than relying on the mutable repository-level
    default, and the vulnerability-scan workflow pins
    govulncheck@v1.6.0 instead of floating @latest, so a future scan
    result stays reproducible against a fixed scanner version.

Test coverage: 100.0% (root module), 100.0% (zerologadapter).