18 KiB
phase, plan, subsystem, tags, requires, provides, affects, actuals, plan_head_before, plan_head_after, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, coverage, duration, completed, status
| phase | plan | subsystem | tags | requires | provides | affects | actuals | plan_head_before | plan_head_after | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | coverage | duration | completed | status | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 12-p-ytarium-api-collections-and-albums | 05 | testing |
|
|
|
|
|
summercms.go 37595fb6b2c446e65aea5e25d1703fb8d297dba4; fonoteka.go 3b8304ea8cf6fe06af0972066e40e36e3ef2fe9a | summercms.go 1f4e1e01c40a71621db1d9b6bfaa1a23aa266990; fonoteka.go f60c3af06f573cc6f98c60363eeea0a747ef1a8b |
|
|
|
|
|
|
2h15m | 2026-10-02 | complete |
Phase 12 Plan 05: Phase 12 Security Proof, Unit Coverage and Gate Summary
Poisoned-index leak test, route-table scope test, a 41-route write fuzz and one test per T-12 threat, each proven by 25 anchor-exact removal mutations, plus 80%+ coverage in nine packages and a fail-closed check-phase12.sh gate; six parity and safety bugs found and fixed on the way.
Performance
- Duration: about 2h15m (including one interruption, see below)
- Started: 2026-10-02T12:43:34Z (after the 12-04 SUMMARY commit)
- Completed: 2026-10-02T14:57Z
- Tasks: 3/3
- Files modified: 41 code/test files and 41 fuzz seeds across both repositories and the sm-user-plugin submodule, plus 3 planning docs
Accomplishments
TestSearchLeakdrives the realalbums/searchroute on both auth groups with a scripted test-only engine. It shows that stale, mis-scoped, soft-deleted, removed-editor and other-collection ids never show up indataor inmeta.total/last_page. The recount pages by 250 and stops at 1000, and an engine error falls back to SQL.TestRouteTablePhase12checks the assembled router against a table of every Phase 12 route transcribed from routes.php (with line numbers). It covers scopes, JWT-only absences,[0-9]+constraints and throttles.FuzzWriteEndpointsgets its 41 write routes from the route table and sends every server-owned key with hostile values. It snapshots Postgres rows before and after and allows only each route's own columns to change. There is one committed seed per route, and 60 s of fuzzing came back clean.TestPhase12Threatshas 26 subtests named by threat id. Together with the dedicated tests above, every mitigated T-12 threat has a named test.- Unit coverage, framework: beachcomber 84.3%, beachcomber/typesense 95.9%, lagoon 84.4%, lagoon/attach 87.7%, tide 81.4%.
- Unit coverage, application: fonoteka classes 83.6%, controllers/api 81.7%, sm-user-plugin classes 88.7%, sm-user-plugin updates 86.2%.
scripts/check-phase12.sh:--allpasses (vet and tests in both repos, parity 99 ported and 0 failing, recorded 171/171, named tests, coverage, evidence).--removalreports all 25 RC mutations failing their named test, and both trees are clean afterwards.--self-testshows that every detector fails closed.- 12-SECURITY-REVIEW.md, the validated 12-VALIDATION.md (
nyquist_compliant: true, no pending rows), and API-01 and API-02 set to Complete.
Task Commits
- Task 1: poisoned search index leak test (fonoteka.go):
7962bfc(test) - Task 2: token scopes, write-endpoint fuzz, T-12 threat tests (fonoteka.go):
e4122ae(test) - Task 3: unit coverage, gate, sign-off
- summercms.go
1307060fix: broken-image thumbnail for an unusable original (T-12-16) - summercms.go
36983bcfix: Laravel in/not_in on array values - summercms.go
3ac1d64fix: float to string with PHP's 14-digit precision - summercms.go
6e30624test: framework packages to full unit coverage - summercms.go
6f4386cchore: the fail-closed Phase 12 gate - fonoteka.go
64f5496fix: PHP 8 int/string/numeric casts - fonoteka.go
817867dfix: egulias domain part in the Laravel email rule - fonoteka.go
2869747fix: Laravel int/bool query parameters - fonoteka.go
40b2c65test: album_added recipients matched by the payload's album id - fonoteka.go
1ac1911test: fonoteka classes and API handlers to full unit coverage - sm-user-plugin
c258e9ftest: user group codes and class helpers; fonoteka.gof60c3afchore: bump the submodule - summercms.go
1f4e1e0docs: security review, validation sign-off, API-01/API-02
- summercms.go
Files Created/Modified
Listed in the key-files frontmatter. The production changes are limited to modules/lagoon/attach/thumb.go, modules/lagoon/validate_rules.go (plus its README and docs/database/attachments.md), and in fonoteka.go classes/php_values.go, classes/laravel_email.go and controllers/api/request.go. Each change is its own fix commit with a test that fails without it.
Decisions Made
See key-decisions. The most significant: when attach.File.Thumb gets an unusable original, it now follows WinterCMS and stores the broken-image picture instead of returning an error.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] A header-only 30000x30000 PNG made every later listing answer 500 (T-12-16)
- Found during: Task 2 (T-12-16 subtest)
- Fix:
Thumblogs the reason, storesattach.BrokenImagePNGand returns its URL - Files: modules/lagoon/attach/thumb.go, README, docs/database/attachments.md
- Verification: TestThumbBrokenSourceServesPlaceholder (RED: three errors), TestPhase12Threats/T-12-16
- Commit: summercms.go
1307060
2. [Rule 1 - Bug] in/not_in on arrays diverged from Laravel
- Found during: Task 3 (validator truth table)
- Fix: follow
array_diffand!validateIn - Files: modules/lagoon/validate_rules.go
- Verification: TestValidateRulesMatchLaravel (162 recorded cases)
- Commit: summercms.go
36983bc
3. [Rule 1 - Bug] Float-to-string cast used 17 digits instead of PHP's 14
- Found during: Task 3
- Files: modules/lagoon/validate_rules.go
- Verification: TestPHPFloatStringMatchesPHPCast
- Commit: summercms.go
3ac1d64
4. [Rule 1 - Bug] PHP 8 (int), is_numeric and float-string casts diverged
- Found during: Task 3
- Files: classes/php_values.go
- Verification: TestPHPValueCasts (RED: nineteen values)
- Commit: fonoteka.go 64f5496
5. [Rule 1 - Bug] The Laravel email rule's domain part diverged from egulias
- Found during: Task 3
- Files: classes/laravel_email.go
- Verification: TestValidLaravelEmailRFC
- Commit: fonoteka.go 817867d
6. [Rule 1 - Bug] per_page=1e2 and boolean() parsing diverged from Laravel
- Found during: Task 3
- Files: controllers/api/request.go
- Verification: TestRequestCasts
- Commit: fonoteka.go 2869747
7. [Rule 1 - Bug] Flaky test: album_added recipients were matched by position, not by the payload's album id
- Found during: Task 3 (coverage runs)
- Commit: fonoteka.go 40b2c65
Total deviations: 7 auto-fixed (Rule 1). Impact on plan: each fix is needed for API parity or safety and is pinned by a test that fails without it. No scope creep and no new dependency.
Issues Encountered
- Interruption: an API usage limit stopped the first executor in the middle of Task 3, while it was running
scripts/check-phase12.sh --all. At that point all code commits existed, and the security review, validation file and REQUIREMENTS.md edits were still uncommitted. A continuation executor checked the commits and reviewed the uncommitted docs. It re-ran--all(passed, 7 min) and--removal(25/25 fail as required, 3 min, both trees clean afterwards). It then committed the docs as1f4e1e0and wrote this summary. No code was redone. - sm-user-plugin not pushed: the plan asked for the submodule's master to be pushed. This run was told not to push, so
plugins/golem15/useris still 3 commits ahead of origin/master (c65ab3c, 8697007, c258e9f). fonoteka.go's pointerf60c3afrefers to c258e9f, so the submodule has to be pushed before anyone else clones fonoteka.go. - RC-04 is partial by design: with
AlbumsAccessibleByremoved fromScopedAlbums, stale-moved, mis-scoped and soft-deleted still pass, because the active-collection filter and GORM'sdeleted_atfilter still exclude those rows. Only token-pin and removed-editor fail. This is documented in the review.
User Setup Required
None. Push sm-user-plugin master when convenient (see above).
Next Phase Readiness
Phase 12 is complete: all 5 plans have summaries, the gate is green, and API-01 and API-02 are Complete. Next steps are /gsd-verify-work 12, including a human read of 12-SECURITY-REVIEW.md and the manual-only fixture-recording row in 12-VALIDATION.md. Phase 12.2 is being planned in a parallel session.
Phase: 12-p-ytarium-api-collections-and-albums Completed: 2026-10-02
Self-Check: PASSED
- Files exist: scripts/check-phase12.sh, 12-SECURITY-REVIEW.md, 12-VALIDATION.md, search_leak_test.go, fake_engine_test.go, routes_table_phase12_test.go, write_endpoints_fuzz_test.go, phase12_security_test.go, 41 fuzz seeds
- Commits exist:
130706036983bc3ac1d646e306246f4386c1f4e1e0(summercms.go); 7962bfc e4122ae 64f5496 817867d 2869747 40b2c65 1ac1911 f60c3af (fonoteka.go); c258e9f (sm-user-plugin) - Acceptance: t.Run count in search_leak_test.go 21 (>= 9); T-12 subtests 26 (>= 15); RegisterEngine only in _test.go; nyquist_compliant true 1, TBD rows 0; T-12 ids in review equal the union of the plan registers; API-01/API-02 Complete; nine coverage lines >= 80%