Files
summercms/.planning/phases/13-p-ytarium-api-wishlist-notifications-csv-credentials-public/deferred-items.md
Jakub Zych 931c02db31 docs(13-06): sign off the Phase 13 security review and validation
- 13-SECURITY-REVIEW.md: every T-13 threat with its strictest severity and
  disposition, protecting code, named tests and the 31 removal checks,
  all failing as required; the CSV export logging fix and the Phase 9
  route inventory update
- 13-VALIDATION.md: per-task map 13-01-T1 to 13-06-T3 all green, the gate
  command, coverage per package, Wave 0 ticked, status validated
- REQUIREMENTS.md: API-03, API-04, API-06 and API-07 complete
- deferred-items.md: 13-06 findings (process-wide job dispatcher, scalar
  mapping body, tmpfs quota)
2026-10-03 11:43:39 +02:00

5.0 KiB

Phase 13 deferred items

Out-of-scope findings logged by plan executors. Not fixed by the plan that found them.

From 13-01

  • fonoteka.go TestPhase09SecurityRoutes fails on the current framework. plugins/golem15/fonoteka/admin_phase09_security_test.go:52 reports the cabana admin file and relation routes (/plytadmin/api/v1/{vendor}/{plugin}/{controller}/{id}/files/..., .../relations/{name}/records/{child}..., .../relations/{name}/pivot/{child}) as unexpected. They were added by Phase 12.2 commits e54fd25, afb05b6 and fe9e8ba in summercms.go; the Phase 9 assembled-route inventory in fonoteka.go was not updated. Unrelated to 13-01 (no route was added or removed by the surf overlap change; Routes() is unchanged). Fix: extend the test's expected admin route set, or confirm with the 12.2 owner.
  • FORCE_COLOR=3 in the agent shell fails modules/bonfire TestColorPolicy and TestInjectedOutputCapture. They pass with the variable unset; the suite was run with env -u FORCE_COLOR. Environment, not code.
  • gofmt drift in files 13-01 did not touch: fonoteka.go/plugins/golem15/fonoteka/household_smoke_test.go, summercms.go/modules/tide/flow_test.go, summercms.go/modules/tide/headers_test.go.

From 13-02

  • Path ids between 2^31 and 2^32 bind-fail into an opaque 500 on other routes. pathID (fonoteka.go/plugins/golem15/fonoteka/controllers/api/collections_controller.go:264) parses up to uint32, but the id columns are Postgres integer, so for example DELETE /household/invitations/3000000000 fails to encode the argument and answers the opaque 500 where PHP answers its 404. 13-02 guards only MarkNotificationRead (id > math.MaxInt32 is not found). Fix: have pathID treat values above math.MaxInt32 as 0 (no row), or guard each caller.
  • A Phase 2 fixture of a still-pending route carries a masked provider key text. parity/fixtures/routes/POST___fonoteka_api_v1_ai-credential_test_jwt.yaml:21 holds OpenAI's error text with sk-parit******real (a fake, masked value). The route stays pending until Phase 14 (D-02), which re-records it.
  • TestPhase09SecurityRoutes and the household_smoke_test.go gofmt drift from 13-01's list are still open; 13-02 did not touch them.

From 13-03

  • The general pathID range gap is still open. The 30 wishlist routes use int4PathID (controllers/api/wishlist_albums_controller.go), which treats ids above math.MaxInt32 as no row, so they answer PHP's 404. Other pathID routes are unchanged (see the 13-02 entry).
  • cleanSession handles carry the triggering write's statement until their first chained call. db.Session(&gorm.Session{NewDB: true}) keeps the callback's statement on the handle itself; only a chained call (Where, Raw, Scopes, ...) starts a fresh one, while WithContext clones the old one. 13-03 hit it when conga.Dispatch (which calls WithContext and then Create) received such a handle inside the album insert hook: every digest dispatch inserted two extra album rows. The wishlist code now hands job queues jobDB (cleanSession(...).Scopes()). WriteNotification passes the same kind of handle to lighthouse.Service.Emit; it works today because Emit does not create through it, but any future callee that does WithContext(...).Create(...) on a cleanSession handle has the same bug. Fix: make cleanSession return a chained (fresh-statement) handle.
  • TestPhase09SecurityRoutes (12.2 cabana routes) and the household_smoke_test.go gofmt drift are still open.

From 13-06

  • Resolved: TestPhase09SecurityRoutes. The failure was an outdated route inventory: the 19 cabana relation child, pivot and file routes added by Phase 12.2 all carry the backend guard. The expected set now lists them (fonoteka.go 549840d); the test still fails on any unguarded or unlisted admin route.
  • classes.SetJobDispatcher is process-wide. Like the pubfail counter before 13-05 moved it into the app's service registry, the job dispatcher the album insert hook and the purchase use is installed per process at boot, so in a process that boots several apps the last one wins. Production runs one app per process; tests that boot more than one harness must boot the one whose writes dispatch jobs last (FuzzWriteEndpoints and TestPhase13Threats do). Moving it into the app registry would remove the ordering rule.
  • A JSON scalar body on PATCH import/csv/{id}/mapping. Laravel's json() bag casts a decoded scalar with (array), so a body of 5 becomes [0 => 5] in $request->all(); mappingInput drops a scalar body (it keeps lists and objects). No client sends a scalar body; the difference only changes which detected map a garbage request gets.
  • Hosts with a small /tmp tmpfs. go test ./... in summercms.go failed to link with "disk quota exceeded" on this host while /tmp held stale caches of earlier sessions; the gate and the suites ran with TMPDIR and GOTMPDIR on the home disk. Environment, not code.
  • gofmt drift in fonoteka.go/plugins/golem15/fonoteka/household_smoke_test.go is still open (13-06 did not touch the file).