diff --git a/dev-docs/BACKLOG.md b/dev-docs/BACKLOG.md index c1841ad4..0756d2ca 100644 --- a/dev-docs/BACKLOG.md +++ b/dev-docs/BACKLOG.md @@ -987,54 +987,77 @@ tamperbaar door lokale users, dus dit is ook een kleine security verbetering. **Prioriteit:** Laag — defensive hardening, geen user-impact. -### TECH-TS-PORTAL-TSC — `tsc --noEmit` baseline reduction (apps/portal) +### ~~TECH-TS-PORTAL-TSC — `tsc --noEmit` baseline reduction (apps/portal)~~ -**Priority:** medium → **high before S3b organizer UI lands.** -**Scope:** 22 pre-existing TypeScript errors in `apps/portal/src/` -own code surfaced by foundation-tooling commit 3 (ts-reset install). +**Status: closed 2026-04-25** — `pnpm exec vue-tsc --noEmit` exits +clean in `apps/portal/`. Sprint commits: `f7bb864` (tiptap 2.27.2 +upgrade) + `a7ccd2b` (4 long-tail fixes). -**Trigger to upgrade priority to "must-fix-now":** any S3b -form-builder organizer UI commit. Launching new TypeScript code on -top of an unverified existing-error baseline produces unactionable -compile output ("which errors are mine?"). Reduce to zero before -S3b starts. +**Correction to the original framing:** the entry initially read +"22 pre-existing tsc errors in own code + 4 in tiptap node_modules". +The "4" was the **delta** that ts-reset added in foundation-tooling +commit 3 (ts-reset's `JSON.parse → unknown` tightening surfaced 4 +new tiptap errors), **not** the absolute pre-existing tiptap baseline. +The actual absolute count was **~707 tiptap node_modules errors**, +silently invisible because the project's CI runs build + vitest only, +not `vue-tsc`. -**Triage approach (mirror Larastan reduction pattern):** -1. `cd apps/portal && pnpm exec vue-tsc --noEmit 2>&1 | grep "src/" > /tmp/tsc-errors.txt` -2. Group by error code (TS2339 property-not-found, TS2345 argument - type, TS18047 possibly null, TS2322 not-assignable, etc.) — - typical top categories on a Vue-3 + Pinia codebase. Foundation- - tooling triage already noted clusters in TiptapEditor/ - ProductDescriptionEditor commands, a `@iconify/types` missing - import, and a themeConfig `Lowercase` mismatch -3. Fix per-category in scoped commits (mirror Larastan reduction - sprints — one category per PR if >5 occurrences, combine if <=5) -4. Add `pnpm exec vue-tsc --noEmit` to a pre-commit hook or CI as - blocking gate once own-code errors hit zero (CI integration is - tracked separately; the gate enforcement is what closes the - "new code introduces no new errors" discipline gap) +**Root cause of the 707:** tiptap 2.27.1's `dist/index.d.ts` +re-exported from `'../src/CommandManager.js'` and ~22 similar lines +that referenced `.js` files which did not exist (only `.ts` source). +With `moduleResolution: "Bundler"`, vue-tsc fell through and pulled +tiptap's entire uncompiled source tree into the program. Tiptap +2.27.2 (a patch release) fixed the dist exports to use sibling- +relative paths (`./CommandManager.js`) that resolve correctly to +the existing `dist/*.d.ts` siblings. -**Tiptap upstream errors (4 in node_modules):** -`skipLibCheck: true` is **already set** in both SPAs' `tsconfig.json` -(only one tsconfig variant exists per SPA; no `tsconfig.app.json` -or `tsconfig.node.json` split). Despite that, the 4 errors persist -because **tiptap ships uncompiled `.ts` source files** in -`node_modules/.../@tiptap/core/src/`, not `.d.ts` declaration -files. `skipLibCheck` only suppresses checking of `.d.ts` files; -it does **not** apply to raw `.ts` files that vue-tsc pulls in -through the import graph. Real options, in order of preference: -(a) upgrade `@tiptap/*` to a release that ships only `.d.ts` -(check upstream — the policy may already have changed in newer -majors); (b) add a focused `exclude` glob for tiptap's -`node_modules/.../src/**/*.ts` if the upgrade is blocked. Avoid -blanket `node_modules` excludes — they can break import resolution -in vue-tsc. +**Why `skipLibCheck` did not help:** `skipLibCheck: true` was +already set in `apps/portal/tsconfig.json` (and `apps/app/`) +**but only suppresses checking of `.d.ts` declaration files**. +Tiptap's uncompiled `.ts` source files in `node_modules/.../src/` +were raw `.ts`, not `.d.ts`, so they bypassed `skipLibCheck` once +the import graph reached them. The 2.27.2 packaging fix made the +import graph stop there, no exclusion needed. -**Out of scope:** runtime fixes for behaviors that surface as type -errors but aren't actually broken at runtime. If a fix requires -reasoning about runtime behavior (not just type narrowing), surface -it as a separate ticket — TypeScript-correctness is this sprint's -remit, runtime-correctness is a different concern. +**Final error tally:** +- Pre: 729 vue-tsc errors (~22 own-code, of which 18 were TS2339 + downstream of tiptap's broken types; ~707 in node_modules/@tiptap) +- Post-tiptap-upgrade: 4 own-code (the tiptap-independent stragglers: + `vite.config.ts` TS7006, `themeConfig.ts` TS2322 via + `LayoutConfig.title` `Lowercase` over-constraint, + `build-icons.ts` TS2307 missing `@iconify/types`, + `casl.ts` TS2345 vue-router meta cast) +- Post-long-tail-fixes: 0 own-code, 0 node_modules + +**Aftermath:** +- The S3b form-builder organizer UI now lands on a verified + zero-error baseline. +- The "new code introduces no new errors" discipline still depends + on a CI gate — see TECH-PORTAL-TSC-CI-GATE follow-up. + +### TECH-PORTAL-TSC-CI-GATE — vue-tsc as a blocking gate for apps/portal + +**Aanleiding:** TECH-TS-PORTAL-TSC reached zero in commits `f7bb864` ++ `a7ccd2b`, but the project has no pre-commit infrastructure +(no husky, lefthook, or simple-git-hooks) and CI does not run +`vue-tsc` either. Without a blocking gate, the baseline can drift +back to non-zero between commits — exactly the discipline gap +that produced the 22 pre-existing errors in the first place. +**Wat:** +- Add `pnpm exec vue-tsc --noEmit` as a CI step in the workflow that + runs portal build/vitest (most natural location). +- OR introduce a pre-commit infrastructure (lefthook is lighter than + husky for monorepos) and run vue-tsc on portal-touching commits. +- Either path: the gate must fail the run on any new vue-tsc error + in `apps/portal/`. +**Out of scope:** extending the same gate to `apps/app/` — that +SPA still has a different mix of errors and would be a separate +sprint (out of scope today, would land alongside TECH-APP-VITEST or +later). +**Prioriteit:** Middel — without the gate, TECH-TS-PORTAL-TSC's +zero state has no enforcement. Should land before S3b organizer UI +work to keep that sprint's "new code introduces no new errors" +discipline mechanically enforceable. ### TECH-APP-VITEST — apps/app Vitest setup