--- phase: 14.2.1-translate-plugin plan: 04 subsystem: i18n tags: [translate, tests, phase-gate, security-review, testcontainers, race] requires: - phase: 14.2.1-03 provides: "cabana ML fields, TranslationWriter adapter, proof-host user+translate boot" provides: - "TestTranslateEndToEnd on real Postgres through party/surf/cabana" - "Migration up/down/re-up, Translator, Translatable, Locales, ML, markdown, SPA matrices" - "scripts/check-phase14.2.1.sh fail-closed gate ending with Phase 14.2.1 gate passed" - "14.2.1-SECURITY-REVIEW.md ASVS L1 with T-14.2.1-01..18 and T-14.2.1-SC closed" affects: [15-journal-plugin] actuals: tokens: 38000 tasks: 3 commits: 7 plan_head_before: c7e2e4b4ed1a1048af3dcdaa2c74d37ef70de482 plan_head_after: ba6e436 plugin_repo_head_after: 64f8901 host_repo_head_after: 20108b8 tech-stack: added: [] patterns: - "Phase gate uses go -C for sibling plugin and proof host; Docker/Postgres failure is a failure except explicit -short" - "Security review without a dedicated auditor still re-runs every cited TestName and records that fallback" key-files: created: - ../sm-translate-plugin/integration_test.go - ../sm-translate-plugin/admin_harness_test.go - ../sm-translate-plugin/updates/migrations_test.go - ../sm-translate-plugin/classes/translator_resolve_test.go - ../sm-translate-plugin/classes/translatable_test.go - ../sm-translate-plugin/locales_admin_test.go - modules/cabana/ml_test.go - modules/cabana/markdown_test.go - admin/tests/form/MarkdownField.test.ts - scripts/check-phase14.2.1.sh - .planning/phases/14.2.1-translate-plugin/14.2.1-SECURITY-REVIEW.md modified: - ../sm-grzybyfunkcjonalne-app/boot_test.go - modules/surf/locale_resolver_test.go - modules/cabana/openapi_conformance_test.go - .planning/phases/14.2.1-translate-plugin/14.2.1-VALIDATION.md key-decisions: - "WhereIndex follows PHP transWhere: when no golem15_translate_indexes row matches, it falls back to the host column" - "Full cabana go test -race needs -timeout 30m; the default 10m timed out on the existing suite, not on the new tests" - "14.2.1-04 security review was executor-self-performed (no gsd-security-auditor in this Cursor session); every cited TestName was re-run" patterns-established: - "Fail-closed phase gate: named PASS lines, refuse skip/no-tests/race, sibling go -C, PHP SHA pin, forbidden-surface scan" - "Integration fixture plugin is process-local via party.Register in tests only and must not appear in plugins.gen.go" requirements-completed: [D-01, D-02, D-03, D-04, D-05, D-06, D-07, D-08, D-09, D-10, D-11, D-12, D-13, D-14, D-15, D-16, D-17] coverage: - id: D1 description: "Real-Postgres e2e activates user+translate+fixture, 403s Locales without manage_locales, saves nested ML en/pl, and proves URL locale precedence" requirement: D-17 verification: - kind: e2e ref: "sm-translate-plugin#TestTranslateEndToEnd" status: pass - kind: integration ref: "sm-grzybyfunkcjonalne-app#TestBootUserTranslate" status: pass human_judgment: false - id: D2 description: "Migration up/down/re-up, Translator D-07 order, Translatable storage/fallback, and Locales authorization/mass-assignment matrices" requirement: D-07 verification: - kind: integration ref: "sm-translate-plugin/updates#TestTranslateMigrationsRollbackAndRemigrate" status: pass - kind: unit ref: "sm-translate-plugin/classes#TestTranslatorResolve" status: pass - kind: unit ref: "sm-translate-plugin/classes#TestTranslatorConcurrentIsolation" status: pass - kind: unit ref: "sm-translate-plugin/classes#TestTranslatableGetSet" status: pass - kind: integration ref: "sm-translate-plugin#TestLocalesAdminForbidden" status: pass human_judgment: false - id: D3 description: "Cabana ML/markdown, surf isolation, SPA fields, OpenAPI FormView types, and fail-closed phase gate" requirement: D-06 verification: - kind: unit ref: "modules/cabana#TestMLNestedSave" status: pass - kind: unit ref: "modules/cabana#TestMarkdownRejectsUnsafeHTML" status: pass - kind: unit ref: "modules/surf#TestLocaleResolver" status: pass - kind: automated_ui ref: "admin/tests/form/MLFields.test.ts" status: pass - kind: other ref: "bash scripts/check-phase14.2.1.sh --all" status: pass human_judgment: false - id: D4 description: "ASVS L1 security review closes T-14.2.1-01 through T-14.2.1-18 and T-14.2.1-SC" verification: - kind: other ref: ".planning/phases/14.2.1-translate-plugin/14.2.1-SECURITY-REVIEW.md" status: pass human_judgment: false - id: D5 description: "Proof-host Locales SPA check as an administrator holding manage_locales" requirement: D-17 verification: [] human_judgment: true rationale: "Needs a running host, admin login, and visual confirmation of English then Polski; recorded as end-of-phase UAT" duration: 51min completed: 2026-10-06 status: complete --- # Phase 14.2.1 Plan 04: Translate unit/integration tests and phase gate Summary **Real-Postgres e2e, decision/security test matrices, fail-closed `check-phase14.2.1.sh`, and an ASVS L1 review that closes T-14.2.1-01..18 plus T-14.2.1-SC** ## Performance - **Duration:** 51 min - **Started:** 2026-10-06T11:31:12Z - **Completed:** 2026-10-06T12:21:36Z - **Tasks:** 3 - **Files modified:** 22 ## Accomplishments - `TestTranslateEndToEnd` boots user+translate plus a process-local fixture on dedicated Postgres, proves 403 without `golem15.translate.manage_locales`, nested mltext/mlmarkdown save (English on the host, one Polish attribute/index row), WithLocale reads, D-11 fallback, and `/pl/...` winning over cookie + Accept-Language. - Horizontal matrices cover gormigrate up/down/re-up, Translator D-07 order and `-race` isolation, Translatable storage/fallback/morph isolation, Locales mass-assignment and default-lifecycle guards, cabana ML lift/rollback, unsafe markdown rejection, and SPA markdown composition without `v-html=`. - `scripts/check-phase14.2.1.sh --all` passed every stage and printed `Phase 14.2.1 gate passed`. PHP pin SHA `725d547ec839f02b5fdc0f0a6faaed601a414d50` is unchanged. High threats are mitigated with re-executed named tests in `14.2.1-SECURITY-REVIEW.md`. ## Task Commits Each task was committed atomically: 1. **Task 1: End-to-end integration harness** - `e612b7f` (test) sm-translate-plugin — TestTranslateEndToEnd harness - `20108b8` (test) sm-grzybyfunkcjonalne-app — expanded TestBootUserTranslate 2. **Task 2: Decision and security matrices** - `1cfb5ee` (test) sm-translate-plugin — migrate/Translator/Translatable/Locales - `1bc6200` (test) summercms.go — ML, markdown, resolver, SPA 3. **Task 3: Phase gate, security review, validation sign-off** - `64f8901` (test) sm-translate-plugin — gofmt harness - `ba6e436` (test) summercms.go — `scripts/check-phase14.2.1.sh` **Plan metadata:** (this commit) Nothing was pushed. The proof host remains local-only. ## Files Created/Modified - `../sm-translate-plugin/integration_test.go` — production-path e2e - `../sm-translate-plugin/admin_harness_test.go` — fail-closed TestMain + fixture plugin - `../sm-translate-plugin/updates/migrations_test.go` — schema, seed, rollback - `../sm-translate-plugin/classes/translator_resolve_test.go` — D-07 + race isolation - `../sm-translate-plugin/classes/translatable_test.go` — storage, fallback, morph - `../sm-translate-plugin/locales_admin_test.go` — 403, mass-assignment, default guards - `modules/cabana/ml_test.go`, `markdown_test.go` — ML lift/XSS - `modules/surf/locale_resolver_test.go` — present/absent/isolation - `admin/tests/form/MarkdownField.test.ts` — SPA sinks - `scripts/check-phase14.2.1.sh` — fail-closed gate - `14.2.1-SECURITY-REVIEW.md`, `14.2.1-VALIDATION.md` — review and sign-off ## Decisions Made - WhereIndex matches PHP transWhere and falls back to the host column when no index row matches. - Cabana's existing suite needs `-timeout 30m` under `-race`. - Security review used the Phase 08 fallback (executor-performed) because this session has no `gsd-security-auditor`. ## Deviations from Plan ### Auto-fixed Issues **1. [Correctness] Polish-index lookup vs host-column fallback** - **Found during:** Task 1 (e2e) - **Issue:** Asserting that English slug `hello` must not match a Polish `WhereIndex` failed because `WhereIndex` falls back to the host column when no index row matches. - **Fix:** Assert the Polish index row is `slug=witaj` and that an unknown slug is `ErrRecordNotFound`. - **Files modified:** `../sm-translate-plugin/integration_test.go` - **Verification:** `TestTranslateEndToEnd` PASS - **Committed in:** `e612b7f` **2. [Correctness] SPA verify paths** - **Found during:** Task 2 - **Issue:** `npm --prefix admin test -- --run admin/tests/form/...` finds no files because Vitest include is `tests/**/*.test.ts` under `admin/`. - **Fix:** Gate and verify use `tests/form/registry.test.ts`, `MLFields.test.ts`, `MarkdownField.test.ts`. - **Verification:** 53 Vitest tests PASS - **Committed in:** `ba6e436` (gate) --- **Total deviations:** 2 auto-fixed (correctness) **Impact on plan:** Required for PHP-parity lookup and a green SPA stage. No scope creep. ## Issues Encountered - `go test ./modules/cabana -race` hit the default 10m timeout on the pre-existing suite. New tests pass under `-race` in seconds. The gate uses `-timeout 30m` and the full cabana+surf race passed. - Plugin `go.mod` gained a sibling `replace` for `sm-user-plugin` and a direct `gocloud.dev v0.46.0` require (already-decided pin) so the e2e harness can activate the real user plugin. Not a new package install (T-14.2.1-SC). ## User Setup Required None - no external service configuration required. ## Next Phase Readiness Phase 14.2.1 code and gate are green. Ready for `$gsd-verify-work` / milestone audit. Human UAT remains: boot the proof host, open Locales as `manage_locales`, confirm English then Polski. Journal (Phase 15) can implement `Translatable()` on its models. --- *Phase: 14.2.1-translate-plugin* *Completed: 2026-10-06*