test(pwa): browser-level regression for the install-to-activation cache re-poisoning window - #2632
Closed
Chris0Jeky wants to merge 2 commits into
Closed
test(pwa): browser-level regression for the install-to-activation cache re-poisoning window#2632Chris0Jeky wants to merge 2 commits into
Chris0Jeky wants to merge 2 commits into
Conversation
Holds the window open with a waiting replacement instead of racing a poll: the seed is written by the old worker's own CacheFirst handler strictly after the install-time sweep (proven by the marker cache) and strictly before activation (proven by registration.waiting and the pre-#2350 policy answer). This case is RED against current main - see the record on #2475. Not for merge as-is.
…ilure The case is red against the current production build because the forced activate-time re-sweep never runs on the generated worker. Marking it with test.fail keeps the pwa-proof lane exit code meaningful and turns the case red again the moment a production repair makes it pass.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Owner
Author
|
Superseded, closing: this PR was opened by the fix round of the bounded #2475 attempt after its review asked for an expected-failure marker; it carries only the test.fail() case. The production repair is #2639, whose branch already cherry-picks this commit and will land the case without the marker once the sweep really runs. The attempt record stays on #2475. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds one gated Playwright case to
frontend/taskdeck-web/tests/e2e/pwa-proof-strict.spec.tsthat pins the install-to-activation re-poisoning window described in #2475 at browser level, and marks it withtest.fail()because it is red against the current production build.The case installs the #2350-era worker exactly as the existing strict case does, then holds the migration window open with the browser rather than racing a clock:
registerType: 'prompt'parks the replacement worker inwaitinguntil a page sendstaskdeck:skip-waiting, and the real sign-in migration is what sends it. Inside that window the case proves the install-time sweep already finished (its marker cachetaskdeck-pwa-cache-policy-v2is present), proves the old worker is still the controller (it still answers the pre-#2350 policy handshake) and proves the replacement is still waiting. It then seedstaskdeck-static-assetsthrough the OLD worker's own CacheFirst fetch handler, from a real 200 response, not by page script writing into CacheStorage. After sign-in completes the migration it asserts the seeded entry is gone.No production code changes. The stub worker, the route interception and the policy handshake are all test-side.
Root cause
The seeded entry survives the migration on the current build, so the case fails. The reason is already recorded on main in
frontend/taskdeck-web/public/api-cache-cleanup.js(the comment at the end of the file, landed with #2416): the generated worker loads that file withimportScripts()from inside vite-plugin-pwa's asynchronous AMDdefine()factory, which runs in a promise continuation rather than during the worker's synchronous initial evaluation. By the time theactivatelistener is attached, the activate event has already been dispatched, so the forced re-sweep insideevent.waitUntilnever fires. Only the memoised evaluation-time sweep runs, and that sweep has already resolved by the time this case seeds.That is the defect #2475 asks for evidence of, and repairing it needs a production change (an activation hook that registers synchronously, or the injectManifest move), which is out of scope for this branch. So the case ships marked rather than unmarked and red:
test.fail()on the case, with a comment naming [Frontend][PWA] Browser-level regression for the install-to-activation cache re-poisoning window #2475, naming the Keep configured API paths out of PWA runtime caches #2416 inertness record, and saying what to do when the repair lands.Nothing in CI runs this file. It is gated behind
TASKDECK_E2E_PWA_PREVIEW=1and nothing in the repository sets that variable, so the marker governs only the manually driven lane.Verification
Environment: backend from this worktree on
http://localhost:5031(dotnet run --project backend/src/Taskdeck.Api/Taskdeck.Api.csproj -c Debug --no-launch-profile, ASPNETCORE_ENVIRONMENT=Development), production build served bynpx vite preview --port 4173 --strictPortfromfrontend/taskdeck-web. All Playwright runs fromfrontend/taskdeck-webwithTASKDECK_E2E_PWA_PREVIEW=1,TASKDECK_E2E_API_BASE_URL=http://localhost:5031/api,TASKDECK_E2E_FRONTEND_BASE_URL=http://localhost:4173.Lane command, run three consecutive times:
Results:
2 passed (5.8s)exit 0,2 passed (4.4s)exit 0,2 passed (3.9s)exit 0. A fourth run after the marker-semantics check below:2 passed (5.0s)exit 0.Diagnostics printed by the new case on run 1, which are the actual red evidence for #2475:
The seeded entry is present before the migration and still present after it, and the failing assertion under the marker is
expect(entriesAfter.some((u) => u.includes('td-race-seed'))).toBe(false).Marker-semantics check, to prove the marker does not hide a future regression: the final assertion was temporarily inverted to
.toBe(true)so the case would pass, and the same lane command was run. Output:Expected to fail, but passed.then1 failed,1 passed (5.2s), exit 1. The assertion was restored from a backup copy and the lane was re-run green (the fourth run above). The working tree diff after restoring contains only the marker and its comment.Other checks, all from
frontend/taskdeck-webin this worktree:npx eslint tests/e2e/pwa-proof-strict.spec.tsexit 0, no output.npm run typecheck(vue-tsc -b) exit 0.git diff --checkexit 0, no output.Not verified
src/changed, sosrc/tests/pwa/andtest:pwa-generated-workerwere not exercised.TASKDECK_E2E_PWA_PREVIEW=1.Risk notes
test.fail(). That is deliberate and the comment on the marker says so, but it is a red an operator has to read rather than react to.taskdeck-static-assetsonce rather than polling. If a repair lands that sweeps inside a real activatewaitUntil, the read could in principle happen while that sweep is still in flight and report a false red. It cannot produce a false green, so it does not weaken the evidence this branch carries, but the assertion should become anexpect.pollwhen the repair lands.playwright.pwa-proof.config.ts, so on a slow box a failure could surface as an opaque timeout instead of the diagnostics above. Not observed in any of the runs here.askPolicyhelper are duplicated between the two cases in the file. If the handshake constants inpublic/api-cache-cleanup.jsorsrc/pwa/legacyApiCacheWorker.tschange, both copies need updating.Closes #2475