refactor: pass context and I/O explicitly through sign and verify #6

Closed
opened 2026-07-21 17:20:16 +02:00 by heiko · 1 comment
Owner

Problem

sign and verify accept an io.Writer but intentionally discard it:

func sign(r io.Reader, _ io.Writer, opts signOpts) error
func verify(r io.Reader, _ io.Writer) error

They instead use os.Stdout, os.Stderr, fmt.Print, and the package-global logger. sign also creates request contexts from context.Background, so caller/Cobra cancellation is not propagated.

This makes the most important workflows difficult to test and can corrupt the wrong output stream. It also prevents clean cancellation on command shutdown.

Checklist: #46 (accept readers/writers for testability) and #60 (propagate context through blocking operations).

Proposed fix

  • Use signatures such as sign(ctx context.Context, in io.Reader, out, diag io.Writer, opts signOpts) error and the equivalent for verification.
  • Pass cmd.Context(), cmd.InOrStdin(), cmd.OutOrStdout(), and cmd.ErrOrStderr() from Cobra commands.
  • Replace every direct fmt.Print, os.Stdout.Write, os.Stderr, and log.Printf in command logic with the supplied writers/logger.
  • Keep pure formatting separate from I/O where possible.
  • Establish one clear contract for primary output versus diagnostics.

Acceptance criteria

  • Command logic contains no direct references to process-global stdin/stdout/stderr.
  • Canceling the command context cancels all TSA requests.
  • Unit tests capture message, header, token, response, and diagnostic output entirely in memory.
  • Write failures from either output stream are propagated.

Reviewed against 948b7a9 on master (Go 1.26.2).

## Problem `sign` and `verify` accept an `io.Writer` but intentionally discard it: ```go func sign(r io.Reader, _ io.Writer, opts signOpts) error func verify(r io.Reader, _ io.Writer) error ``` They instead use `os.Stdout`, `os.Stderr`, `fmt.Print`, and the package-global logger. `sign` also creates request contexts from `context.Background`, so caller/Cobra cancellation is not propagated. This makes the most important workflows difficult to test and can corrupt the wrong output stream. It also prevents clean cancellation on command shutdown. Checklist: #46 (accept readers/writers for testability) and #60 (propagate context through blocking operations). ## Proposed fix - Use signatures such as `sign(ctx context.Context, in io.Reader, out, diag io.Writer, opts signOpts) error` and the equivalent for verification. - Pass `cmd.Context()`, `cmd.InOrStdin()`, `cmd.OutOrStdout()`, and `cmd.ErrOrStderr()` from Cobra commands. - Replace every direct `fmt.Print`, `os.Stdout.Write`, `os.Stderr`, and `log.Printf` in command logic with the supplied writers/logger. - Keep pure formatting separate from I/O where possible. - Establish one clear contract for primary output versus diagnostics. ## Acceptance criteria - Command logic contains no direct references to process-global stdin/stdout/stderr. - Canceling the command context cancels all TSA requests. - Unit tests capture message, header, token, response, and diagnostic output entirely in memory. - Write failures from either output stream are propagated. Reviewed against `948b7a9` on `master` (Go 1.26.2).
Author
Owner

sign, query, verify, and now normalize route all output and diagnostics through injected io.Writers (no direct os.Stdout/os.Stderr references remain in command logic); sign/verify accept ctx from cmd.Context(). Added tests: all four sign output formats captured entirely in memory, and write-failure propagation for sign, verify, query, and normalize.

Closing commit: 26b6dc84e166

Note: local master only so far; the link resolves once pushed.

`sign`, `query`, `verify`, and now `normalize` route all output and diagnostics through injected `io.Writer`s (no direct `os.Stdout`/`os.Stderr` references remain in command logic); `sign`/`verify` accept `ctx` from `cmd.Context()`. Added tests: all four `sign` output formats captured entirely in memory, and write-failure propagation for sign, verify, query, and normalize. Closing commit: [`26b6dc84e166`](https://forgejo.schlittermann.de/heiko/mail-seal/commit/26b6dc84e166088524d83d72fd0918b121bf4752) _Note: local `master` only so far; the link resolves once pushed._
heiko closed this issue 2026-07-21 23:33:02 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
heiko/mailseal#6
No description provided.