lint: type-checked eslint rules and safer form field reads #102
Inga granskare
Etiketter
Inga etiketter
area/backups
area/ci
area/control-panel
area/identity
area/infra
area/observability
area/payments
area/security
area/storage
area/web
blocked
needs-info
needs-triage
ready-for-implementation
type
bug
type
chore
type
docs
type
epic
type
feature
type
task
wontfix
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Inget förfallodatum satt.
Beroenden
Inga beroenden satta
Referens
bitborg/bitborg-web!102
Läser in…
Hänvisa till i nytt ärende
Ingen beskrivning angiven.
Ta bort grenen "lint/type-checked"
Borttagning av en gren är permanent. Även om den borttagna grenen kan fortsätta existera en kort tid innan den faktiskt tas bort, kan det INTE ångras i de flesta fall. Vill du fortsätta?
Enables typescript-eslint's
recommendedTypeChecked(#59), completing the rollout across the fourTS repos. This one needed more care than the three services, for two reasons.
Scoping:
.astrois excluded, deliberatelyType-aware rules need a real TypeScript program per file, and the Astro parser does not reliably
provide one — enabling them on
.astroproduces parsing errors rather than findings, which lookslike a broken config rather than a useful signal. So the type-checked block is scoped to
**/*.{ts,mts,cts}with.astroexplicitly ignored.Also:
vitest.config.tsanddrizzle.config.tsmust NOT go inallowDefaultProjecthere — they arealready in tsconfig's program, and double-claiming them fails to parse. Only the
.mjsconfigs needit. Parse errors are now 0.
A real input-handling bug on the public sign-up endpoint
no-base-to-stringflagged seven sites doingString(form.get("x") ?? "").FormData.get()returnsstring | File | null, so a crafted multipart request that submits a file part where a text fieldis expected yields the literal
"[object Object]"— which then flows intousername,email,countryandcap-tokenbefore validation ever sees it.Fixed with a small
formText()helper (src/lib/form.ts) that returns""for anything that is nota text part, so a non-string field fails validation honestly instead of arriving as
"[object Object]". Five tests, including one asserting explicitly that aFiledoes notstringify.
Applied at all seven call sites in
src/pages/api/signup.tsandsrc/pages/api/renovate.ts.Behaviour is unchanged for ordinary string input.
38
no-unsafe-*findings are deferred, on purpose — see #6533 of them are in
src/lib/auth/**: the OIDC discovery document, JWKS and token responses are parsedas
anyand flow into logic unchecked.The tempting fix is a type assertion, which clears all 38 in an afternoon. That would be worse than
the current state — it asserts a shape nobody verified, so the code would read as type-safe while
being exactly as unsafe as before. A lint rule satisfied by a lie is a regression in a security
boundary, and the honest
anyat least says "unvalidated".So those four rules are
offwith that reasoning recorded inline, and the real fix — zod validationat the boundary, which the workspace already uses elsewhere — is filed as #65. Everything else in
recommendedTypeCheckedgates normally.Smaller items
require-await: 11 in test files → scoped off for**/*.test.ts, matching the sibling repos. Theone production hit (
validateCapToken) gets a targeted disable with its rationale: it is currentlysynchronous but is an awaited public API whose token store is the kind of thing that moves to shared
state, so the promise contract is worth keeping.
no-unnecessary-type-assertion×2 auto-fixed inoidc.test.ts— redundantas CryptoKeyPairwherethe return type was already correct. No assertion weakened; the attacker-key rejection test is
untouched.
Verified:
check,eslint,stylelint,format:check,mdlint,drizzle-kit checkandbuildall pass; 76 tests (71 + 5 new).
Refs #59, #65
9bd1be563da150ae3439