fix(ci): enable no-eval for the website application tree (#7699) - #8385
Conversation
eslint's recommended set does not include no-eval, and the base
src/**/*.{ts,tsx} block never enabled it, so eval was unlinted across the
entire application tree. PR #7569 already covered the .mjs generator side
of issue #7699 (the src/**/*.mjs block enabling no-eval, making the
generator's disable directive live) and burned the --max-warnings ceiling
to 0, so the ratchet hunk the issue proposed is obsolete. This adds the
remaining piece: no-eval as a hard-zero 'error' in the base block. The
tree has zero eval sites in .ts/.tsx (all matches are prose in comments),
verified by a clean eslint run (exit 0, 0 warnings).
Closes #7699
UX Review (Fable 5) — ✅ PASSUX-level review of UX-Verdict: PASS Lint-config-only change; no user-facing surface, string, or pixel is touched. [UX-REVIEWED] 348db79 |
Design Review (Fable 5) — ✅ PASSDesign-level review of Design-Verdict: PASS One-line hard-zero lint gate closing a verified real gap; claims check out against the tree (zero eval sites, [DESIGN-REVIEWED] 348db79 |
Opus 4.8 Review — ✅ no blocking findingsReviewed Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
GPT 5.6 Review — ✅ no blocking findingsGPT 5.6 completed its review of This comment is updated in place on each push. Review detailsNo findings. False positive or not applicable? A repository writer can comment: |
NicholasRBowers
left a comment
There was a problem hiding this comment.
Tier 1 auto-approve: fix (1 files). Criteria: no conflict, no requested changes, security path denylist clean, design-doc gate clean, SAST annotations clean, security checklist all-NO, AI reviewers green. Category: single-file CI lint-config fix enabling no-eval for the website application tree with a clear root cause.
Summary
no-evalis not part ofeslint:recommended, and the basefiles: ['src/**/*.{ts,tsx}']block inwebsite/eslint.config.jsnever enabled it — soevalwas unlinted across the entire application tree. This adds'no-eval': 'error'to that base block.The tree is at zero eval sites in
.ts/.tsx(everyevalmatch undersrc/is prose in comments, per the issue's scope check and re-verified here), so this is a hard-zeroerrorlike the native-<select>gate, not awarnriding the--max-warningsbudget.Closes #7699
What #7569 already covered (and why this PR is one line of config)
Issue #7699 proposed three hunks. Two of them landed on main via #7569 before this PR:
src/**/*.mjsblock enablingno-eval(making the generator's line-173 disable directive used and killing the permanent unused-directive warning), andci.ymlnow runsnpx eslint src/ --max-warnings 0, so the "lower the ceiling" hunk is obsolete — the ceiling is already at the floor.The remaining gap was the base application block, which is this PR. Per the issue, the
.mjsgenerator file itself is untouched (its directive stays as-is, now live via the existing.mjsblock).Deliberately out of scope
no-new-func(thenew FunctioninserviceWorkerSkipRules.test.ts) — the reporter explicitly excluded it as a separate decision. Note:no-evalalso does not coverno-implied-eval(string-argsetTimeout/setInterval), so this PR narrows the eval-family gap rather than closing it entirely; those two rules remain a possible follow-up.Pattern harvest
Rule candidate: eslint config self-check — a
// eslint-disable-next-line <rule>directive is only meaningful when some config block matching that file enables<rule>; a directive naming a never-enabled rule is a permanent unused-directive warning. ESLint's ownlinterOptions.reportUnusedDisableDirectives: 'error'(flat config) is the built-in detector for this class and would turn the silent decay into a hard failure; the tree is already at zero unused directives, so it could land as a hard-zero gate. Beyond that, the specific defect class (security-relevant rules likeno-eval/no-new-func/no-implied-evalabsent from the base block) is closed forno-evalby this PR and enumerated as follow-up above.Verification
cd website && npx eslint src/→ exit 0, 0 errors, 0 warnings (measured count 0 under the--max-warnings 0ceiling; the one deliberateevalincrew-ghost-sprite.gen.mjsstays suppressed by its now-live directive)npx tsc -b→ passno linked issue: linked — Closes #7699.
No UI change — lint config only, no screenshots warranted.