docs(19.3-06): progress record after Task 4
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# 19.3-06 progress record after Task 4
|
||||
|
||||
Mid-plan record of plan 19.3-06 (gap closure CR-01, WR-01..WR-09), superseded by 19.3-06-SUMMARY.md once that file exists. It is not a SUMMARY: Tasks 5-7 are still to run.
|
||||
|
||||
next: Task 5
|
||||
|
||||
Recorded: 2026-10-15. Plan start: 2026-10-15T20:20:38Z. Ledger base (summercms.go HEAD before the plan): e9ad640.
|
||||
|
||||
## Completed Tasks
|
||||
|
||||
| Task | Name | Commit (repository, hash, subject) | Key files |
|
||||
|------|------|------------------------------------|-----------|
|
||||
| 1 | Tracer: cors:<profile> headers on every refusal (CR-01) | summercms.go 0723536 `fix(19.3-06): cors:<profile> headers on every response of the route (CR-01)` | modules/surf/router.go, modules/surf/cors.go, modules/surf/cors_profile_test.go, modules/surf/README.md, docs/services/routing.md, docs/architecture/request-lifecycle.md, scripts/check-phase19.3.sh |
|
||||
| 2 | Credentialed CORS origin rules (WR-04) | summercms.go e32940d `fix(19.3-06): credentialed CORS refuses wildcard-host and unanchored origins (WR-04)` | modules/surf/cors.go, modules/surf/cors_profile_test.go, modules/surf/README.md, docs/services/routing.md |
|
||||
| 2 | Production cookie Secure rule (WR-05) | summercms.go 4dae833 `fix(19.3-06): production refuses an inferred insecure token cookie (WR-05)` | modules/bouncer/cookie.go, modules/bouncer/cookie_test.go, modules/bouncer/README.md, docs/services/authentication.md |
|
||||
| 2 | Zero CookieConfig defaults (WR-09) | summercms.go 85d8b6a `fix(19.3-06): zero CookieConfig writes SameSite=Lax and Secure (WR-09)` | modules/bouncer/cookie.go, modules/bouncer/cookie_test.go, modules/bouncer/README.md, docs/services/authentication.md |
|
||||
| 3 | Nonce-only api-docs CSP (WR-06) | summercms.go f705343 `fix(19.3-06): api-docs CSP allows only nonce-carrying scripts (WR-06)` | modules/surf/apidocs.go, modules/surf/apidocs_test.go, modules/surf/README.md, docs/services/routing.md |
|
||||
| 3 | Protected uploads refused with public_url (WR-07) | summercms.go caa5b5d `fix(19.3-06): refuse protected uploads into a public_url bucket (WR-07)` | modules/lagoon/attach/store.go, modules/lagoon/attach/bucket.go, modules/lagoon/attach/url_test.go, modules/lagoon/README.md, docs/services/storage.md |
|
||||
| 3 | Turnstile boot warning (WR-08) | summercms.go d0a580c `fix(19.3-06): warn at boot when turnstile routes have no secret (WR-08)` | modules/surf/router.go, modules/surf/cors_profile_test.go, modules/surf/README.md, docs/services/authentication.md |
|
||||
| 4 | Purge without redirects (WR-02) | summercms.go 50a584c `fix(19.3-06): site-cache purge never follows redirects (WR-02)` | modules/cooler/sitecache.go, modules/cooler/sitecache_test.go, modules/cooler/README.md, docs/services/caching.md |
|
||||
| 4 | Queued, coalesced purges and Wait (WR-01) | summercms.go db6a7f5 `fix(19.3-06): queue site-cache purges after commit and coalesce them (WR-01)` | modules/cooler/sitecache.go, modules/cooler/cooler.go, modules/cooler/sitecache_test.go, modules/cooler/example_test.go, modules/cooler/README.md, docs/services/caching.md |
|
||||
| 4 | FAQ plugin test waits (WR-01) | sm-faq-plugin e52b286 `test(19.3-06): wait for the queued site-cache purge before asserting (WR-01)` | site_cache_admin_test.go |
|
||||
| 4 | Menu plugin test waits (WR-01) | sm-menu-plugin 4b42978 `test(19.3-06): wait for the queued site-cache purge before asserting (WR-01)` | site_cache_admin_test.go |
|
||||
| 4 | Journal plugin test waits (WR-01) | sm-journal-plugin 4f633f0 `test(19.3-06): wait for the queued site-cache purge before asserting (WR-01)` | site_cache_admin_test.go, classes/site_cache_test.go |
|
||||
|
||||
## Heads after Task 4
|
||||
|
||||
| Repository | HEAD |
|
||||
|------------|------|
|
||||
| summercms.go | db6a7f5 (this record's commit follows it) |
|
||||
| sm-faq-plugin | e52b286 (planning head fa90e83) |
|
||||
| sm-menu-plugin | 4b42978 (planning head fe27b9a) |
|
||||
| sm-journal-plugin | 4f633f0 (planning head a99e9a1) |
|
||||
| vue-faq-layer | 96b6bc0 (planning-time head, v0.2.0) |
|
||||
| vue-menu-layer | dd0ee35 (planning-time head, v0.2.0) |
|
||||
| vue-journal-layer | 5936f66 (planning-time head, v0.4.0) |
|
||||
|
||||
Nothing pushed or tagged in any repository.
|
||||
|
||||
## Verify results
|
||||
|
||||
- Task 1: PASS. `go vet ./...`, surf short suite, the five named CORS tests (5 top-level PASS), guard_403, turnstile_422 and turnstile_503 (3 subtest PASS), `check-phase19.3.sh go` passed, TestDocsTree ok. Both new tests failed against the old router.go (checked by restoring it locally, then the new file back). Tracer gate: automated verify re-run green, expansion continued.
|
||||
- Task 2: PASS. Surf and bouncer short suites, 7 top-level PASS, TestDocsTree ok.
|
||||
- Task 3: PASS. Vet in both tag modes, surf and lagoon short suites, 6 top-level PASS, TestDocsTree ok.
|
||||
- Task 4: PASS. `go test -short -race ./modules/cooler` ok, 5 top-level PASS, `check-phase19.3.sh plugins` passed, `check-phase19.3.sh docker` RUN and passed (Docker answered for user jin; framework cooler, cabana, attach suites and the FAQ, menu and Journal admin purge suites).
|
||||
|
||||
## Notes for the SUMMARY
|
||||
|
||||
Deviations:
|
||||
- [Rule 2 - docs] Task 1 also updated docs/architecture/request-lifecycle.md ("The wrapping order" list gains the CORS profile step), since the list would otherwise be wrong after the change. Same commit as CR-01.
|
||||
- [Rule 1 - test] Task 2 (WR-05): TestLoadCookieConfigDefaults had production rows with an http and an empty app.url expecting Secure false without error; they now run in development (the production case is an error by design and is covered in TestLoadCookieConfigErrors).
|
||||
- [Rule 1 - test] Task 4 (WR-01): ExampleSiteCacheFromApp printed the purge from the receiver synchronously; it now calls `cooler.SiteCacheFromApp(app).Wait` after the save, and the `purge` doc comment of the example controller says the purge is queued. docs/services/caching.md's src= copy was refreshed with `summer docs:sync`.
|
||||
- [Rule 1 - test] Task 4: "a slow receiver is abandoned and the save stays committed" now asserts the save returns within 500 ms (it no longer waits for the 2 s purge) and waits for the queue before reading the log.
|
||||
|
||||
Decisions taken while executing:
|
||||
- CR-01: `Router.wrap` resolves the profile through `routeCORSProfile` (two profiles stay a boot error), skips the `cors:<profile>` entry in its loop after the unknown-profile check, and wraps the recovered handler in `profileMiddleware` just inside `recordPattern`. `bufferedResponse.commit` merges each comma-separated `Vary` value through `addVary`.
|
||||
- WR-04: anchoring is checked on the parsed expression (`regexp/syntax`): every alternative must begin with `^` and end with `$`, so `^a|b$` is refused as unanchored. Wildcard entries must be `<literal scheme>://*.<rest>` with one `*`. Probe origins: https://cors-probe.invalid, http://cors-probe.invalid, https://cors-probe.com, null.
|
||||
- WR-05: the explicit-false message stays; the inferred case says "auth.cookie.secure resolves to false in the production environment" and names app.url.
|
||||
- WR-09: the zero-config Secure is decided before Name and Path are filled; any unset SameSite becomes Lax.
|
||||
- WR-07: the check sits in `attach.Store` right after the argument checks, before the extension check and before the body is read.
|
||||
- WR-08: the warning goes through `accessLogger(app)` (the published `*slog.Logger`, else `slog.Default`) with attributes `routes` and `production`.
|
||||
- WR-01: `installSiteCache` returns the purger in effect, also one a plugin published before Install (the Journal alias keys), so `Handle.Close` drains whichever purger the app uses. Queued sends use a background context bounded by `SiteCachePurgeTimeout`. Log lines add `coalesced` only when above zero. `Purge` tolerates a nil client field (falls back to a no-redirect client).
|
||||
- Plugin tests: `purgeReceiver` gains a `drain` hook set by `drainFrom(t, app)`; `take` (and so `expectOnePurge` and `expectNone`) waits on `cooler.SiteCacheFromApp(app).Wait` with a 5 s context first. In TestCategoriesAdminFrameworkKeysWin both receivers drain the app's purger.
|
||||
|
||||
What the admin shows for a refused protected upload (Task 3, WR-07): cabana's `writeFileError` has no branch for `attach.ErrProtectedNeedsPrivateBucket`, so it reaches the default path: `logFileFailure` logs the error (its message names storage.uploads.public_url) and the client gets the generic opaque 500 error body. cabana is unchanged, as planned.
|
||||
|
||||
Acceptance notes:
|
||||
- The `git log --oneline --grep='(WR-0N)$'` checks of Tasks 2 and 3 print 4 and 5 lines rather than 3: commits of earlier phases (02) also end with `(WR-04)` and `(WR-07)`. The three 19.3-06 commits per task are present.
|
||||
- `grep -n 'cooler.SiteCachePurger.Wait' modules/cooler/README.md` prints two lines (the Features bullet and the API row); Task 5's cooler README edit rewords the bullet so only the API row names it.
|
||||
Reference in New Issue
Block a user