docs: close TECH-AXIOS-STORE-COUPLING and add TECH-AXIOS-INTERCEPTOR-TESTS
Removes the closed TECH-AXIOS-STORE-COUPLING entry from BACKLOG.md (the structural decoupling landed in53f6a7b+26a92b3). The git-history search `git log --grep=TECH-AXIOS-STORE-COUPLING` remains the durable closure record, per the backlog hygiene convention. Adds a follow-up entry TECH-AXIOS-INTERCEPTOR-TESTS that captures all four acceptance scenarios (X-Organisation-Id header injection, 401 auth-fail flow, 403+impersonation_ended revocation flow, 4xx/5xx error toast). Phase A audit found that none of these is tested today; the refactor is gedragsneutraal so no regression was introduced, but the gap is real and should not silently outlive the refactor that made it visible. Priority medium per Bert's Phase B sign-off. Appends the debt-closed sentence to the Sessie 1c entry in ARCH-CONSOLIDATION-2026-04.md, citing commit53f6a7b. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -602,43 +602,65 @@ sprint waard, geen meelift-pad.
|
||||
|
||||
---
|
||||
|
||||
### TECH-AXIOS-STORE-COUPLING — Decouple lib/axios.ts from stores layer
|
||||
### TECH-AXIOS-INTERCEPTOR-TESTS — Coverage voor de vier axios-interceptor scenarios
|
||||
|
||||
**Aanleiding:** WS-3 sessie 1c (eslint-plugin-boundaries enforcement)
|
||||
constateerde dat `apps/app/src/lib/axios.ts` 4 imports heeft uit `stores/`
|
||||
(2 statisch op regel 3-4 voor `useNotificationStore` /
|
||||
`useOrganisationStore`, 2 dynamisch op regel 61, 72 voor
|
||||
`useImpersonationStore` / `useAuthStore` uit 1b-iii). De `lib → stores`
|
||||
edge schendt de layered-architecture matrix. Om sessie 1c on-time te
|
||||
landen zijn de 4 sites gemarkeerd met `eslint-disable-next-line` +
|
||||
verwijzing naar dit backlog-item; de structurele fix is bewust uitgesteld
|
||||
naar een dedicated sessie omdat het architectuurwerk is, geen tooling-
|
||||
cleanup.
|
||||
**Aanleiding:** TECH-AXIOS-STORE-COUPLING (gesloten 2026-05-04, zie
|
||||
`git log --grep=TECH-AXIOS-STORE-COUPLING`) heeft `lib/axios.ts`
|
||||
ontkoppeld van de stores via een `registerInterceptors(client, deps)`
|
||||
seam plus `plugins/3.axios-bindings.ts`. Tijdens de Phase A audit van
|
||||
die sessie bleek dat de vier acceptatie-scenarios geen van alle een
|
||||
test hebben — niet vóór en niet ná de refactor. De refactor is
|
||||
gedragsneutraal (1:1 behoud), dus er is geen regressie geïntroduceerd,
|
||||
maar het blijft een echte coverage-gap die we niet wilden meeniggen
|
||||
in de refactor-sessie zelf: refactor-en-test-toevoeging in dezelfde
|
||||
commit-set vernietigt het vermogen om vast te stellen of de tests pre-
|
||||
of post-refactor gedrag specificeren.
|
||||
|
||||
**Wat:**
|
||||
- Decouple `lib/axios.ts` van stores zodat het puur HTTP-infrastructuur
|
||||
wordt. Twee paden, kies bij refactor:
|
||||
- **Approach 1 (preferred starting point):** `lib/axios.ts` exporteert
|
||||
de axios-instance plus een `registerInterceptors(client, deps)`
|
||||
functie die callbacks accepteert (`onAuthFail`,
|
||||
`onImpersonationDrop`, `getActiveOrgId`, `notify(message, level)`).
|
||||
Een nieuwe `plugins/axios-bindings.ts` (mag `stores` importeren per
|
||||
matrix) roept `registerInterceptors` aan bij app-init met closures
|
||||
over de stores.
|
||||
- **Approach 2 (fallback):** event-bus / callback registry; axios.ts
|
||||
emit-eert semantische events (`auth-failed`, `needs-org-header`,
|
||||
`notify-error`) en `plugins/axios-bindings.ts` subscribet.
|
||||
- Verwijder alle 4 `eslint-disable-next-line` comments uit
|
||||
`lib/axios.ts`.
|
||||
- Tests moeten dekken: X-Organisation-Id header injection, 401/403
|
||||
logout flow, impersonation revocation flow, error toast op 4xx/5xx.
|
||||
- Optioneel: meteen ook de static/dynamic import-split in axios.ts
|
||||
uniformeren (nu inconsistent om legacy 1b-iii-redenen).
|
||||
**Wat:** Vitest-tests die de interceptors echt laden (niet via
|
||||
`vi.mock('@/lib/axios')`) en assertions doen tegen een gemockte
|
||||
HTTP-laag (bv. `axios-mock-adapter`). De vier scenarios:
|
||||
|
||||
**Prioriteit:** Middel — geen blokker voor andere workstreams, maar elke
|
||||
maand dat dit blijft staan is een vlek op de boundaries-enforcement
|
||||
geloofwaardigheid. Aanbevolen: meelift met de eerste WS-3 PR die `lib/`
|
||||
of `plugins/` raakt, of een dedicated 2-3 uur sessie na WS-6 sluiting.
|
||||
1. **`X-Organisation-Id` header-injection.** Set een actieve
|
||||
organisatie via `useOrganisationStore`, registreer interceptors
|
||||
met de bindings-deps, fire een outbound request, assert dat de
|
||||
header de actieve ULID bevat. Test ook het null-pad: geen
|
||||
actieve organisatie → header niet gezet.
|
||||
2. **401 → auth-fail flow.** Mock de response op 401, registreer
|
||||
interceptors waarbij `onAuthFail` een spy is, assert dat de
|
||||
spy wordt aangeroepen exact wanneer `useAuthStore.isInitialized`
|
||||
true is en niet gedurende de eerste `/auth/me`-probe (de
|
||||
race-conditie die sessie 1b-iii repareerde — die guard moet
|
||||
blijven werken).
|
||||
3. **403 + `impersonation_ended` → revocation flow.** Mock de
|
||||
response op `403` met body `{ impersonation_ended: true }`,
|
||||
registreer interceptors waarbij `onImpersonationRevoked` een
|
||||
spy is, assert dat de spy precies één keer wordt aangeroepen
|
||||
en dat de generieke 403-toast NIET wordt geactiveerd (dat was
|
||||
een early-return in `axios.ts`, makkelijk per ongeluk te
|
||||
breken bij een toekomstige refactor).
|
||||
4. **4xx/5xx error toast.** Mock 403/404/422/503/5xx/network-error
|
||||
responses, assert dat `notify` de juiste boodschap + level
|
||||
krijgt voor elk geval. 422 met body-`message` moet het
|
||||
server-bericht doorgeven; 422 zonder `message` mag geen toast
|
||||
triggeren (huidige gedrag).
|
||||
|
||||
**Hoe niet:** geen unit-tests die het hele `lib/axios.ts`-module
|
||||
mocken — die testen de seam niet, alleen het mock-framework. De
|
||||
toegevoegde waarde zit in een test-fixture die de echte
|
||||
`registerInterceptors` aanroept met een echte axios-instance die
|
||||
tegen `axios-mock-adapter` praat.
|
||||
|
||||
**Niet in scope:** integratietests die echt door Pinia heen lopen.
|
||||
De seam is bewust callback-injectie zodat tests met spy-callbacks
|
||||
volstaan. Wie de full-stack flow wil dekken (zie `App.vue`'s
|
||||
session-init dance) doet dat met E2E in een latere sprint.
|
||||
|
||||
**Prioriteit:** Middel — de gap is reëel maar niet blokkerend. De
|
||||
6 bestaande `vi.mock('@/lib/axios')`-tests vangen "named export
|
||||
werkt nog" af, en de vier flows zijn manueel via de browser
|
||||
verifieerbaar. Aanbevolen moment: eerste WS-3 PR die `axios.ts`
|
||||
of de bindings-plugin opnieuw raakt, of opvolger van TECH-APP-VITEST
|
||||
als bredere harness-uitbreiding.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user