Code Quality Audit 2026-07-08 (MC #105042)
Proveo Code Quality Audit — basicfakta
MC #105042 | 2026-07-08 | Audit type: read-only (no code mutations, no deploy, no commits)
Project: /Users/makinja/projects/internal/basicfakta
Note: BUILD-BLUEPRINT.md/CLAUDE.md describe this as a plain Node.js/Express serverless app (Vercel
functions in api/, vanilla JS in src/), NOT the React/Next.js/TS stack implied in the dispatch
description. Tests are hand-rolled Node scripts (no Jest), so "coverage" comes from c8 (Istanbul),
not a framework-native coverage command.
Verdict: CONCERNS
No blocking defects — 0 lint errors, 0 type errors, all 139 tests pass. "CONCERNS" reflects real coverage gaps in security/data-layer code and a large amount of high-complexity, hard-to-maintain logic (esp. one 36-complexity, 270-line function) that should be refactored before this codebase grows further.
1. Lint
Command: npm run lint (eslint src tests)
Result: 0 errors, 35 warnings, exit code 0.
Full output: lint-output.txt
Breakdown by rule:
| Rule | Count |
|---|---|
quotes (must use singlequote) |
25 — all in tests/run-manual-tests.js (orphaned file, see §3) |
no-unused-vars |
7 (analyzer.js x2, heuristics.js, security.js, server.js, ssb-verifier.js, heuristics.test.js, unit-deep.test.js) |
no-useless-escape |
2 (heuristics.js regex patterns) |
No errors anywhere. All fixable via --fix (eslint reports 25 auto-fixable).
2. Type check / Complexity
Command: npm run typecheck (tsc --noEmit)
Result: clean, exit code 0, no output.
Full output: typecheck-output.txt
Caveat (material): tsconfig.json has "checkJs": false and "strict": false, and include is
scoped to src/**/*.js only (excludes api/, tests/). With checkJs: false, tsc does NOT
type-check JS file bodies — this run only confirms the files parse as valid syntax. It is not
meaningful type-safety verification. If real type coverage is wanted, checkJs: true needs
enabling (out of scope for this read-only audit — flagging as a finding, not fixing).
Complexity (measured via one-off npx eslint --rule '{"complexity":["warn",10],...}'
override, read-only, no config file changed). Full output: complexity-output.txt.
Top 10 most complex functions:
| # | Function | File:line | Complexity | Lines |
|---|---|---|---|---|
| 1 | analyzeHeuristics |
src/heuristics.js:507 | 36 | 270 |
| 2 | combineResults |
src/analyzer.js:576 | 29 | 120 |
| 3 | analyzeText |
src/analyzer.js:231 | 23 | 151 |
| 4 | getStats |
src/database.js:72 | 23 | — |
| 5 | fetchTableData |
src/ssb-verifier.js:240 | 22 | — |
| 6 | isPrivateIP |
src/url-extractor.js:28 | 18 | — |
| 7 | extractWebPageContent |
src/url-extractor.js:272 | 17 | — |
| 8 | extractYouTubeContent |
src/url-extractor.js:138 | 16 | — |
| 9 | detectLanguage |
src/language-detector.js:58 | 15 | — |
| 10 | runAllTests |
tests/run-tests.js:66 | 14 | — (orphaned file, §3) |
Also flagged: parseAIResponse (analyzer.js:505, complexity 11), an anonymous arrow fn
(analyzer.js:519, complexity 19), verifyClaim (ssb-verifier.js:303, complexity 12), validateURL
(url-extractor.js:63, complexity 12), one 5-deep nested block (ssb-verifier.js:267, max-depth 5 vs
limit 4).
Largest files by LOC: heuristics.js (847), analyzer.js (717), ssb-verifier.js (500), url-extractor.js (381), middleware/security.js (372).
analyzeHeuristics, combineResults, and analyzeText are the three core pipeline functions and
all exceed complexity 20 — these are the priority refactor candidates (see fix list).
3. Dead code detection
Ran both ts-prune and knip --no-config-hints (one-off npx, no devDependency added to repo).
Full outputs: ts-prune-output.txt, knip-output.txt (also captured in deadcode-output.txt).
ts-prune (scoped to tsconfig's src/**/*.js include, so misses api/ and tests/):
10 items reported, but all are "(used in module)" — i.e. exported but only consumed inside their
own file. These are export-hygiene items (could be de-exported), not actual dead code.
knip (wider scan, more useful signal here) reported:
- Unused files (7):
api/analyze.js,api/feedback.js,api/health.js,src/sentry.js,src/url-extractor.js,tests/run-manual-tests.js,tests/run-tests.js- False positives, verified by grep: the 3
api/*.jsfiles are Vercel serverless entry points invoked by the platform router (pervercel.jsonrewrites), not imported by other modules — knip has no visibility into that root.src/sentry.jsandsrc/url-extractor.jsare both required byapi/analyze.js(confirmed:grep -rn "require.*sentry" api/analyze.jsandgrep -rln "require.*url-extractor" apiboth hit) — knip misses this because it doesn't traceapi/as an entry root either. - Genuine findings:
tests/run-manual-tests.jsandtests/run-tests.jsare NOT referenced by anypackage.jsonscript, CI workflow, or other source file (grep confirmed empty). Superseded bytests/unit-deep.test.js/tests/heuristics.test.jsper naming and content overlap. Safe deletion candidates.
- False positives, verified by grep: the 3
- Unused dependency (1):
@sentry/nodein package.json — flagged unused by knip's dependency graph, but this is also a false positive:src/sentry.js(line uses it) is itself only reached via the untracedapi/root, so the whole chain is invisible to knip. Do not remove. - Unused exports (27): concentrated in
src/middleware/security.js(11 exports),src/rate-limiter.js(5),src/ssb-verifier.js(5),src/database.js(4),src/analyzer.js(2). Same caveat — many of these ARE used byapi/*.jsfiles knip can't see as roots. Not verified individually line-by-line (out of timebox); treat as "needs manual triage," not "confirmed dead."
Net dead-code finding with highest confidence: 2 orphaned test files
(tests/run-manual-tests.js, tests/run-tests.js, ~11KB combined) plus their 25 lint warnings —
both the code and its lint noise disappear if deleted.
4. Test coverage
Three test suites, all passing:
| Suite | Command | Result |
|---|---|---|
| Heuristics | npm test |
50/50 passed |
| Unit-deep | npm run test:unit |
62/62 passed |
| API integration | npm run test:api |
27/27 passed |
| Total | 139/139 passed, 0 failures |
e2e (npm run test:e2e, Playwright) skipped per timebox instruction — unit+integration coverage
sufficient for this audit; explicitly noting the skip, not silently omitting it.
Coverage (coverage/coverage-summary.json, file mtime 2026-07-01 — regenerated fresh during this
audit via npx c8 over heuristics.test.js + unit-deep.test.js combined, and the numbers
reproduced exactly match the existing file, so the "staleness" is cosmetic — the underlying
source hasn't changed since Jul 1 in a way that would move these numbers):
| Metric | % |
|---|---|
| Statements | 66.94 |
| Lines | 66.94 |
| Branches | 84.54 |
| Functions | 61.11 |
Per-file (only files touched by these two suites appear in the report — api/*.js, src/server.js,
src/database.js, src/emailer.js, src/sentry.js are 0% / not instrumented at all, since
api-integration.test.js tests API logic without importing the handler modules under c8):
10 worst-covered files (lines %, lowest first; only instrumented files listed):
| File | Lines % | Functions % | Branches % |
|---|---|---|---|
src/analyzer.js |
45.18 | 44.44 | 23.8 |
src/ssb-verifier.js |
49.8 | 33.33 | 85.71 |
src/middleware/security.js |
46.77 | 38.46 | 89.28 |
src/heuristics.js |
94.33 | 100 | 93.27 |
src/rate-limiter.js |
92.89 | 100 | 85.71 |
src/language-detector.js |
97.05 | 100 | 87.5 |
Not instrumented (0%, no coverage data): api/analyze.js, api/feedback.js, api/health.js, src/server.js, src/database.js, src/emailer.js, src/sentry.js, src/url-extractor.js |
— | — | — |
analyzer.js, ssb-verifier.js, and middleware/security.js are the three weakest-covered files
that DO have partial coverage — and two of them (analyzer.js, security.js) also contain the
highest-complexity functions found in §2. High complexity + low coverage is the same code twice.
Top 5 Prioritized Issues
-
analyzer.jscombines the highest complexity in the codebase with the lowest coverage.combineResults(complexity 29) andanalyzeText(complexity 23, the main pipeline entry) sit in a file at only 45.18% line / 23.8% branch coverage. This is the analysis pipeline's core — the least-tested, hardest-to-reason-about code is exactly where a regression would be most costly. Priority: add branch-level tests for the AI/heuristic-fallback paths, then refactorcombineResultsandanalyzeTextto extract sub-functions (target complexity <15 each). -
analyzeHeuristics(heuristics.js:507) has complexity 36 across 270 lines — the single highest-complexity function found. Coverage is good (94.33%) so behavior is protected, but maintainability is poor: any future pattern addition risks unintended interaction with existing branches. Recommend decomposing into per-category scoring functions before adding more patterns. -
security.js(auth/input-validation middleware) is only 46.77% line-covered and 38.46% function-covered, with 11 flagged (possibly-unused, needs manual triage) exports. Security middleware being the least-tested layer is a QA risk independent of the dead-code ambiguity — recommend a dedicated test pass onsanitize,validateAnalyzeInput,errorHandler, andcorsConfigbefore touching complexity/dead-code cleanup here. -
typecheckis a no-op safety net.checkJs: false+strict: falsemeanstsc --noEmitonly validates syntax, not types — "0 type errors" in this report should not be read as "no type-related bugs." If type-safety is actually wanted here, enablingcheckJs: true(as an incremental, separately-scoped change) would surface real signal; right now the script name is misleading about what it verifies. -
2 orphaned test files (
tests/run-manual-tests.js,tests/run-tests.js) contribute 25 of the 35 total lint warnings (allquotes) and are not wired into any script/CI. Low-risk, low-effort cleanup: delete both files, re-run lint to confirm warning count drops from 35→~9. (Note:api/*.js,src/sentry.js,src/url-extractor.js, and the 27 "unused exports" flagged by knip are NOT safe to delete — verified as false positives/needing manual triage, see §3.)
Evidence files (all under ~/system/evidence/105042/)
audit-report.md— this filelint-output.txt— fullnpm run lintoutputtypecheck-output.txt— fullnpm run typecheckoutputcomplexity-output.txt— eslint with complexity/max-depth/max-lines-per-function rulesdeadcode-output.txt,ts-prune-output.txt,knip-output.txt— dead code detection raw outputscoverage-summary.txt— copy of project'scoverage/coverage-summary.jsoncoverage-run-output.txt— fresh c8 run, unit-deep suite onlycoverage-combined-output.txt— fresh c8 run, heuristics + unit-deep combined (reproduces the committed coverage-summary.json exactly)test-unit-run-output.txt,test-heuristics-output.txt,test-api-output.txt— full test logs for all 3 suites (139/139 passed)
No comments to display
No comments to display