Files
summercms/.planning/phases/14.2.1-translate-plugin/14.2.1-04-PLAN.md
2026-10-06 11:22:45 +02:00

20 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
14.2.1-translate-plugin 04 execute 4
14.2.1-03
../sm-translate-plugin/updates/postgres_test.go
../sm-translate-plugin/updates/migrations_test.go
../sm-translate-plugin/classes/translator_test.go
../sm-translate-plugin/classes/translatable_test.go
../sm-translate-plugin/admin_harness_test.go
../sm-translate-plugin/locales_admin_test.go
../sm-translate-plugin/integration_test.go
modules/surf/locale_resolver_test.go
modules/cabana/ml_test.go
modules/cabana/markdown_test.go
modules/cabana/openapi_conformance_test.go
admin/tests/form/MLFields.test.ts
admin/tests/form/MarkdownField.test.ts
../sm-grzybyfunkcjonalne-app/boot_test.go
scripts/check-phase14.2.1.sh
.planning/phases/14.2.1-translate-plugin/14.2.1-SECURITY-REVIEW.md
.planning/phases/14.2.1-translate-plugin/14.2.1-VALIDATION.md
true
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
truths artifacts key_links
A real-Postgres integration test migrates all four winter_translate tables, activates user+translate+fixture, saves en/pl through cabana ML fields, reads via WithLocale, and reaches Locales admin.
Migration up/down verifies every final column/index, empty Messages table, idempotent en/pl seed, absence of de, and complete rollback.
Translator tests prove URL → preferred_locale → remembered locale → cookie-gated Accept-Language → default, invalid-code rejection, API order, plugin-absent surf behavior, and concurrent request isolation.
Translatable tests prove default-row storage, non-default JSON, default fallback, indexed lookup, undeclared-field rejection, invalid-locale rejection, and atomic preservation of sibling fields.
Admin/ML tests prove manage_locales authorization, default-locale lifecycle guards, mass-assignment resistance, nested-map preservation, synchronized locale controls, and stored-XSS rejection.
All three repositories pass vet/tests; docs/OpenAPI/types/dist consistency checks pass; a security review closes every high threat.
path provides contains
../sm-translate-plugin/integration_test.go full production-path integration proof TestTranslateEndToEnd
path provides contains
../sm-translate-plugin/updates/migrations_test.go real Postgres migration up/down and seed proof winter_translate_messages
path provides contains
modules/surf/locale_resolver_test.go resolver-present/absent and request-isolation tests TestLocaleResolver
path provides contains
modules/cabana/ml_test.go nested ML write and mass-assignment tests TestML
path provides contains
scripts/check-phase14.2.1.sh fail-closed phase gate sm-translate-plugin
path provides contains
.planning/phases/14.2.1-translate-plugin/14.2.1-SECURITY-REVIEW.md ASVS L1 threat evidence T-14.2.1-01
from to via pattern
../sm-translate-plugin/integration_test.go modules/cabana/field_ml.go fixture admin save uses real TranslationWriter TestTranslateEndToEnd
from to via pattern
scripts/check-phase14.2.1.sh ../sm-translate-plugin/updates/migrations_test.go full plugin test suite runs with Docker/Postgres, not -short go -C
from to via pattern
.planning/phases/14.2.1-translate-plugin/14.2.1-SECURITY-REVIEW.md modules/cabana/ml_test.go each mitigated high threat cites executed failure evidence T-14.2.1
Finish Phase 14.2.1 with the dedicated unit/integration/security test plan and one fail-closed gate across plugin, framework, admin SPA, and proof host.

Purpose: make every locked decision and high-risk locale/admin write behavior observably fail when broken. Output: full test matrix, migration rollback proof, phase gate, security review, and validated validation map.

<execution_context> @/.codex/gsd-core/workflows/execute-plan.md @/.codex/gsd-core/templates/summary.md </execution_context>

@.planning/phases/14.2.1-translate-plugin/14.2.1-01-SUMMARY.md @.planning/phases/14.2.1-translate-plugin/14.2.1-02-SUMMARY.md @.planning/phases/14.2.1-translate-plugin/14.2.1-03-SUMMARY.md @.planning/phases/14.2.1-translate-plugin/14.2.1-VALIDATION.md @.planning/phases/14.2.1-translate-plugin/14.2.1-RESEARCH.md @.planning/phases/14.2.1-translate-plugin/14.2.1-PATTERNS.md @../fonoteka.go/plugins/golem15/user/updates/postgres_test.go @../fonoteka.go/plugins/golem15/user/admin_harness_test.go @scripts/check-phase14.sh

Spec-less probe fallback

The phase has no mapped REQUIREMENTS.md IDs. This is a visible, intentional skip of spec-less probes. Tests and gate rows map directly to D-01 through D-17, the frozen PHP pin, and the RESEARCH validation/threat tables.

Artifacts this phase produces

  • TestTranslateEndToEnd spanning migration, activation, resolver, permissioned admin, nested ML write, en/pl storage, fallback, and indexed query.
  • Real-Postgres migration/seed/rollback suite.
  • Translator, surf, Translatable, Locales admin, cabana ML/markdown, SPA, generated-contract, and proof-host tests.
  • scripts/check-phase14.2.1.sh with short/full/docs/admin/host/security stages.
  • 14.2.1-SECURITY-REVIEW.md and a completed 14.2.1-VALIDATION.md.

Multi-source coverage audit

SOURCE ID Feature/Requirement Plan Status Notes
GOAL — Lean Translate core lets Journal keep translatable fields and boots in proof host 01-04 COVERED Schema, API, admin, ML fields, host, tests
REQ — No mapped requirement IDs — COVERED Visible spec-less fallback; D-IDs are used
CONTEXT D-01..D-04 Frozen/read-only PHP SHA 01,04 COVERED Pin asserted; PHP tree unchanged
CONTEXT D-05 Locale/admin/behavior lean scope; deferred surfaces absent 02,04 COVERED Negative scope checks in gate
CONTEXT D-06 markdown/mltext/mlmarkdown compose 03,04 COVERED Go + SPA + generated artifacts
CONTEXT D-07 full request locale resolution 01,04 COVERED Ordered and concurrent tests
CONTEXT D-08 en/pl only 01,04 COVERED Seed/absence tests
CONTEXT D-09..D-12 explicit Translatable APIs/storage/fallback 02-04 COVERED Fixture and full matrix
CONTEXT D-13..D-17 proof host, remotes, submodules, boot/proof 01,03,04 COVERED Host smoke and layout checks
RESEARCH — Exact four final tables/columns/indexes and migrations up/down 01,04 COVERED Real Postgres
RESEARCH — Permission, default-locale guards, phrasebook separation 02,04 COVERED Admin suite
RESEARCH — Nested ML map before projection, safe markdown 03,04 COVERED Security tests
RESEARCH — README/docs/OpenAPI/TS/dist same change 03,04 COVERED Consistency gate
RESEARCH — No external SaaS API integration 01-04 COVERED No COVERAGE matrix or fabricated API tests

Excluded by explicit scope: Messages catalogue/admin, CMS locale components, locale picker/hreflang/banner, AI/theme commands, message import/export, extra locale seeds, PHP edits, and Phase 15 Journal implementation.

Task 1: Prove migration → activation → resolver → Locales admin → ML save → WithLocale read end to end ../sm-translate-plugin/updates/postgres_test.go, ../sm-translate-plugin/integration_test.go, ../sm-translate-plugin/admin_harness_test.go, ../sm-grzybyfunkcjonalne-app/boot_test.go ../fonoteka.go/plugins/golem15/user/updates/postgres_test.go, ../fonoteka.go/plugins/golem15/user/admin_harness_test.go, ../sm-translate-plugin/plugin.go, ../sm-translate-plugin/classes/translator.go, ../sm-translate-plugin/classes/translatable.go, ../sm-translate-plugin/controllers/locales.go, modules/cabana/ml_smoke_test.go, ../sm-grzybyfunkcjonalne-app/boot_test.go, .planning/phases/14.2.1-translate-plugin/14.2.1-VALIDATION.md Build the final integration harness on testcontainers Postgres, copying the proven user-plugin fail-closed TestMain/dedicated database pattern. Docker unavailability is a failure for full runs; only an explicit `-short` invocation may skip integration.

TestTranslateEndToEnd must migrate user and translate plugin sets in dependency order, activate the real user and translate plugins plus a test-only neutral fixture controller/model, assemble surf/cabana, and create backend principals with and without golem15.translate.manage_locales. Assert unauthorized Locales access is 403 and authorized schema/list sees en then pl. Send one real fixture create/update body with mltext title and mlmarkdown body maps for en/pl. Assert host columns contain English, only the Polish non-default attribute row exists, safe markdown source round-trips, WithLocale(...,"pl") reads Polish, a missing Polish field falls back to English, and indexed Polish slug lookup finds only the fixture.

Exercise a request with /pl/... and conflicting preferred/session/header candidates to prove URL precedence reaches towel.Locale(ctx) == "pl". Keep all fixture plugin/model registration process-local to the test.

Expand host TestBootUserTranslate to prove both actual gitlink plugins activate, migrations are discoverable, and the Locales controller/permission are registered. It need not duplicate the fixture model. go -C ../sm-translate-plugin test ./... -count=1 -v -run '^(TestTranslateEndToEnd)$' && go -C ../sm-grzybyfunkcjonalne-app test ./... -count=1 -v -run '^(TestBootUserTranslate)$' <fails_when>Non-zero exit; either run prints "--- FAIL", "--- SKIP", "no tests to run", container startup failure treated as skip, or lacks its named "--- PASS" line.</fails_when> <acceptance_criteria> - Integration uses real Postgres and actual gormigrate/party/surf/cabana production paths. - Unauthorized Locales is 403; authorized list includes only seeded en/pl in order. - One nested admin save persists English on the host and Polish in attributes/indexes. - WithLocale Polish read, default fallback, and indexed lookup all pass. - URL prefix wins over all conflicting candidates and locale is context-only. - Fixture registration cannot appear in the production plugin list or host binary. </acceptance_criteria> The entire Phase 14.2.1 user-visible path is proven through production wiring on real Postgres before horizontal test expansion.

Task 2: Complete migration, Translator, Translatable, admin, ML, markdown, and SPA test matrices ../sm-translate-plugin/updates/migrations_test.go, ../sm-translate-plugin/classes/translator_test.go, ../sm-translate-plugin/classes/translatable_test.go, ../sm-translate-plugin/locales_admin_test.go, modules/surf/locale_resolver_test.go, modules/cabana/ml_test.go, modules/cabana/markdown_test.go, modules/cabana/openapi_conformance_test.go, admin/tests/form/MLFields.test.ts, admin/tests/form/MarkdownField.test.ts /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/tests/unit/behaviors/TranslatableModelTest.php, ../sm-translate-plugin/integration_test.go, ../sm-translate-plugin/updates/202610060001_create_winter_translate_locales.go, ../sm-translate-plugin/classes/translator.go, ../sm-translate-plugin/classes/translatable.go, modules/surf/locale_from_principal_test.go, modules/cabana/form_schema_test.go, modules/cabana/field_permission.go, admin/tests/form/DatepickerField.test.ts, admin/tests/form/registry.test.ts Complete the decision and security matrix without adding unrelated PHP-suite surfaces.

Migration tests: assert every final table, column type/default, PHP-indexed column, empty Messages row count, no rainlab/provisional tables, idempotent seed, en/pl exact flags/order/names, no de, and rollback removes all four tables in reverse-safe order. Re-migrate after rollback.

Translator tests: table-drive URL prefix precedence and stripping; preferred locale; remembered locale; absent/present manual flag behavior; weighted Accept-Language reduced only to enabled codes; default fallback; invalid URL/session/header ignored; API resolver preferred → header → default without persistence; plugin-absent surf retains old behavior. Run parallel requests with conflicting locales under -race and assert no cross-request leak.

Translatable tests: default/non-default storage, D-11 fallback, explicit empty translation, invalid locale and undeclared field no-write, sibling JSON field preservation, indexed upsert/update and morph/model isolation, WithLocale context isolation, transaction rollback. Admin tests: exact permission 403/allowed, is_default/sort_order mass-assignment rejection, delete/unset/disabled-default guards, no manage_messages surface, phrasebook keys in en/pl.

Cabana tests: three types compile and unknown mlunknown fails; non-ML nested values remain blocked; ML values lift before projection; malformed/extra locale keys fail; writer failure rolls back host write; writer is not invoked before permission/query checks. Markdown tests include script, iframe, event attributes, javascript/vbscript/data schemes. SPA tests cover selector synchronization, per-locale editing, copy, complete nested payload, and markdown composition without raw-HTML sinks. Extend OpenAPI conformance for all types. go -C ../sm-translate-plugin test ./... -count=1 -race && go test ./modules/surf ./modules/cabana -count=1 -race && npm --prefix admin test -- --run admin/tests/form/registry.test.ts admin/tests/form/MLFields.test.ts admin/tests/form/MarkdownField.test.ts <fails_when>Non-zero exit; Go race detector reports a race; any package/test reports FAIL; integration tests unexpectedly SKIP in the plugin run; or Vitest reports no tests or failures.</fails_when> <acceptance_criteria> - Every D-01..D-17 behavior assigned to code has at least one named assertion or gate check. - Migrate, rollback, and re-migrate are proven against real Postgres. - Parallel locale tests pass under -race with no shared current-locale state. - High threats T-14.2.1-01/02/04/05/06/07/09/10/11/12 have concrete fail-when-broken tests. - No tests require Messages admin, CMS components, AI/theme commands, import/export, or extra locale seeds. </acceptance_criteria> All production branches introduced by Plans 01-03 have focused unit or integration evidence, including race, rollback, authorization, mass-assignment, and XSS cases.

Task 3: Build the fail-closed phase gate, security review, and validation sign-off scripts/check-phase14.2.1.sh, .planning/phases/14.2.1-translate-plugin/14.2.1-SECURITY-REVIEW.md, .planning/phases/14.2.1-translate-plugin/14.2.1-VALIDATION.md scripts/check-phase14.sh, scripts/check-phase12.2.sh, .planning/phases/14.2.1-translate-plugin/14.2.1-VALIDATION.md, .planning/phases/14.2.1-translate-plugin/14.2.1-RESEARCH.md (Security Domain and Validation Architecture), .planning/phases/14.2.1-translate-plugin/14.2.1-01-PLAN.md (T-14.2.1-01..04), .planning/phases/14.2.1-translate-plugin/14.2.1-02-PLAN.md (T-14.2.1-05..08), .planning/phases/14.2.1-translate-plugin/14.2.1-03-PLAN.md (T-14.2.1-09..13) Create `scripts/check-phase14.2.1.sh` with explicit stages: frozen PHP SHA and no PHP diff; tracked-source/module/layout checks; plugin vet/full tests/race; framework cabana+surf vet/tests/race; docs tree and docs build check; admin typecheck/tests/build plus generated OpenAPI/schema/dist cleanliness; proof-host vet/test/build; forbidden-scope scan; security evidence. Use `go -C ` exactly for sibling repositories. Full mode must run Postgres integration and fail if Docker is unavailable; do not treat `-short` as final evidence. Detect zero-test filters by requiring named PASS lines where a filter is used.

Run the requested security-review lane over the local Phase 14.2.1 changes. Produce 14.2.1-SECURITY-REVIEW.md at ASVS L1, preserving unique threat IDs T-14.2.1-01 through T-14.2.1-18. For every high threat, cite the exact source control and executed named test; status must be mitigated or the phase gate remains red. Review locale injection, manage_locales privilege, nested ML JSON, stored XSS, mass assignment, process-wide leakage, and submodule provenance. Do not fabricate an external-API matrix: state No external API integration: this phase ports a compiled plugin and local framework/host contracts only.

Update VALIDATION frontmatter to validated/nyquist compliant/wave 0 complete only after all mapped commands pass. Replace pending rows with exact test names and threat references, record the proof-host/manual Locales SPA check as end-of-phase UAT, and run the phase gate once in full. bash scripts/check-phase14.2.1.sh --all <fails_when>Non-zero exit; any stage is absent/skipped; output contains FAIL, a Go race, no-tests-to-run, unexpected SKIP, stale generated artifacts, forbidden deferred surface, unmitigated high threat, or lacks the final Phase 14.2.1 gate passed line.</fails_when> <acceptance_criteria> - Gate uses go -C ../sm-translate-plugin and go -C ../sm-grzybyfunkcjonalne-app; it does not invent a nested application directory. - Plugin, cabana, surf, admin, docs, generated artifacts, and proof host all have explicit fail-closed stages. - Security review contains every T-14.2.1-NN exactly once and blocks on all high findings. - Validation rows name existing tests/commands and frontmatter is marked validated/nyquist compliant only after green execution. - Gate confirms no Messages admin/manage_messages, CMS locale components, AI/theme commands, import/export, de seed, runtime plugin loading, AutoMigrate, or PHP modifications. </acceptance_criteria> The full three-repository phase gate is green, all high threats are mitigated with executed evidence, and validation is signed off.

<threat_model>

Trust Boundaries

Boundary Description
Test/gate → production claims A no-op, skipped container, or stale generated artifact must not pass
Concurrent requests → context locale Conflicting request locales must stay isolated
Security review → phase completion High findings block completion

STRIDE Threat Register

Threat ID Category Component Severity Disposition Mitigation Plan
T-14.2.1-14 Repudiation phase gate high mitigate Require named PASS/final marker; reject no-tests and unexpected skips
T-14.2.1-15 Information Disclosure concurrent Translator high mitigate Race-enabled conflicting-locale test asserts context isolation
T-14.2.1-16 Tampering migration rollback medium mitigate Up/down/re-up on dedicated Postgres with exact schema assertions
T-14.2.1-17 Tampering generated admin artifacts medium mitigate Regenerate and require clean OpenAPI/TS/dist diff after build
T-14.2.1-18 Elevation of Privilege test fixture high mitigate Fixture plugin is process-local/test-only and absent from generated production imports
T-14.2.1-SC Tampering package installs high mitigate No dependency installation; existing exact pins and lockfile only

ASVS L1: phase completion is blocked on every high finding. </threat_model>

`bash scripts/check-phase14.2.1.sh --all` is the authoritative final command and must end with `Phase 14.2.1 gate passed`. With the executor-started proof host and admin SPA, sign in as an administrator holding `golem15.translate.manage_locales`; open Locales, confirm English and Polski appear in order, edit the permitted name/enabled fields, and verify a user without the permission cannot open the controller.

<success_criteria>

  • Full unit, integration, race, migration rollback, SPA, docs, generated-artifact, and host gates pass.
  • Every locked D-01..D-17 decision is covered.
  • Every high STRIDE threat is mitigated with source and named-test evidence.
  • No deferred surface or new external dependency entered the phase. </success_criteria>
Create `.planning/phases/14.2.1-translate-plugin/14.2.1-04-SUMMARY.md` when done.