feat(npm): S01 error-envelope transport helpers (S11 Step 6, 1/4)
What
Part 1 of 4 splitting !425 (closed) (S11 Step 6) into reviewable, sub-500-line MRs. This MR lands the S01 error-envelope transport helpers shared by every npm endpoint.
WriteJSON/WriteErrorover the S01 standard envelope, mirroringinternal/transport.- The
CodeandSafeMessagenamed types — both closed sets of constants — make "caller used a canonical code" and "no internal detail in the body" compile-time gates: only pre-approved messages can reach the envelope.
Stack
- transport (this MR) →
main - resolver → transport
- middleware → resolver
- integration + CI → middleware
No new plan MR — this re-packages already-approved Step 6 code (!425 (closed) was reviewed APPROVE; the sole warning was MR size). Post-split, transport.go/transport_test.go carry small review-driven changes: the package doc moved to buffered.go (merged to main meanwhile) to satisfy godoclint, TestErrorCodes is now table-driven, and an encode-failure no-leak test was added per AppSec review. SafeMessage was then closed to a Msg* constant set (open Msg(string) removed) per review, with the stacked MRs' call sites rebased onto it. CLAUDE.md also gains an AppSec-review-reply convention, per review.
Tests
transport_test.go (unit): envelope shape, status/code table, missing-correlation-ID, content-type, code constants (table-driven), and the encode-failure no-leak contract (WriteJSON on an unencodable body → status + JSONContentType + empty body, never err.Error()).
Spec / plan
- Spec: S11 npm-local — API Contracts, Error Cases
- Plan: 2026-05-11 npm-local, Step 6