docs(19.3-06): review disposition and validation map after the gap closure
This commit is contained in:
@@ -5,43 +5,43 @@ titles: json
|
||||
findings:
|
||||
- id: CR-01
|
||||
severity: critical
|
||||
disposition: open
|
||||
disposition: fixed
|
||||
title: "`cors:<profile>` headers are missing from every response produced outside the profile middleware (401, 403, 413, 422, 429, 500)"
|
||||
- id: WR-01
|
||||
severity: warning
|
||||
disposition: open
|
||||
disposition: fixed
|
||||
title: "The site-cache purge runs synchronously in the admin request, and bulk delete multiplies it"
|
||||
- id: WR-02
|
||||
severity: warning
|
||||
disposition: open
|
||||
disposition: fixed
|
||||
title: "The purge client follows redirects and forwards the bearer token, including https-to-http on the same host"
|
||||
- id: WR-03
|
||||
severity: warning
|
||||
disposition: open
|
||||
disposition: fixed
|
||||
title: "The shipped purge route refuses every proxied request, so the https/remote mode the Go side advertises cannot work"
|
||||
- id: WR-04
|
||||
severity: warning
|
||||
disposition: open
|
||||
disposition: fixed
|
||||
title: "Credentialed CORS validation only refuses a bare `*`; a wildcard entry or an unanchored pattern still trusts arbitrary origins with credentials"
|
||||
- id: WR-05
|
||||
severity: warning
|
||||
disposition: open
|
||||
disposition: fixed
|
||||
title: "In production, the cookie's Secure flag is inferred false without an error when `app.url` is http or unset"
|
||||
- id: WR-06
|
||||
severity: warning
|
||||
disposition: open
|
||||
disposition: fixed
|
||||
title: "The api-docs CSP allowlists all of jsDelivr for scripts, which cancels the nonce"
|
||||
- id: WR-07
|
||||
severity: warning
|
||||
disposition: open
|
||||
disposition: fixed
|
||||
title: "`storage.uploads.public_url` puts protected (`is_public=false`) files in a publicly served bucket"
|
||||
- id: WR-08
|
||||
severity: warning
|
||||
disposition: open
|
||||
disposition: fixed
|
||||
title: "`turnstile:open` without a secret switches off bot protection in production, with nothing logged"
|
||||
- id: WR-09
|
||||
severity: warning
|
||||
disposition: open
|
||||
disposition: fixed
|
||||
title: "The zero `CookieConfig` does not give the documented default attributes (no SameSite, no Secure)"
|
||||
- id: IN-01
|
||||
severity: info
|
||||
@@ -87,7 +87,7 @@ findings:
|
||||
severity: info
|
||||
disposition: open
|
||||
title: "A published `*bouncer.Turnstile` silently overrides `turnstile.secret`"
|
||||
open: 21
|
||||
open: 11
|
||||
total: 21
|
||||
recorded: 2026-10-15T18:18:43.865Z
|
||||
---
|
||||
@@ -96,16 +96,16 @@ recorded: 2026-10-15T18:18:43.865Z
|
||||
|
||||
| Finding | Severity | Disposition | Source |
|
||||
|---------|----------|-------------|--------|
|
||||
| CR-01 | critical | open | - |
|
||||
| WR-01 | warning | open | - |
|
||||
| WR-02 | warning | open | - |
|
||||
| WR-03 | warning | open | - |
|
||||
| WR-04 | warning | open | - |
|
||||
| WR-05 | warning | open | - |
|
||||
| WR-06 | warning | open | - |
|
||||
| WR-07 | warning | open | - |
|
||||
| WR-08 | warning | open | - |
|
||||
| WR-09 | warning | open | - |
|
||||
| CR-01 | critical | fixed | summercms.go 0723536 (19.3-06) |
|
||||
| WR-01 | warning | fixed | summercms.go db6a7f5; sm-faq-plugin e52b286, sm-menu-plugin 4b42978, sm-journal-plugin 4f633f0 (19.3-06) |
|
||||
| WR-02 | warning | fixed | summercms.go 50a584c (19.3-06) |
|
||||
| WR-03 | warning | fixed | vue-faq-layer a229f6a, vue-menu-layer c4639c2, vue-journal-layer f5d7aac; summercms.go 4d4e379 (19.3-06) |
|
||||
| WR-04 | warning | fixed | summercms.go e32940d (19.3-06) |
|
||||
| WR-05 | warning | fixed | summercms.go 4dae833 (19.3-06) |
|
||||
| WR-06 | warning | fixed | summercms.go f705343 (19.3-06) |
|
||||
| WR-07 | warning | fixed | summercms.go caa5b5d (19.3-06) |
|
||||
| WR-08 | warning | fixed | summercms.go d0a580c (19.3-06) |
|
||||
| WR-09 | warning | fixed | summercms.go 85d8b6a (19.3-06) |
|
||||
| IN-01 | info | open | - |
|
||||
| IN-02 | info | open | - |
|
||||
| IN-03 | info | open | - |
|
||||
|
||||
@@ -39,7 +39,7 @@ created: "2026-10-15"
|
||||
|
||||
## Per-Task Verification Map
|
||||
|
||||
Filled by plan 05. Every row is a stage of `scripts/check-phase19.3.sh`, which runs the named tests and fails when one is missing, skipped or red (go test -json and TAP detectors). Statuses from the run of 2026-10-15 on a Docker host.
|
||||
Filled by plan 05; the plan 06 rows (gap closure, run of 2026-10-15 with `PHASE193_REQUIRE_DOCKER=1 --all` on a Docker host) follow the SC-4 row. Every row is a stage of `scripts/check-phase19.3.sh`, which runs the named tests and fails when one is missing, skipped or red (go test -json and TAP detectors). Statuses from the run of 2026-10-15 on a Docker host.
|
||||
|
||||
| Req | Behavior | Test Type | Automated Command | File Exists | Status |
|
||||
|-----|----------|-----------|-------------------|-------------|--------|
|
||||
@@ -61,6 +61,16 @@ Filled by plan 05. Every row is a stage of `scripts/check-phase19.3.sh`, which r
|
||||
| D-10, D-11 | Plugin purge helpers; Journal framework keys win, alias keys deprecated | unit + docker | `bash scripts/check-phase19.3.sh plugins` (`TestPurgeSiteCacheWithoutTx`, `TestPurgeSiteCacheWithoutPurger`, `TestSiteCacheFrameworkKeysWin`, `TestSiteCacheAliasKeysDeprecated`, `TestSiteCacheNoKeys`); `... docker` (`TestFaqAdminPurgesSiteCache`, `TestMenuAdminPurgesSiteCache`, `TestCategoriesAdminPurgesSiteCache`, `TestPostsAdminPurgesSiteCache`, `TestCategoriesAdminFrameworkKeysWin`) | ✅ three plugins | ✅ green |
|
||||
| D-11 | Nuxt shared purge route (lib and route handler), shared files byte-identical | unit (node) | `bash scripts/check-phase19.3.sh layers` (11 `sitePurge:` names per layer, `cmp` of the three shared files) | ✅ `tests/sitePurge.test.ts` in three layers | ✅ green |
|
||||
| SC-4 | Docs identifiers and links; no consuming application named in framework lines of the phase | docs | `bash scripts/check-phase19.3.sh docs` | ✅ | ✅ green |
|
||||
| SC-1, D-05 (CR-01, plan 06) | `cors:<profile>` headers on every response of the route: guard 401 and 403 (route and group), throttle 429, Turnstile 422 and 503, body limit 413, recovered 500 (JSON and raw); disallowed origin gets `Vary: Origin` only; handler `Vary` merged | unit | `bash scripts/check-phase19.3.sh go` (SURF_TESTS: `TestCORSProfileHeadersOnRefusals`, `TestCORSProfileVaryKeptWithHandlerVary`) | ✅ `modules/surf/cors_profile_test.go` | ✅ green |
|
||||
| D-04 (WR-04, plan 06) | Credentialed CORS: wildcard must be the leftmost host label, patterns anchored, no rule matches the probe origins; global and per profile; non-credentialed configs unchanged | unit | `bash scripts/check-phase19.3.sh go` (SURF_TESTS: `TestCORSCredentialedOriginRules`, `TestCORSAnchoredPatternNoSuffixMatch`, rows in `TestCORSCredentialsWildcardRefused`) | ✅ `modules/surf/cors_profile_test.go` | ✅ green |
|
||||
| D-03 (WR-05, plan 06) | Production refuses a Secure that resolves to false, set or inferred from app.url | unit | `bash scripts/check-phase19.3.sh go` (BOUNCER_TESTS: `TestLoadCookieConfigProductionInferredSecure`, rows in `TestLoadCookieConfigErrors`) | ✅ `modules/bouncer/cookie_test.go` | ✅ green |
|
||||
| D-03 (WR-09, plan 06) | Zero `CookieConfig` writes SameSite=Lax and Secure; unset SameSite is Lax | unit | `bash scripts/check-phase19.3.sh go` (BOUNCER_TESTS: `TestZeroCookieConfigDefaults`, `TestTokenCookieAttributes`) | ✅ `modules/bouncer/cookie_test.go` | ✅ green |
|
||||
| D-17 (WR-06, plan 06) | api-docs `script-src` holds only the per-request nonce; every script tag carries it; SRI unchanged | unit | `bash scripts/check-phase19.3.sh go` (SURF_TESTS: `TestAPIDocsCSPNoHostSource`, `TestAPIDocsServesPinnedPage`) | ✅ `modules/surf/apidocs_test.go` | ✅ green |
|
||||
| D-12 (WR-07, plan 06) | `attach.Store` refuses a protected upload while `public_url` is set, before any blob is written | unit (both tag modes) | `bash scripts/check-phase19.3.sh go` (ATTACH_TESTS: `TestStoreProtectedNeedsPrivateBucket`) | ✅ `modules/lagoon/attach/url_test.go` | ✅ green |
|
||||
| D-18 (WR-08, plan 06) | One boot warning with the route count when turnstile routes have no secret; none with a secret or without such routes | unit | `bash scripts/check-phase19.3.sh go` (SURF_TESTS: `TestTurnstileEmptySecretWarnsAtBoot`) | ✅ `modules/surf/cors_profile_test.go` | ✅ green |
|
||||
| D-10 (WR-02, plan 06) | The purge client never follows a redirect; a 3xx is a failed purge, the token never reaches the Location | unit | `bash scripts/check-phase19.3.sh go` (COOLER_TESTS: `TestSiteCachePurgeNoRedirect`) | ✅ `modules/cooler/sitecache_test.go` | ✅ green |
|
||||
| D-10, D-11 (WR-01, plan 06) | After-commit purges queued, one in flight per purger, later saves coalesced; Wait and Handle.Close drain; a bulk commit sends at most two; plugin admin tests wait for the queue | unit + docker | `bash scripts/check-phase19.3.sh go` (COOLER_TESTS: `TestSiteCachePurgeAsyncCoalesced`, `TestSiteCachePurgeWaitAndClose`); `... docker` (`TestSiteCacheBulkCommitCoalesced`, the FAQ, menu and Journal admin purge suites) | ✅ `modules/cooler/sitecache_test.go`, three plugins | ✅ green |
|
||||
| D-11 (WR-03, plan 06) | Shared purge route accepts proxied requests on `siteCache.allowProxied`, refuses them without it; files byte-identical | unit (node) | `bash scripts/check-phase19.3.sh layers` (LAYER_REQUIRE: `sitePurge: allowProxied lets a proxied request reach the token check`, `sitePurge: route accepts a proxied request with allowProxied and the right bearer`) | ✅ `tests/sitePurge.test.ts` in three layers | ✅ green |
|
||||
|
||||
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
|
||||
|
||||
|
||||
Reference in New Issue
Block a user