@dailephd/my-frontend-observer 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,468 @@
1
+ # v0.9.1 Implementation Plan — PWA Hard-Gate Isolation
2
+
3
+ Status: frozen planning authority; implementation not started.
4
+
5
+ Base release: v0.9.0.
6
+
7
+ Target maintenance version: v0.9.1.
8
+
9
+ Primary defect owner: `tests/browser/pwaHardening.test.ts`.
10
+
11
+ This plan is concrete implementation authority for the bounded v0.9.1
12
+ maintenance patch. ROADMAP owns the version-level goal and constraints; this
13
+ file owns the exact correction strategy, sequencing, tests, and gates.
14
+
15
+ ## 1. Problem statement
16
+
17
+ The released PWA browser coverage contains a test named:
18
+
19
+ `HARD GATE: after the server goes down, a reload never presents previously-fetched evidence as current`.
20
+
21
+ That test passes in the normal file/suite order but fails when selected alone
22
+ with Vitest `-t`.
23
+
24
+ The current first PWA `describe` block creates one evidence root, one viewer
25
+ server, and one persistent Chromium context in `beforeAll`. It launches that
26
+ context from a fixed profile under:
27
+
28
+ `.my-dev-kit-workflow/v0.8/batch-08/pwa-profile`.
29
+
30
+ Earlier tests in the same block register/activate the service worker, navigate
31
+ the app, and exercise cache behavior before the hard gate runs. The hard gate
32
+ therefore benefits from state that it did not establish itself. The fixed
33
+ profile can also retain service-worker/cache state across local runs.
34
+
35
+ The hard gate currently waits for an active service-worker registration before
36
+ shutting down the server. An active registration is not equivalent to proving
37
+ that the current page is controlled by that worker or that the shell needed for
38
+ offline reload has definitely been precached.
39
+
40
+ This is a test-isolation defect. There is currently no evidence that v0.9.0
41
+ serves stale evidence as current or that production PWA semantics are wrong.
42
+
43
+ ## 2. Frozen maintenance invariant
44
+
45
+ A test explicitly designated `HARD GATE`, `SECURITY GATE`, or
46
+ `ACCEPTANCE GATE` must:
47
+
48
+ - establish every prerequisite material to the claim it makes;
49
+ - pass when selected independently in a fresh process/environment;
50
+ - not require another test to run first;
51
+ - not depend on a fixed browser profile or historical cache/filesystem state;
52
+ - own and clean up disposable servers, evidence roots, browser profiles,
53
+ contexts, and similar mutable state where those resources are part of the
54
+ experiment.
55
+
56
+ The PWA hard gate is the first explicit application of this invariant.
57
+
58
+ ## 3. Scope
59
+
60
+ v0.9.1 owns:
61
+
62
+ - isolation of the PWA hard-gate experiment;
63
+ - removal of hidden dependency on the historical fixed Chromium profile for
64
+ that gate;
65
+ - explicit service-worker control proof;
66
+ - explicit app-shell cache prerequisite proof;
67
+ - explicit `/api/` cache exclusion proof within the hard gate;
68
+ - explicit server/network-unavailable proof before the offline reload;
69
+ - explicit stale-evidence-absence proof after the offline reload;
70
+ - deterministic cleanup;
71
+ - a dedicated command/gate that runs the hard gate by itself;
72
+ - complete browser/security regression after the correction;
73
+ - documentation reconciliation and normal patch readiness if the user elects
74
+ to publish v0.9.1.
75
+
76
+ ## 4. Explicit exclusions
77
+
78
+ The patch must not, merely to make the test pass:
79
+
80
+ - change production service-worker caching policy;
81
+ - add runtime caching for `/api/` or evidence/media;
82
+ - weaken the stale-evidence hard gate;
83
+ - change Viewer protocol or evidence schemas;
84
+ - add a product feature or CLI command;
85
+ - add v0.10 workflow behavior;
86
+ - add arbitrary sleeps/retries as a substitute for state proof;
87
+ - enforce test ordering;
88
+ - retain a fixed persistent profile as an implicit fixture.
89
+
90
+ If the corrected self-contained experiment fails after all prerequisites are
91
+ proven, stop and classify a product defect before modifying production code.
92
+
93
+ ## 5. Target test architecture
94
+
95
+ The hard gate becomes one complete experiment with this lifecycle:
96
+
97
+ ```text
98
+ fresh temporary evidence root
99
+ → populate deterministic reference/annotation fixture
100
+ → fresh viewer server
101
+ → fresh temporary persistent Chromium profile
102
+ → fresh BrowserContext
103
+ → fresh page
104
+ → navigate while server is live
105
+ → wait for service-worker registration/activation
106
+ → prove current page is service-worker controlled
107
+ → prove required application shell is present in Cache Storage
108
+ → prove /api/ entries are absent from Cache Storage
109
+ → prove live evidence is visible
110
+ → close viewer server
111
+ → prove server/API network is unavailable
112
+ → reload
113
+ → prove shell still renders
114
+ → prove evidence surface reports unavailable
115
+ → prove previously visible evidence identity is absent
116
+ → close context
117
+ → close server if still open
118
+ → remove evidence root
119
+ → remove browser profile
120
+ ```
121
+
122
+ No prior `it()` may be part of this lifecycle.
123
+
124
+ ## 6. Resource ownership
125
+
126
+ ### 6.1 Evidence root
127
+
128
+ Create a test-owned root with `mkdtemp()` under the OS temporary directory.
129
+
130
+ Populate it through the existing canonical deterministic fixture helpers used by
131
+ the current PWA test. The hard gate should still include the real annotation
132
+ needed for annotation/media route coverage when that remains relevant to the
133
+ cache boundary.
134
+
135
+ Remove the root in `finally`/test cleanup even after a failed assertion where
136
+ practical.
137
+
138
+ ### 6.2 Viewer server
139
+
140
+ Start a dedicated viewer server for the hard gate. Do not reuse a server from a
141
+ describe-level `beforeAll`.
142
+
143
+ The server may be closed deliberately in the middle of the experiment; cleanup
144
+ must tolerate an already-closed server.
145
+
146
+ ### 6.3 Chromium profile/context
147
+
148
+ Create a fresh temporary persistent profile, for example:
149
+
150
+ ```ts
151
+ const profileRoot = await mkdtemp(
152
+ path.join(tmpdir(), 'my-frontend-observer-pwa-hard-gate-'),
153
+ );
154
+ ```
155
+
156
+ Launch:
157
+
158
+ ```ts
159
+ const context = await chromium.launchPersistentContext(profileRoot, {
160
+ headless: true,
161
+ });
162
+ ```
163
+
164
+ The hard gate must not use
165
+ `.my-dev-kit-workflow/v0.8/batch-08/pwa-profile`.
166
+
167
+ Remove the temporary profile after closing the context.
168
+
169
+ ## 7. Service-worker readiness proof
170
+
171
+ Before shutting down the server, prove two distinct conditions.
172
+
173
+ First, the registration is ready and has an active worker:
174
+
175
+ ```ts
176
+ const registrationState = await page.evaluate(async () => {
177
+ const registration = await navigator.serviceWorker.ready;
178
+ return {
179
+ active: registration.active !== null,
180
+ scope: registration.scope,
181
+ };
182
+ });
183
+ ```
184
+
185
+ Second, the current page is actually controlled:
186
+
187
+ ```ts
188
+ await page.waitForFunction(
189
+ () => navigator.serviceWorker.controller !== null,
190
+ undefined,
191
+ { timeout: 10_000 },
192
+ );
193
+ ```
194
+
195
+ If the first navigation installs/activates the worker without immediately
196
+ controlling the current page, perform a normal reload while the server is still
197
+ available, then wait for `navigator.serviceWorker.controller !== null`.
198
+
199
+ Do not replace these proofs with a fixed sleep.
200
+
201
+ ## 8. App-shell cache proof
202
+
203
+ Before server shutdown, inspect Cache Storage from the page and prove that the
204
+ Workbox/app-shell precache contains the resources necessary for the offline
205
+ navigation shell.
206
+
207
+ The assertion should use stable build-level expectations rather than hashed
208
+ asset filenames where possible. It must prove that a cache exists and that a
209
+ navigation/app-shell response is available; it must not simply infer cache
210
+ readiness from `registration.active`.
211
+
212
+ If the exact stable cache representation requires inspection during
213
+ implementation, record that concrete representation in the implementation
214
+ report and test the narrowest durable condition.
215
+
216
+ ## 9. API cache exclusion proof
217
+
218
+ The hard gate itself must inspect Cache Storage and prove that cached requests
219
+ do not contain paths beginning with:
220
+
221
+ `/api/`.
222
+
223
+ The separate focused `never caches /api/ responses` test may remain, but the
224
+ hard gate cannot rely on that test having run first.
225
+
226
+ No runtime caching rule for evidence/API may be added.
227
+
228
+ ## 10. Live evidence proof
229
+
230
+ Before server shutdown:
231
+
232
+ - wait for the first real evidence item;
233
+ - prove it is visible;
234
+ - capture/assert a deterministic evidence identity/text such as the fixture's
235
+ `many-regions-candidate` identity.
236
+
237
+ That exact previously visible identity becomes the stale-data negative
238
+ assertion after the offline reload.
239
+
240
+ ## 11. Server/network-down proof
241
+
242
+ After `server.close()`, prove that the authoritative network endpoint is no
243
+ longer available before evaluating offline behavior.
244
+
245
+ Use a bounded direct request/fetch that must fail because the server is gone.
246
+ Do not infer network unavailability solely from the fact that `close()`
247
+ resolved.
248
+
249
+ The cache/service-worker may still satisfy app-shell navigation; the proof of
250
+ server unavailability must target server-backed evidence/API behavior.
251
+
252
+ ## 12. Offline reload proof
253
+
254
+ Reload the controlled page after the server is proven unavailable.
255
+
256
+ Require:
257
+
258
+ - the precached viewer shell still renders;
259
+ - the evidence-dependent UI reaches its explicit unavailable/error state;
260
+ - body/UI text contains the existing unavailable message;
261
+ - the previously visible evidence identity is absent.
262
+
263
+ The safety invariant remains unchanged: a cached shell is permitted; stale
264
+ authoritative evidence is not.
265
+
266
+ ## 13. Cleanup guarantees
267
+
268
+ Cleanup must be deterministic and tolerant of the intentional mid-test server
269
+ shutdown.
270
+
271
+ At minimum:
272
+
273
+ - close page/context;
274
+ - close server if not already closed;
275
+ - remove evidence root recursively;
276
+ - remove temporary persistent profile recursively.
277
+
278
+ Do not leave the hard gate's browser state under `.my-dev-kit-workflow`.
279
+
280
+ If cleanup errors are currently swallowed too broadly, preserve enough
281
+ diagnostic information that a leaked profile/server can be debugged without
282
+ turning cleanup into a product semantic change.
283
+
284
+ ## 14. Other PWA tests
285
+
286
+ The focused tests for:
287
+
288
+ - service-worker registration;
289
+ - manifest validity;
290
+ - API cache exclusion;
291
+ - install-control behavior;
292
+ - standalone display-mode proof;
293
+
294
+ remain valuable and should retain their narrow assertions.
295
+
296
+ Where the first PWA describe still uses a shared persistent context for the
297
+ non-hard-gate tests, replace any fixed historical profile with a fresh
298
+ describe-owned temporary profile and remove it in cleanup. This prevents
299
+ cross-run contamination even when those focused tests continue sharing state
300
+ within their describe.
301
+
302
+ The hard gate itself must not share that context/profile.
303
+
304
+ ## 15. Dedicated isolated command
305
+
306
+ Add one repository-owned command so isolation remains a permanent gate.
307
+
308
+ Preferred package script:
309
+
310
+ ```json
311
+ "test:pwa-hard-gate": "vitest run --config vitest.browser.config.ts tests/browser/pwaHardening.test.ts -t \"HARD GATE\""
312
+ ```
313
+
314
+ Use repository naming conventions if a better exact script name already exists,
315
+ but keep one explicit isolated command.
316
+
317
+ This command must start from normal test setup and must not require another test
318
+ to have run first.
319
+
320
+ ## 16. Security/readiness integration
321
+
322
+ The isolated hard-gate command must be part of the applicable security or
323
+ release-readiness validation path so future full-suite success cannot hide a
324
+ regression in test independence.
325
+
326
+ Do not remove the normal complete
327
+ `tests/browser/pwaHardening.test.ts`/browser/security execution. The isolated
328
+ proof is additive.
329
+
330
+ If adding the dedicated command to `npm run test:security` would cause the
331
+ same expensive test to run redundantly in a harmful way, keep the command
332
+ separate and wire it into pre-release readiness explicitly. Choose the smallest
333
+ repository-consistent integration, and document the decision.
334
+
335
+ ## 17. Implementation sequence
336
+
337
+ ### Batch 1 — Isolate and strengthen the hard-gate experiment
338
+
339
+ Primary owner:
340
+
341
+ `tests/browser/pwaHardening.test.ts`
342
+
343
+ Expected work:
344
+
345
+ - replace hard-gate shared state with test-owned fresh resources;
346
+ - replace fixed persistent-profile dependence with temporary profile ownership;
347
+ - add explicit active-registration and current-client-controller proof;
348
+ - add explicit shell-cache and API-cache-exclusion proof;
349
+ - add explicit server/API-down proof;
350
+ - preserve the existing offline-shell/stale-evidence assertions;
351
+ - make cleanup deterministic;
352
+ - make the hard gate pass independently.
353
+
354
+ Batch 1 acceptance:
355
+
356
+ ```text
357
+ isolated HARD GATE PASS
358
+ full pwaHardening.test.ts PASS
359
+ no production file modified
360
+ no fixed-profile dependence in the hard gate
361
+ ```
362
+
363
+ If the isolated experiment still demonstrates stale evidence or cannot satisfy
364
+ the existing product contract after all prerequisites are proven, STOP with a
365
+ product-defect verdict before Batch 2.
366
+
367
+ ### Batch 2 — Freeze the isolation gate and run full regression
368
+
369
+ Expected work:
370
+
371
+ - add the dedicated package script;
372
+ - add the isolation proof to the appropriate security/readiness path;
373
+ - update development/CI/current-state documentation from planned to
374
+ implemented wording;
375
+ - run complete unit/browser/security/build/docs/package validation;
376
+ - perform patch release readiness if v0.9.1 publication is requested.
377
+
378
+ Batch 2 acceptance:
379
+
380
+ ```text
381
+ test:pwa-hard-gate PASS
382
+ full browser suite PASS
383
+ security suite PASS
384
+ typecheck PASS
385
+ lint PASS
386
+ unit tests PASS
387
+ build PASS
388
+ docs check PASS
389
+ pack dry run PASS
390
+ no unintended production semantic change
391
+ ```
392
+
393
+ ## 18. Required implementation tests
394
+
395
+ At minimum prove:
396
+
397
+ 1. hard gate passes alone from a clean temporary profile;
398
+ 2. hard gate passes when the whole PWA file runs;
399
+ 3. hard gate passes in the normal full browser suite;
400
+ 4. hard gate passes in the security validation path;
401
+ 5. repeated isolated executions do not depend on state from the prior run;
402
+ 6. no `/api/` request is present in Cache Storage at the shutdown boundary;
403
+ 7. the current client is controlled before shutdown;
404
+ 8. the shell cache prerequisite is explicitly established;
405
+ 9. the server/API is explicitly unavailable before offline reload;
406
+ 10. stale evidence identity is absent after reload;
407
+ 11. temporary profile/evidence state is cleaned up.
408
+
409
+ ## 19. Production-code escalation rule
410
+
411
+ Expected initial classification:
412
+
413
+ ```text
414
+ TEST_DEFECT
415
+ PRODUCT_CHANGE_REQUIRED = false
416
+ ```
417
+
418
+ If the corrected clean-state experiment fails because production behavior
419
+ actually violates the stale-evidence safety contract:
420
+
421
+ - do not loosen the test;
422
+ - do not add retry/sleep until it happens to pass;
423
+ - capture the exact runtime evidence;
424
+ - stop the maintenance batch;
425
+ - report a product defect;
426
+ - revise this plan explicitly before changing production PWA/service-worker
427
+ code.
428
+
429
+ ## 20. Version/package expectations
430
+
431
+ v0.9.1 is a maintenance patch. No canonical evidence schema version is expected
432
+ to change.
433
+
434
+ No new runtime dependency is expected.
435
+
436
+ If implementation remains test/documentation-only, package runtime bytes may be
437
+ unchanged apart from version/docs if the user elects to publish v0.9.1. The
438
+ release decision must be made after implementation evidence rather than by
439
+ inventing a product change solely to justify a package release.
440
+
441
+ ## 21. Documentation reconciliation after implementation
442
+
443
+ When implementation passes:
444
+
445
+ - `CURRENT_STATE.md` changes from planned to implemented status;
446
+ - `ROADMAP.md` records v0.9.1 as implemented/released only when that state is
447
+ actually true;
448
+ - `DEVELOPMENT.md` and `CI_CD.md` retain the durable gate-isolation rule;
449
+ - `CHANGELOG.md` receives the actual implemented correction under
450
+ `[Unreleased]` or the final v0.9.1 section at release preparation;
451
+ - historical v0.9.0 reports remain unchanged.
452
+
453
+ ## 22. Final implementation verdicts
454
+
455
+ Use a precise result.
456
+
457
+ Expected success before release:
458
+
459
+ `PASS_V0_9_1_PWA_HARD_GATE_ISOLATION`
460
+
461
+ Use a blocker such as:
462
+
463
+ `BLOCKED_V0_9_1_PRODUCT_PWA_DEFECT_DISCOVERED`
464
+
465
+ if the self-contained experiment reveals a real production failure.
466
+
467
+ Do not claim v0.9.1 released until the normal release workflow actually
468
+ completes.