diff --git a/.planning/phases/04-cli-scaffolding-i18n-and-mail/04-04-SUMMARY.md b/.planning/phases/04-cli-scaffolding-i18n-and-mail/04-04-SUMMARY.md new file mode 100644 index 0000000..bf15488 --- /dev/null +++ b/.planning/phases/04-cli-scaffolding-i18n-and-mail/04-04-SUMMARY.md @@ -0,0 +1,145 @@ +--- +phase: 04-cli-scaffolding-i18n-and-mail +plan: 04 +subsystem: testing +tags: [scaffold, phrasebook, postcard, mailpit, testcontainers, i18n] + +requires: + - phase: 04-cli-scaffolding-i18n-and-mail + provides: six make commands, phrasebook Translator, postcard Mailer and drivers +provides: + - adversarial unit coverage for CLI scaffolding, catalog lookup, and mail safety + - Mailpit testcontainer SMTP receipt via HTTP API + - scripts/check-phase4.sh root/hello/race/SMTP sign-off gate +affects: [plugin-porting, 05-data-layer] + +tech-stack: + added: [] + patterns: + - copied hello workspace drives public make/build APIs then go build and go vet + - Mailpit receipt is asserted through a separate HTTP API after go-mail SMTP send + - testing.Short skips only Mailpit; missing Docker fails the full test + +key-files: + created: + - postcard/templates_test.go + - postcard/smtp_test.go + - postcard/mailpit_test.go + - scripts/check-phase4.sh + modified: + - internal/build/build_test.go + - cmd/summer/main_test.go + - phrasebook/translator_test.go + - party/registry_test.go + - examples/hello/hello_test.go + +key-decisions: + - "Mailpit image is axllent/mailpit:v1.31.1; receipt is polled from /api/v1/messages then /api/v1/message/{ID}" + - "fstest.MapFS WalkDir cannot host '..' keys; malformed lang paths are extra-segment and wrong-suffix files" + +patterns-established: + - "Phase gate scripts refuse missing Docker instead of skipping SMTP" + - "Hello activation tests obtain Translator from backpack and pass towel.WithLocale" + +requirements-completed: [CLI-02, I18N-01, I18N-03] + +duration: 8min +completed: 2026-09-18 +--- + +# Phase 4 Plan 04: Unit tests and Mailpit Summary + +**Adversarial coverage for six make artifacts, pl/en phrasebook lookup, and postcard mail, plus a real Mailpit SMTP receipt and `scripts/check-phase4.sh`** + +## Performance + +- **Duration:** 8 min +- **Started:** 2026-09-18T12:04:31Z +- **Completed:** 2026-09-18T12:12:42Z +- **Tasks:** 3 +- **Files modified:** 9 + +## Accomplishments + +- Copied hello-app tests generate all six artifacts, compile and vet the workspace, reject malformed names/traversal/duplicates, and leave handwritten `plugin.go` untouched +- Phrasebook catalog tests cover nested groups, invalid YAML/pipes, compass `app.locale`/`fallback_locale`, and hello activation through `towel.WithLocale` +- Postcard memory tests preserve To/Cc/Bcc/ReplyTo and keep unsafe HTML out; SMTP TLS stays explicit; Mailpit HTTP API proves go-mail receipt; `scripts/check-phase4.sh` is the phase gate + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Close scaffold and CLI command boundary coverage** - `85bdb51` (test) +2. **Task 2: Close translation lookup and catalog boundary coverage** - `918e941` (test) +3. **Task 3: Close mail safety, driver, and Mailpit receipt coverage** - `9f6fbad` (test) + +**Plan metadata:** (this commit) + +## Files Created/Modified + +- `internal/build/build_test.go` - exact paths, workspace build/vet, malformed artifact names +- `cmd/summer/main_test.go` - five make argument forms, `--no-migration`, public CLI execution +- `phrasebook/translator_test.go` - catalog, pipe, locale-config, and substitution boundaries +- `party/registry_test.go` - activation errors name plugin, file, and key +- `examples/hello/hello_test.go` - backpack translator via `towel.WithLocale`; unknown mail template +- `postcard/templates_test.go` - recipients, HTML safety, registration ownership +- `postcard/smtp_test.go` - TLS policy and credential-free SMTP errors +- `postcard/mailpit_test.go` - `TestSMTPMailpit` against `axllent/mailpit:v1.31.1` +- `scripts/check-phase4.sh` - root vet/test, hello vet/test, focused race; Docker required + +## Decisions Made + +- Mailpit receipt is observed through the HTTP API after SMTP send, not by trusting `Send`'s return value +- `testing.Short` skips only the Mailpit container test; a full `go test ./postcard -run TestSMTPMailpit` fails when Docker is unavailable +- Malformed lang-path cases use extra segments and wrong suffixes because `fstest.MapFS` `WalkDir` recurses on `..` keys + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] fstest.MapFS cannot walk `..` fixture keys** +- **Found during:** Task 2 (path traversal catalog case) +- **Issue:** `lang/en/../pl/lang.yaml` in `fstest.MapFS` caused `WalkDir` to recurse until a stack overflow +- **Fix:** Cover malformed paths with extra-segment, `.yml`, and non-`lang/` prefixes; `parseLangPath` still rejects `..` when it appears in a cleaned path +- **Files modified:** `phrasebook/translator_test.go` +- **Verification:** `go test ./phrasebook -short -count=1` PASS +- **Committed in:** `918e941` (Task 2 commit) + +**2. [Rule 3 - Blocking] cobra help omits optional-arg descriptions** +- **Found during:** Task 1 (CLI argument-form assertions) +- **Issue:** `make:migration --help` prints `[plugin] [name]`, not the Arg Description `vendor.plugin` +- **Fix:** Assert the real Usage forms `[plugin] [name]` and `--no-migration`; keep `vendor.plugin` on required `make:plugin` +- **Files modified:** `cmd/summer/main_test.go` +- **Verification:** `go test ./cmd/summer -run TestToolCommandNames -count=1` PASS +- **Committed in:** `85bdb51` (Task 1 commit) + +--- + +**Total deviations:** 2 auto-fixed (1 bug, 1 blocking) +**Impact on plan:** No production API changes. Tests cover the same contracts with fixtures cobra and `fstest` can actually execute. + +## Issues Encountered + +None + +## User Setup Required + +None - no external service configuration required. Mailpit runs in Docker via testcontainers; production SMTP stays in `mail.*` / `SUMMER_MAIL__`. + +## Next Phase Readiness + +Phase complete, ready for next step. Scaffolding, phrasebook, and postcard contracts now have failing-when-broken tests including a real SMTP receipt. `scripts/check-phase4.sh` is the sign-off gate and requires Docker. + +## Verification + +- `go test ./internal/build ./cmd/summer -run 'TestScaffoldAllArtifacts|TestModelsLeaf|TestToolCommandNames' -short -count=1` — PASS +- `go test ./phrasebook ./party -short -count=1 && go -C examples/hello test ./...` — PASS +- `go test ./postcard -run 'TestMail|TestSMTPMailpit' -short -count=1` — PASS (Mailpit skipped under `-short`) +- `go test ./postcard -run TestSMTPMailpit -count=1` — PASS (Docker/Mailpit receipt) +- `./scripts/check-phase4.sh` — PASS (root vet/test including Mailpit, hello vet/test, race) + +## Self-Check: PASSED + +--- +*Phase: 04-cli-scaffolding-i18n-and-mail* +*Completed: 2026-09-18*