WriteTypedErrorEnvelope writes the JSON error envelope for a typed error. Each typed error owns its wire shape via its own struct tags: Problem fields are promoted to the top level through embedding, and extension fields (MissingScopes, ChallengeURL, etc.) sit alongside as siblings — not inside a `d
(w io.Writer, err error, identity string)
| 56 | // Returns false only when err carries no Problem (the dispatcher then handles |
| 57 | // it via its signal / usage-error branches) or when JSON encoding itself failed. |
| 58 | func WriteTypedErrorEnvelope(w io.Writer, err error, identity string) bool { |
| 59 | typed, ok := errs.UnwrapTypedError(err) |
| 60 | if !ok { |
| 61 | return false |
| 62 | } |
| 63 | env := typedEnvelope{ |
| 64 | OK: false, |
| 65 | Identity: identity, |
| 66 | Error: typed, |
| 67 | Notice: GetNotice(), |
| 68 | } |
| 69 | var buf bytes.Buffer |
| 70 | enc := json.NewEncoder(&buf) |
| 71 | enc.SetEscapeHTML(false) |
| 72 | enc.SetIndent("", " ") |
| 73 | if encErr := enc.Encode(env); encErr != nil { |
| 74 | // Encoding failed — emit nothing here; the dispatcher's fall-through |
| 75 | // branches still surface the error, so stderr is never blank. |
| 76 | return false |
| 77 | } |
| 78 | // Best-effort write. Partial-write does not downgrade the success status: |
| 79 | // the dispatcher has already captured ExitCodeOf(err) before calling us, |
| 80 | // and a torn stderr is preferable to falling through to the plain |
| 81 | // "Error:" path with exit 1. |
| 82 | _, _ = w.Write(buf.Bytes()) |
| 83 | return true |
| 84 | } |
| 85 | |
| 86 | // typedEnvelope wraps a typed error for wire emission. Error is `error` so the |
| 87 | // underlying typed error's own json tags determine the inner shape via |