144 lines
11 KiB
Markdown
144 lines
11 KiB
Markdown
---
|
|
phase: 04-cli-scaffolding-i18n-and-mail
|
|
plan: "04"
|
|
type: execute
|
|
wave: 4
|
|
depends_on: ["04-01", "04-02", "04-03"]
|
|
files_modified:
|
|
- 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
|
|
autonomous: true
|
|
requirements: [CLI-02, I18N-01, I18N-03]
|
|
must_haves:
|
|
truths:
|
|
- "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."
|
|
artifacts:
|
|
- path: internal/build/build_test.go
|
|
provides: six-artifact compile/vet and leaf-import regression tests
|
|
- path: phrasebook/translator_test.go
|
|
provides: catalog, CLDR, pipe, substitution, and fallback boundary tests
|
|
- path: postcard/mailpit_test.go
|
|
provides: real SMTP receipt assertion via Mailpit HTTP API
|
|
- path: scripts/check-phase4.sh
|
|
provides: repeatable root, hello and Mailpit sign-off gate
|
|
key_links:
|
|
- from: scripts/check-phase4.sh
|
|
to: postcard/mailpit_test.go
|
|
via: full root go test ./... includes the non-short Mailpit test
|
|
- from: internal/build/build_test.go
|
|
to: internal/build/scaffold.go
|
|
via: copied hello app drives public make/build API
|
|
- from: examples/hello/hello_test.go
|
|
to: party/registry.go
|
|
via: 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.
|
|
|
|
<objective>
|
|
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.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/home/jin/.codex/get-shit-done/workflows/execute-plan.md
|
|
@/home/jin/.codex/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<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
|
|
|
|
<interfaces>
|
|
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.
|
|
</interfaces>
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Close scaffold and CLI command boundary coverage</name>
|
|
<files>internal/build/build_test.go, cmd/summer/main_test.go</files>
|
|
<read_first>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</read_first>
|
|
<action>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.</action>
|
|
<verify><automated>go test ./internal/build ./cmd/summer -run 'TestScaffoldAllArtifacts|TestModelsLeaf|TestToolCommandNames' -short -count=1 && go vet ./... && go test ./...</automated></verify>
|
|
<acceptance_criteria>Every generated artifact compiles and vets in the copied app; intentional malformed input and sibling import fail with named errors.</acceptance_criteria>
|
|
<done>CLI-02 has green positive and negative tests through the public command/build flow.</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Close translation lookup and catalog boundary coverage</name>
|
|
<files>phrasebook/translator_test.go, party/registry_test.go, examples/hello/hello_test.go</files>
|
|
<read_first>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</read_first>
|
|
<action>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.</action>
|
|
<verify><automated>go test ./phrasebook ./party -short -count=1 && go -C examples/hello test ./... && go vet ./... && go test ./...</automated></verify>
|
|
<acceptance_criteria>All I18N-01 decisions have tests that fail if lookup order, plural category, substitution or catalog validation regresses.</acceptance_criteria>
|
|
<done>The published translator passes Polish/English happy paths and malformed-catalog failures.</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 3: Close mail safety, driver, and Mailpit receipt coverage</name>
|
|
<files>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</files>
|
|
<read_first>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/</read_first>
|
|
<action>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.</action>
|
|
<verify><automated>go test ./postcard -run 'TestMail|TestSMTPMailpit' -short -count=1 && ./scripts/check-phase4.sh</automated></verify>
|
|
<acceptance_criteria>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.</acceptance_criteria>
|
|
<done>scripts/check-phase4.sh exits zero with Docker available and fails rather than silently skipping a missing Docker daemon.</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<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>
|
|
|
|
<verification>
|
|
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.
|
|
</verification>
|
|
|
|
<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>
|
|
|
|
<output>
|
|
Create .planning/phases/04-cli-scaffolding-i18n-and-mail/04-04-SUMMARY.md when done.
|
|
</output>
|