Files
summercms/.planning/phases/04-cli-scaffolding-i18n-and-mail/04-04-PLAN.md
2026-09-18 13:24:54 +02:00

11 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
04-cli-scaffolding-i18n-and-mail 04 execute 4
04-01
04-02
04-03
internal/build/build_test.go
cmd/summer/main_test.go
phrasebook/translator_test.go
postcard/mailer_test.go
postcard/templates_test.go
postcard/smtp_test.go
postcard/mailpit_test.go
party/registry_test.go
examples/hello/hello_test.go
scripts/check-phase4.sh
true
CLI-02
I18N-01
I18N-03
truths artifacts key_links
CLI-02 and D-10 through D-17: Every make command produces a compiling, vet-clean artifact in a copied hello app; registry bytes are stable, --no-migration works, hand-written plugin.go is untouched, and models sibling imports fail by name.
I18N-01 and D-01 through D-05: Embedded en/pl catalogs resolve nested keys, both plural syntaxes, parameter variants, fallback order, raw missing keys, and named boot errors for malformed assets.
I18N-03 and D-06 through D-09/D-18 through D-21: Registered mail and layout render safe subject, HTML and text through memory; invalid registrations, dangerous content and headers fail; SMTP delivery is visible in Mailpit.
D-19: go test ./postcard -run TestSMTPMailpit -count=1 fails when Docker is unavailable, while -short skips only the Mailpit container test.
path provides
internal/build/build_test.go six-artifact compile/vet and leaf-import regression tests
path provides
phrasebook/translator_test.go catalog, CLDR, pipe, substitution, and fallback boundary tests
path provides
postcard/mailpit_test.go real SMTP receipt assertion via Mailpit HTTP API
path provides
scripts/check-phase4.sh repeatable root, hello and Mailpit sign-off gate
from to via
scripts/check-phase4.sh postcard/mailpit_test.go full root go test ./... includes the non-short Mailpit test
from to via
internal/build/build_test.go internal/build/scaffold.go copied hello app drives public make/build API
from to via
examples/hello/hello_test.go party/registry.go activation checks published phrasebook and postcard services

Phase Goal

As a plugin developer, I want to generate compiling plugin artifacts, resolve translated strings, and send registered mail, so that I can port WinterCMS plugins into one SummerCMS binary.

Prove the three Phase 4 slices with focused unit coverage and a real SMTP integration receipt.

Purpose: Scaffolding, translation and mail contracts remain checkable as later plugin ports use them. Output: adversarial tests, Mailpit testcontainer coverage, and one repeatable phase gate.

<execution_context> @/home/jin/.codex/get-shit-done/workflows/execute-plan.md @/home/jin/.codex/get-shit-done/templates/summary.md </execution_context>

@CLAUDE.md @.planning/ROADMAP.md @.planning/REQUIREMENTS.md @.planning/phases/04-cli-scaffolding-i18n-and-mail/04-CONTEXT.md @.planning/phases/04-cli-scaffolding-i18n-and-mail/04-RESEARCH.md @.planning/phases/04-cli-scaffolding-i18n-and-mail/04-VALIDATION.md @.planning/phases/04-cli-scaffolding-i18n-and-mail/04-01-SUMMARY.md @.planning/phases/04-cli-scaffolding-i18n-and-mail/04-02-SUMMARY.md @.planning/phases/04-cli-scaffolding-i18n-and-mail/04-03-SUMMARY.md The public paths under test are build.MakePlugin, build.AddPlugin, build.App and the five new make commands; phrasebook.Translator.Get/Choice plus explicit-locale variants; postcard.Mailer.Send(ctx, postcard.Message) and its three drivers; party.Activate with optional HasLang and HasMailTemplates. Existing internal/build/build_test.go copies examples/hello and rewrites the local framework replacement. Existing lagoon/postgres_test.go shows the testcontainers rule: Docker failure fails full tests and testing.Short skips container startup. Mailpit exposes SMTP 1025 and HTTP API 8025; use axllent/mailpit:v1.31.1, a released upstream tag, with a bounded API poll after SMTP send. Task 1: Close scaffold and CLI command boundary coverage internal/build/build_test.go, cmd/summer/main_test.go internal/build/build_test.go; cmd/summer/main_test.go; internal/build/scaffold.go; internal/build/registry.go; internal/build/leaf.go; internal/build/build.go; .planning/notes/plugin-layout-winter-directories.md; 04-CONTEXT.md D-10 through D-17; 04-VALIDATION.md Extend the temporary hello-app test through all six make commands and run both go build and go vet in that copied workspace. Assert exact generated paths, model table/timestamps, migration Up/Down registration, --no-migration, job Kind/Work contract, admin YAML paths, each registry slice and stable bytes after repeated commands. Inject a models/ to classes/ import and assert summer build reports plugin ID, source and import; cover malformed identifiers, traversal, duplicate names and the one-time accessor instruction for a handwritten plugin without rewriting its plugin.go. Add the five command names and argument forms to cmd/summer/main_test.go. Use public CLI/build paths, not only private helpers. go test ./internal/build ./cmd/summer -run 'TestScaffoldAllArtifacts|TestModelsLeaf|TestToolCommandNames' -short -count=1 && go vet ./... && go test ./... Every generated artifact compiles and vets in the copied app; intentional malformed input and sibling import fail with named errors. CLI-02 has green positive and negative tests through the public command/build flow. Task 2: Close translation lookup and catalog boundary coverage phrasebook/translator_test.go, party/registry_test.go, examples/hello/hello_test.go phrasebook/loader.go; phrasebook/translator.go; phrasebook/translator_test.go; party/registry.go; party/registry_test.go; examples/hello/hello_test.go; 04-CONTEXT.md D-01 through D-05; 04-VALIDATION.md Keep the related loader, plural and lookup cases together in translator_test.go. Use fstest.MapFS fixtures to prove nested YAML flattening, namespace ownership, malformed paths and leaves, and boot errors naming plugin/file/key. Assert map plurals for pl counts 0/1/2/5/22 and fractional values, en 1/2, pipe ordered forms plus {0} and [2,*], and invalid categories/brackets/forms. Assert :name/:Name/:NAME, requested pl-PL to pl to configured en to raw key order, app.locale/fallback_locale defaults en/en, and once-per-key non-production logging without parameter leakage. The hello activation test must obtain the translator from backpack and use towel.WithLocale to prove the existing context seam. go test ./phrasebook ./party -short -count=1 && go -C examples/hello test ./... && go vet ./... && go test ./... All I18N-01 decisions have tests that fail if lookup order, plural category, substitution or catalog validation regresses. The published translator passes Polish/English happy paths and malformed-catalog failures. Task 3: Close mail safety, driver, and Mailpit receipt coverage postcard/mailer_test.go, postcard/templates_test.go, postcard/smtp_test.go, postcard/mailpit_test.go, examples/hello/hello_test.go, scripts/check-phase4.sh postcard/mailer.go; postcard/templates.go; postcard/drivers.go; postcard/mailer_test.go; examples/hello/hello_test.go; lagoon/postgres_test.go; 04-CONTEXT.md D-06 through D-09 and D-18 through D-21; 04-VALIDATION.md; https://mailpit.axllent.org/docs/api-v1/ Assert memory delivery preserves To/Cc/Bcc/ReplyTo, templated subject, Markdown text, final HTML, layout wrappers, neutral default and explicit -en selection. Add adversarial Vars with raw tags, Markdown links and javascript: URLs; test unsafe rendered HTML is absent, subject CR/LF and invalid recipients are rejected, missing template/layout fails Boot with plugin ID and name, and a failing driver error reaches Send without retry. Test log driver redacts credentials and SMTP TLS/no-downgrade policy. Add TestSMTPMailpit using testcontainers-go image axllent/mailpit:v1.31.1, mapped SMTP 1025 and HTTP 8025, go-mail send, and bounded HTTP API polling that asserts recipient, subject, HTML and text receipt; skip only under testing.Short and fail when Docker is absent otherwise. Add scripts/check-phase4.sh that runs root go vet ./..., root go test ./... including Mailpit, go -C examples/hello vet ./..., go -C examples/hello test ./..., and a focused race run for internal/build, phrasebook and postcard. Keep the script within this repository and do not invoke live SMTP accounts. go test ./postcard -run 'TestMail|TestSMTPMailpit' -short -count=1 && ./scripts/check-phase4.sh Memory and SMTP tests verify actual subject, recipients, HTML and text; all unsafe content/header cases fail; Mailpit API proves real SMTP receipt on a full run. scripts/check-phase4.sh exits zero with Docker available and fails rather than silently skipping a missing Docker daemon.

<threat_model>

Trust Boundaries

Boundary Description
Test fixtures to generated source Malicious names and imports must be rejected in public make/build paths.
Plugin translation/mail assets to app services Malformed content must fail activation and unsafe values must not enter final mail.
SMTP client to Mailpit A successful Send claim requires observed receipt through a separate HTTP API.

STRIDE Threat Register

Threat ID Category Component Disposition Mitigation Plan
T-04-12 Tampering scaffold regression tests mitigate Drive public make/build flow with traversal, duplicate, injected sibling import and byte-stability cases.
T-04-13 Tampering catalog regression tests mitigate Fail invalid YAML/plural and duplicate namespace cases with named boot diagnostics.
T-04-14 Information disclosure mail regression tests mitigate Assert final HTML has no unsafe links/raw tags and logs/errors contain no SMTP credentials.
T-04-15 Repudiation SMTP test result mitigate Require Mailpit HTTP API receipt after go-mail SMTP send; full test fails on absent Docker.
T-04-SC Tampering test image/dependencies mitigate Pin released Mailpit image tag and keep Go module dependencies from research; no npm/pip/cargo install.
</threat_model>
Run focused automated tests after each task and root go vet ./... plus go test ./... at each task commit. Final sign-off is scripts/check-phase4.sh with Docker available. A -short run is fast feedback only; it cannot substitute for the Mailpit receipt. Inspect script output for root, nested hello, race and SMTP results.

<success_criteria> The final gate proves CLI-02, I18N-01 and I18N-03 through generated-app compilation, catalog lookup, rendered mail, and actual SMTP receipt. High-severity threat cases have failing-when-broken tests, and full tests do not skip Docker failure. </success_criteria>

Create .planning/phases/04-cli-scaffolding-i18n-and-mail/04-04-SUMMARY.md when done.