验证(08-10-pwa-cross-version-cache-upgrade-validation): 固化PWA跨版本升级回归

这个提交包含在:
2026-08-10 18:05:15 +08:00
父节点 44737697e5
当前提交 6923f4d1f7
共修改 11 个文件,包含 1095 行新增和 0 行删除
@@ -187,6 +187,73 @@ test.beforeEach(async ({ page }) => {
});
```
## Scenario: Production PWA Cross-Version Upgrade Witness
### 1. Scope / Trigger
- Trigger: a deployment, PWA change or cache-related incident needs evidence that an existing browser profile can move from an old production build to a new build.
- Purpose: verify the real cross-version path; a fresh context that opens only the new build is not upgrade evidence.
### 2. Signatures
- Runner: `bash scripts/qa/run-pwa-cross-version-upgrade.sh`.
- Build inputs: two distinct 12-character synthetic `VITE_BUILD_SHA` values, written to temporary outDirs rather than `client/dist`.
- Browser contract: `serviceWorkers: "allow"`, one loopback HTTP origin, one BrowserContext, single worker and zero retries.
### 3. Contracts
- Build A must first prove its document SHA, active Service Worker controller, Workbox precache and at least one cached A-only hashed JS/CSS asset. If that precondition is missing, stop as `PAUSED`; do not switch to B.
- Synthetic APIs must be served by a loopback HTTP harness. Do not use `page.route` or `context.route`, because a real Service Worker owns worker-originated requests.
- Switch the same server/origin from build A to B, close the A page while retaining the BrowserContext, then revisit the same route. Do not change port, hostname or profile.
- After switching to B, test code must not reload, clear cookie/cache, unregister a worker, create another BrowserContext or emulate hard refresh. Application-owned update behavior is the subject under test.
- Prove B with a joint witness: controller change or worker version change, controller equals the active registration, browser-fetched no-store `sw.js` fingerprint matches build B, document SHA is B and a B-only hashed asset loaded successfully. The constant `/sw.js` URL alone is not version evidence.
- Assert the business route and synthetic session survive, old-only hashed assets leave Cache Storage, and there are no login fallbacks, JS/CSS 404s, chunk/preload errors, page errors or reload loops.
- If the first B witness fails, freeze the safe ledger and stop. Do not add a second navigation or reload to turn the first failure into an intermittent result.
### 4. Validation & Error Matrix
- A build artifacts are not distinct -> `PAUSED`; the harness cannot prove an upgrade.
- A controller or precache is absent -> `PAUSED`; B would be a fresh-install observation.
- A is established and B does not converge without a prohibited action -> `PRODUCT_FINDING`; open a separate PWA product task before changing runtime code.
- Same-profile B witness converges with the complete joint evidence and all negative assertions -> `PASS`.
- Fresh B context passes while the same-profile witness fails -> still `PRODUCT_FINDING`; fresh install does not override upgrade failure.
### 5. Good/Base/Bad Cases
- Good: A controls and caches the page, the same context revisits after an in-place B switch, and auto-update converges to B with zero forced actions.
- Base: a fresh B context is used only as an explicitly labelled harness sanity check and does not satisfy acceptance.
- Bad: start preview on B in a new browser profile, observe the latest shell and report that old users will upgrade correctly.
- Bad: B initially remains on A, then the test calls `page.reload()` once more and reports the recovered state as PASS.
### 6. Tests Required
- Run `bash scripts/qa/run-pwa-cross-version-upgrade.sh`; it must use temporary A/B production builds, loopback-only networking, single worker and zero retries.
- A ledger assertions: document SHA A, active controller, fetched A worker fingerprint match, Workbox precache and cached A-only asset count greater than zero.
- B ledger assertions: controller change, active B controller, fetched B worker fingerprint match, document SHA B, B-only loaded asset count greater than zero and A-only cache count zero.
- Negative assertions: zero login fallback, static 404, page/chunk/preload error and prohibited B-stage test actions; route and synthetic refresh/session remain valid.
- Run `cd client && npm run typecheck && npm run build` plus the current Trellis task/process/governance/sensitive gates.
### 7. Wrong vs Correct
#### Wrong
```ts
const context = await browser.newContext();
await context.newPage().then((page) => page.goto(buildBUrl));
// Latest build loaded, therefore upgrade passes.
```
#### Correct
```ts
// One context and one origin: establish A controller/precache first.
await pageA.close();
switchSameOriginToBuildB();
const pageB = await context.newPage();
await pageB.goto(`${origin}/portal`);
// Observe application-owned convergence; do not reload or clear browser state.
```
## Scenario: UTC Date-Time Display In The Company Time Zone
### 1. Scope / Trigger