docs(14.2-03): complete vue-fonoteka-app on Go backend plan

This commit is contained in:
2026-10-11 23:06:04 +02:00
parent a2d19360d2
commit dbdf15da76
3 changed files with 256 additions and 9 deletions

View File

@@ -834,7 +834,7 @@ Plans:
3. Failures against Go are visible (no silent fall-through to PHP); the local stack does not require the production origin.
4. The new glue (env, proxy, CORS, run docs) has tests or a fail-closed check script, delivered in the phase's last plan.
**Plans:** 2/4 plans executed
**Plans:** 3/4 plans executed
Plans:
@@ -845,7 +845,7 @@ Plans:
- [x] 14.2-02-PLAN.md — `scripts/dev-stack.sh` (start, fail-closed guard, logs, e2e verdict), `.env.dev.example`, `.gitignore`, run docs
**Wave 3** *(blocked on Wave 2 completion)*
- [ ] 14.2-03-PLAN.md — Nuxt `E2E_BACKEND=go` switch, realtime rewrite, edit/rate/cover, search and wishlist specs on Go and PHP, Centrifugo origin step, manual UAT session
- [x] 14.2-03-PLAN.md — Nuxt `E2E_BACKEND=go` switch, realtime rewrite, edit/rate/cover, search and wishlist specs on Go and PHP, Centrifugo origin step, manual UAT session
**Wave 4** *(blocked on Wave 3 completion)*
- [ ] 14.2-04-PLAN.md — Unit tests (seed, commands, marker, uploads mount, access log, switch contract) and `scripts/check-phase14.2.sh`
@@ -1316,7 +1316,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
| 13. Płytarium API — wishlist, notifications, CSV, credentials, public routes | 6/6 | In Progress| |
| 14. Domain jobs and external integrations | 6/6 | In Progress| |
| 14.1. OAuth identities and fonoteka me routes (INSERTED) | 2/2 | Complete | 2026-10-05 |
| 14.2. Local Fonoteka frontend on local SummerCMS backend (INSERTED) | 2/4 | In Progress| |
| 14.2. Local Fonoteka frontend on local SummerCMS backend (INSERTED) | 3/4 | In Progress| |
| 14.3. One-command app scaffolding (INSERTED) | 4/4 | In Progress| |
| 15. Journal plugin | 4/4 | Complete | 2026-10-06 |
| 16. grzybyfunkcjonalne.pl on reusable blog views | 5/5 | In Progress| |

View File

@@ -4,16 +4,16 @@ milestone: v1.0
current_phase: 17
current_phase_name: Blog companions
status: executing
stopped_at: Completed 14.2-02-PLAN.md
last_updated: "2026-10-11T17:28:11.705Z"
stopped_at: Completed 14.2-03-PLAN.md
last_updated: "2026-10-11T21:05:57.879Z"
last_activity: 2026-10-11
last_activity_desc: Phase 14.2 execution started
state_head: 05442174b67f1687d07530ef90b4ac6998bf7a50
state_head: a2d19360d290d81339f0c0f519585bcb337472b4
progress:
total_phases: 40
completed_phases: 13
total_plans: 168
completed_plans: 160
completed_plans: 161
gsd_state_version: "1.0"
milestone_name: milestone
---
@@ -216,6 +216,7 @@ Progress: [████░░░░░░] 41%
| Phase 16.3 P04 | 30 min | 3 tasks | 16 files |
| Phase 14.2 P01 | 16 min | 3 tasks | 18 files |
| Phase 14.2 P02 | 27min | 4 tasks | 7 files |
| Phase 14.2 P03 | about 4h | 4 tasks | 23 files |
## Accumulated Context
@@ -706,6 +707,10 @@ Recent decisions affecting current work:
- [Phase 14.2]: dev-stack.sh runs Go processes with TMPDIR=tmp/dev-stack/go-tmp because fileblob renames uploads in from os.TempDir() and fails across devices when /tmp is a tmpfs (deployment fix deferred to Phase 20)
- [Phase 14.2]: dev-stack.sh parses the env file as KEY=value data instead of sourcing it; pnpm dev gets only the NUXT_* values, not the SUMMER_* secrets
- [Phase 14.2]: dev-stack.sh e2e requires a running stack and the guard before Playwright; e2e-verdict refuses skips, flaky, unexpected and zero-expected reports
- [Phase 14.2]: Album model rules see nullable text columns as strings, so an empty format passes like PHP (14.2-03)
- [Phase 14.2]: A 5xx written after the client cancelled the request is logged as 499 by the surf access log (14.2-03)
- [Phase 14.2]: dev-seed creates seeded albums with artist rows and backfills them on rerun (14.2-03)
- [Phase 14.2]: Item 11 PHP cross-check passed by classification: GD-undecodable fixture and missing PHP Centrifugo config, no contract difference (14.2-03)
### Pending Todos
@@ -782,6 +787,6 @@ Items acknowledged and carried forward from previous milestone close:
## Session Continuity
Last session: 2026-10-11T17:08:39.746Z
Stopped at: Completed 14.2-02-PLAN.md
Last session: 2026-10-11T21:05:57.077Z
Stopped at: Completed 14.2-03-PLAN.md
Resume file: None

View File

@@ -0,0 +1,242 @@
---
phase: 14.2-local-fonoteka-frontend-on-local-summercms-backend
plan: 03
subsystem: testing
tags: [playwright, e2e, nuxt, centrifugo, dev-seed, surf, access-log, fonoteka, uat]
requires:
- phase: 14.2-01
provides: fonoteka:dev-seed, storage.uploads.serve, http.access_log, the local backend marker
- phase: 14.2-02
provides: dev-stack.sh up/down/check/e2e/e2e-verdict
provides:
- vue-fonoteka-app E2E_BACKEND=go seed switch (runTinker.ts goMode/goDir, auth.setup.ts Go seed)
- backend-agnostic specs album-edit-rate-cover, album-search, wishlist and the rewritten realtime spec
- repaired smoke, login and album-create specs; tests/e2e/helpers/fonotekaApi.ts
- Go fixes found by the specs and the manual session (empty album format, seeded artist rows, cancelled request logged as 499)
- 14.2-UAT.md with the D-13 session and the D-11 PHP cross-check
affects: [14.2-04 unit tests and gate, phase 20 cutover]
actuals:
tokens: 11639
tasks: 4
commits: 4 # summercms.go: rev-list plan_head_before..plan_head_after = 5, minus 48286b6 docs(17) from another session
plan_head_before: 05442174b67f1687d07530ef90b4ac6998bf7a50
plan_head_after: a2d19360d290d81339f0c0f519585bcb337472b4
fonoteka_head_before: b5363ea99e12b50dc6238438dd3aa60288f08c1e
fonoteka_commits: 3
vue_fonoteka_app_head_before: 984031f646784f640930a25eb7f25b3d268ac4d5
vue_fonoteka_app_commits: 3
tech-stack:
added: []
patterns:
- "Specs self-seed through page.request on the Nuxt origin with the Bearer from the auth_token cookie, Date.now() names, cleanup in finally"
- "Realtime is asserted on Centrifugo JSON protocol frames (connect reply, subscribe reply by id, push), the same for both backends"
- "Go-mode switches read process.env at call time so contract tests can toggle them"
key-files:
created:
- /media/nvme/dev/golem15/fonoteka/vue-fonoteka-app/tests/e2e/album-edit-rate-cover.spec.ts
- /media/nvme/dev/golem15/fonoteka/vue-fonoteka-app/tests/e2e/album-search.spec.ts
- /media/nvme/dev/golem15/fonoteka/vue-fonoteka-app/tests/e2e/wishlist.spec.ts
- /media/nvme/dev/golem15/fonoteka/vue-fonoteka-app/tests/e2e/helpers/fonotekaApi.ts
- .planning/phases/14.2-local-fonoteka-frontend-on-local-summercms-backend/14.2-UAT.md
modified:
- /media/nvme/dev/golem15/fonoteka/vue-fonoteka-app/tests/e2e/helpers/runTinker.ts
- /media/nvme/dev/golem15/fonoteka/vue-fonoteka-app/tests/e2e/auth.setup.ts
- /media/nvme/dev/golem15/fonoteka/vue-fonoteka-app/tests/e2e/.env.example
- /media/nvme/dev/golem15/fonoteka/vue-fonoteka-app/tests/e2e/realtime.spec.ts
- /media/nvme/dev/golem15/fonoteka/vue-fonoteka-app/tests/e2e/smoke.spec.ts
- /media/nvme/dev/golem15/fonoteka/vue-fonoteka-app/tests/e2e/login.spec.ts
- /media/nvme/dev/golem15/fonoteka/vue-fonoteka-app/tests/e2e/fonoteka-item.spec.ts
- ../fonoteka.go/plugins/golem15/fonoteka/classes/album_write_service.go
- ../fonoteka.go/plugins/golem15/fonoteka/classes/album_write_service_db_test.go
- ../fonoteka.go/plugins/golem15/fonoteka/console/dev_seed.go
- ../fonoteka.go/plugins/golem15/fonoteka/dev_stack_smoke_test.go
- ../fonoteka.go/scripts/dev-stack.sh
- modules/surf/accesslog.go
- modules/surf/accesslog_test.go
- modules/surf/README.md
- docs/services/logging.md
- .planning/phases/14.2-local-fonoteka-frontend-on-local-summercms-backend/deferred-items.md
key-decisions:
- "The album model rules see nullable text columns as strings, so an empty format passes like PHP, which skips non-implicit rules for an empty string"
- "A 5xx written after the client cancelled the request is logged as 499 by the surf access log (framework), not remapped per plugin"
- "dev-seed creates albums with their artist rows and backfills seeded albums that have none (album: updated)"
- "dev-stack.sh e2e exports TMPDIR=tmp/dev-stack/go-tmp so the Playwright seed can write covers on a tmpfs /tmp machine"
- "Item 11 (PHP cross-check) passes by classification: the two PHP failures are a GD-undecodable test fixture and a missing PHP Centrifugo config, with no contract difference"
patterns-established:
- "UAT findings that match PHP are recorded with the PHP source reference instead of being changed in Go"
requirements-completed: [QA-05]
coverage:
- id: D1
description: "E2E_BACKEND=go seed switch: Go mode runs fonoteka:dev-seed and fails closed, runTinker throws, the PHP path is byte-identical (additions only)"
requirement: QA-05
verification:
- kind: e2e
ref: "dev-stack.sh e2e auth.setup.ts login.spec.ts smoke.spec.ts fonoteka-item.spec.ts i18n.spec.ts public-share.spec.ts"
status: pass
- kind: other
ref: "git diff HEAD~1 -- tests/e2e/helpers/runTinker.ts | grep -c '^-[^-]' = 0 at 87d6939"
status: pass
human_judgment: false
- id: D2
description: "D-15 Go gate subset (10 spec files) green with zero skips"
requirement: QA-05
verification:
- kind: e2e
ref: "dev-stack.sh e2e (10 files): expected=17 unexpected=0 skipped=0 flaky=0, rerun after the session fixes"
status: pass
human_judgment: false
- id: D3
description: "Edit, rate, cover upload (cover served from /storage/app/uploads/public/ with naturalWidth > 0), search and wishlist add/remove specs, self-seeding"
requirement: QA-05
verification:
- kind: e2e
ref: "album-edit-rate-cover.spec.ts, album-search.spec.ts, wishlist.spec.ts on Go"
status: pass
human_judgment: false
- id: D4
description: "Realtime spec on Centrifugo frames: connect reply, error-free collection: subscribe, push within 15 s"
requirement: QA-05
verification:
- kind: e2e
ref: "realtime.spec.ts on Go with E2E_CENTRIFUGO=1"
status: pass
human_judgment: false
- id: D5
description: "Go fixes: empty wishlist format 201, seeded artist rows, cancelled request logged as 499"
requirement: QA-05
verification:
- kind: integration
ref: "classes#TestSaveAlbumEmptyFormatPassesModelRules, fonoteka#TestDevStackSmoke (artist backfill), surf#TestAccessLogClientClosedRequest"
status: pass
human_judgment: false
- id: D6
description: "Manual D-13 session on the Go stack and D-11 PHP cross-check recorded in 14.2-UAT.md"
requirement: QA-05
verification:
- kind: manual_procedural
ref: ".planning/phases/14.2-local-fonoteka-frontend-on-local-summercms-backend/14.2-UAT.md"
status: pass
human_judgment: true
duration: about 4h including the manual session
completed: 2026-10-11
status: complete
---
# Phase 14.2 Plan 03: vue-fonoteka-app proven on the Go backend Summary
**The vue-fonoteka-app Playwright suite now seeds the Go stack through `fonoteka:dev-seed` (`E2E_BACKEND=go`). Every core flow has a self-seeding spec: edit, rate, cover upload, search, wishlist and realtime over Centrifugo frames. The D-15 subset passes on Go with zero skips. The developer's manual session and the PHP cross-check are on record in 14.2-UAT.md, and the four Go defects they and the specs surfaced are fixed.**
## Performance
- **Duration:** about 4 hours of wall time, including the operator step, the manual session and the PHP run.
- **Completed:** 2026-10-11
- **Tasks:** 4 (2 automated, 1 operator checkpoint, 1 manual checkpoint)
- **Repos:** vue-fonoteka-app (3 commits), fonoteka.go (3), summercms.go (4 before this summary)
## Accomplishments
- **D-14 seed switch.**
- `runTinker.ts` gains `goMode()` and `goDir()`. In Go mode, `backendAvailable()` checks `E2E_GO_BIN`, `runTinker()` throws, and `seedE2EFixtures()` runs `$E2E_GO_BIN fonoteka:dev-seed` and throws on any failure.
- `auth.setup.ts` seeds before login only when `E2E_BACKEND=go`. The PHP lines are unchanged: the change only adds lines.
- **D-16 and D-21 specs.**
- `album-edit-rate-cover`, `album-search` and `wishlist` are new, and `realtime` is a full rewrite without the removed `realtime-*` test IDs.
- The four specs share `helpers/fonotekaApi.ts`.
- **Go fixes:**
- The wishlist form's `"format":""` now gets a 201, as on PHP.
- `dev-seed` attaches artist rows, and a rerun backfills them on albums seeded earlier.
- A cancelled request is logged as 499 instead of 500 (surf access log).
- `dev-stack.sh e2e` keeps the seed's temporary files on the app's device.
- **Records:**
- 14.2-UAT.md has all 11 D-13 items. Items 7, 9 and 10 carry analysed findings, and item 11 is the PHP cross-check.
- `deferred-items.md` lists the follow-ups.
## Task Commits
1. **Task 1 (tracer): seed switch, existing core specs green on Go**
- vue-fonoteka-app `e4f2a9c`: fix(14.2-03): repair stale smoke, login and album-create e2e specs
- vue-fonoteka-app `87d6939`: feat(14.2-03): E2E_BACKEND=go seeds through fonoteka:dev-seed
- Tracer gate: the verify ran green end to end (12/0/0/0) before expanding.
2. **Task 2: Centrifugo origins and namespaces (operator)**
- The operator did it before resume. `dev-stack.sh check` exits 0 and prints no origin or namespace warning.
3. **Task 3: specs for edit, rate, cover, search, wishlist and realtime**
- vue-fonoteka-app `c1f323a`: test(14.2-03): backend-agnostic specs for edit, rate, cover, search, wishlist and realtime
- fonoteka.go `7675d64`: fix(14.2-03): an empty album format passes the model rules like PHP
- summercms.go `66dbd5a`: docs(14.2-03): UAT record with the deferred PHP cross-check
- The PHP cross-check was deferred to Task 4 item 11. Executor runs on 2026-10-11 had no PHP E2E credentials, and the run was never reported as passed.
4. **Task 4: manual session, follow-up fixes and PHP cross-check**
- fonoteka.go `d31e00a`: fix(14.2-03): dev-seed attaches artist rows to the seeded albums
- fonoteka.go `807dfdb`: fix(14.2-03): dev-stack.sh e2e keeps the seed's temporary files on the app device
- summercms.go `4660f95`: fix(14.2-03): access log records a cancelled request's 5xx as 499
- summercms.go `b9de061`: docs(14.2-03): record the manual session, its findings and fixes in UAT
- summercms.go `a2d1936`: docs(14.2-03): PHP cross-check and re-verification recorded in UAT
## Decisions Made
See `key-decisions` in the frontmatter.
## Deviations from Plan
### Auto-fixed Issues
1. **[Rule 3 - Blocking] Three existing gate specs were stale against the current app, on any backend.**
- `smoke` ran with the logged-in storage state, which shows the dashboard on `/`, and expected "Plytarium" where the page says "Płytarium".
- `login` used `/login`, which now serves Polish labels, and clicked before hydration.
- `fonoteka-item` did not fill the now-required artist and format, and its toast race could not succeed.
- Fixed in the specs only; nothing under `app/` changed. Commit `e4f2a9c`.
2. **[Rule 2 - Missing helper] `tests/e2e/helpers/fonotekaApi.ts` added.** It holds the Bearer, create and delete helpers shared by the specs. The file was not in the plan's file list. Commit `e4f2a9c`.
3. **[Rule 1 - Bug, D-11 Go fix] Wishlist create with `"format":""` answered the 500 page.**
- Cause: the model-rule check saw a `*string` pointing to "", not an empty value, so the `in:` rule failed. PHP skips non-implicit rules for an empty string.
- Fixed in fonoteka.go `7675d64`, with a DB test. The framework-level gap is logged in `deferred-items.md`.
4. **[Rule 1 - Bug, session finding A] The artist field in the edit form was empty for seeded albums.** The seed set only `artist_display`. Fixed in fonoteka.go `d31e00a`, and the developer re-verified it.
5. **[Rule 1 - Bug, session finding D] A cancelled request was logged as a 500.**
- Fixed in the framework (summercms.go `4660f95`), with docs.
- The fix belongs in the framework because the status is visible only in the access log, so a per-plugin remap would not reach it.
6. **[Rule 3 - Blocking] The Playwright-run seed failed with `invalid cross-device link`.** A renamed seeded album made the seed write a new cover with the default `/tmp`. Fixed in fonoteka.go `807dfdb`.
7. **[Procedural] The PHP cross-check was not a clean run.**
- Item 11 on PHP gave `expected=4 unexpected=2`. The failures were a GD-undecodable `PNG_1PX` fixture and the PHP env missing a Centrifugo config.
- The developer accepted it as a pass by classification: no contract difference was found. Both issues are in `deferred-items.md`.
### Findings recorded as matching PHP (no change)
- **Item 7:** a new photo is appended and the first photo stays the main cover. Winter's `Sortable` sets `sort_order` to the id, and Go does the same.
- **Item 9:** a same-user edit in a second tab does not refresh the UI, because the frontend's self-echo guard skips it. The Go push payload has the same shape as PHP's.
- **Item 3:** `artist_display` is not rewritten after an artist change. PHP fills it only when it is empty.
**Total deviations:** 6 auto-fixed (3 bugs, 2 blocking, 1 missing helper), 1 procedural. **Impact:** no `app/` change. The Go and framework fixes are parity corrections.
## Issues Encountered
- `pnpm test:contracts` fails 1 of 279 on vue-fonoteka-app HEAD from before this plan: `missing-catalog.test.mjs` finds the word "any" in an `app/` type comment from `984031f`. It is outside D-20 scope and logged.
- `go.log` is appended across `up` runs. The pre-session and session logs are kept as `go.log.pre-uat-20261011` and `go.log.uat-session-20261011`.
## Verification
- **Go gate subset (D-15):** `expected=17 unexpected=0 skipped=0 flaky=0`, `e2e-verdict: passed` after all fixes. go.log shows 0 5xx afterwards.
- **Go tests:**
- fonoteka.go: `go vet ./...` is clean; the fonoteka plugin, classes, console, parity and app-root tests pass.
- summercms.go: `go vet ./...` is clean, `go test -short ./...` passes, and so do `TestDocsTree` and `docs:build --check`.
- **vue-fonoteka-app:** `git diff --name-only 984031f..HEAD -- app` is empty.
## Left running
The Go and Nuxt dev stack (`dev-stack.sh up --detach`) was left running for the developer at the last executor step. The PHP run stopped it and started it again as the coordinator described.
## Next Phase Readiness
Plan 04 can pin the Go seed switch with a contract test (the switch is read at call time) and use `dev-stack.sh` `--guard`, `--self-test` and `--e2e`.
## Self-Check: PASSED
The created spec files, the helper and 14.2-UAT.md exist. Commits:
- vue-fonoteka-app: e4f2a9c, 87d6939, c1f323a
- fonoteka.go: 7675d64, d31e00a, 807dfdb
- summercms.go: 66dbd5a, 4660f95, b9de061, a2d1936