chore: install ts-reset in both portal and app SPAs

Installs @total-typescript/ts-reset 0.6.1 as a dev-dependency in
apps/portal/ and apps/app/. Patches TypeScript's loosest default
types: Array.filter(Boolean) returns non-nullable, JSON.parse
returns unknown, fetch().json() returns unknown, Map.get() strict,
etc.

Configuration: src/reset.d.ts in each SPA imports the reset. Both
tsconfig.json files already include ./src/**/* so the .d.ts is
picked up automatically — no tsconfig edits needed.

Issues surfaced during install:
  - apps/app — 0 pre-install tsc errors in own code; install
    surfaced 2 errors in src/stores/useImpersonationStore.ts
    (both from JSON.parse on sessionStorage content returning
    unknown instead of any). Fixed inline at lines 19 + 123 via
    `as ImpersonationState` casts that make the existing
    trust-in-sessionStorage explicit. Backlog entry
    TECH-TS-IMPERSONATION tracks proper runtime shape validation.
  - apps/portal — 22 pre-existing tsc errors in own code (mostly
    tiptap editor components — tracked as TECH-TS-PORTAL-TSC,
    unrelated to ts-reset). Zero new errors in portal's own code.
    4 additional errors surfaced in tiptap's uncompiled node_modules
    .ts sources (third-party); left as-is.

Neither SPA achieves `tsc --noEmit` clean today — pre-existing
state unrelated to this work package. Build + vitest are the
actual working gates and both remain green:
  - apps/portal: vitest 113/113 passing; production build succeeds
  - apps/app:    (no vitest setup — tracked as TECH-APP-VITEST);
                 production build succeeds

Documentation: /dev-docs/FRONTEND-TOOLING.md added; CLAUDE.md
quality-gates updated.

Backlog: TECH-TS-IMPERSONATION (runtime validation of stored
impersonation state), TECH-TS-PORTAL-TSC (pre-existing portal tsc
errors), TECH-APP-VITEST (Vitest coverage for apps/app).

No production behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 03:58:11 +02:00
parent a043b88bc0
commit 5771a678ef
10 changed files with 136 additions and 2 deletions

View File

@@ -967,5 +967,49 @@ blijft handmatig.
---
## Frontend type-safety
### TECH-TS-IMPERSONATION — runtime validation of impersonation state
**Aanleiding:** ts-reset install (april 2026) surfaced dat
`apps/app/src/stores/useImpersonationStore.ts` blindly vertrouwt
op `JSON.parse(sessionStorage.getItem(...))`. De return is nu
`unknown` in plaats van `any`; we fixten dit door twee `as
ImpersonationState` casts toe te voegen. Die maken de bestaande
trust expliciet maar valideren de shape niet.
**Wat:** vervang beide casts (lines 19 + 123) door een
narrowing-helper `parseStoredState(raw: string | null):
ImpersonationState | null` die het JSON parseert, de verwachte
keys controleert (incl. geneste `impersonatedUser: AdminUser`
fields), en `null` teruggeeft als de shape niet klopt. Zelfde
helper gebruiken bij beide call sites. sessionStorage is in theorie
tamperbaar door lokale users, dus dit is ook een kleine security
verbetering.
**Prioriteit:** Laag — defensive hardening, geen user-impact.
### TECH-TS-PORTAL-TSC — portal tsc --noEmit cleanup
**Aanleiding:** Portal heeft 22 pre-existing tsc errors (+4 in
tiptap node_modules) die niets met ts-reset te maken hebben — meest
TiptapEditor/ProductDescriptionEditor commands en één losse
`@iconify/types` missing, themeConfig type-lowercase issue. CI
checkt tsc niet (build + vitest wel), dus het wordt momenteel
genegeerd. Fix zodra tiptap upgrade beschikbaar komt of per-
component via type-casts.
**Prioriteit:** Laag — niet-blocking, bestaand probleem.
### TECH-APP-VITEST — bring Vitest coverage to apps/app
**Aanleiding:** ts-reset install (april 2026) onderstreepte dat
`apps/app/` geen test-script of `tests/` directory heeft. Portal
heeft wel Vitest-coverage (113 tests); organizer-SPA heeft alleen
build + typecheck als geautomatiseerde gates.
**Wat:** Vitest setup in `apps/app/`, met eerste coverage op de
kern-stores (waaronder `useImpersonationStore.ts` dat nu zonder
runtime-test leeft).
**Prioriteit:** Middel.
---
_Laatste update: April 2026_
_Voeg nieuwe items toe met prefix: ARCH-, COMM-, OPS-, VOL-, ART-, FORM-, SUP-, DIFF-, APPS-, TECH-, UX-_

View File

@@ -0,0 +1,67 @@
# Frontend tooling
Type-safety and quality tooling for the Vue 3 + TypeScript SPAs.
## ts-reset
Installed in both `apps/portal/` and `apps/app/` as a dev-dependency.
Imported via `src/reset.d.ts`:
```typescript
import '@total-typescript/ts-reset'
```
Both SPAs' `tsconfig.json` include `./src/**/*`, so the `.d.ts` is
picked up automatically — no explicit `include` edit needed.
### What it changes
ts-reset patches TypeScript's loosest default types:
- `Array.filter(Boolean)` returns non-nullable `Array<T>` instead
of `Array<T | null | undefined | false | 0 | "">`
- `JSON.parse` returns `unknown` instead of `any`
- `fetch().then(r => r.json())` returns `unknown` instead of `any`
- `Array.includes()` accepts narrower types
- `Map.get()` returns `T | undefined` more strictly
- See <https://github.com/total-typescript/ts-reset> for the full list
### Why this matters
The default TypeScript types for these built-ins lose information
that real code relies on. ts-reset fixes the types to match runtime
behavior, surfacing bugs that were previously hidden.
### Adoption state
**apps/app** — 0 pre-install tsc errors in own code; install
surfaced 2 errors in `src/stores/useImpersonationStore.ts` (both
from `JSON.parse` on sessionStorage content). Both fixed inline via
`as ImpersonationState` assertions that make the existing trust-in-
sessionStorage explicit. A backlog entry (TECH-TS-IMPERSONATION)
tracks proper runtime validation of the stored shape.
**apps/portal** — 22 pre-existing tsc errors in own code (mostly
tiptap editor components — unrelated to ts-reset). ts-reset added
0 new errors in portal's own code. 4 additional errors surfaced in
tiptap's third-party `.ts` sources under `node_modules` (tiptap
ships uncompiled TypeScript and some of its internal `JSON.parse`
call sites fall under ts-reset's tightening). Not our code; left
as-is.
Neither SPA achieves `tsc --noEmit` clean today — that's a pre-
existing state unrelated to this work package. Build + vitest are
the actual CI-relevant gates and both remain green.
### Bypassing
`@ts-expect-error` with comment justification at the call site —
never blanket-disable ts-reset. If a specific reset is genuinely
wrong for the project, document it; the upstream issue is the
backstop.
## Vitest
Runs against `apps/portal/`. `apps/app/` has no test suite yet —
build + typecheck are its only automated gates. Bringing Vitest
coverage to `apps/app` is a separate backlog item.