BasicFakta SaaS platform — product docs, architecture, deployment. Overview BasicFakta Overview SaaS platform — product docs, architecture, deployment. Owner: John Last Verified: 2026-02-17 Contents To be populated from BasicFakta project documentation Active Tasks Last Verified: 2026-02-17 | Owner: John BasicFakta — Active Tasks Open Tasks No currently active BasicFakta tasks in Mission Control. Blocked Tasks #100 — Improve fake news detection accuracy (BLOCKED) Reason: Backend API code not in repo (hosted separately on basicfakta.no) Cannot proceed: Algorithm source code not accessible Dependency: Backend import required Test status: 23/65 tests fail, factScore > 30 for known fake news Resolution: Need backend source code from Alem Recently Completed 13-item audit — Security, accessibility, UX improvements (commit ce800c2) Deployment — Vercel auto-deploy configured GitHub auth fix — Switched from SSH to HTTPS (gh CLI token) Planned Work Backend integration — Import backend source code to repo Algorithm improvements — Once backend is accessible Test coverage — Improve from 42/65 passing to 65/65 Accuracy tuning — Reduce false positives for known fake news Key Decisions Last Verified: 2026-02-17 | Owner: John BasicFakta — Key Decisions Strategic Decisions Backend Separation (Date TBD) Decision: Host backend API separately from frontend repo. Rationale: Protects proprietary algorithm, easier to scale backend independently. Trade-off: Makes algorithm improvements harder, blocks accuracy work. Current impact: Task #100 blocked pending backend import. Deployment on Vercel (Date TBD) Decision: Auto-deploy from GitHub main branch via Vercel. Rationale: Zero-config deployment, global CDN, preview deployments. Status: Active and working. Technical Decisions Frontend Stack Modern web framework (details in repo) Vercel hosting GitHub version control (HTTPS auth) Security Measures (2026-02) Decision: Implement comprehensive security hardening. Implemented: Input sanitization (XSS prevention) Rate limiting (authentication bypass fix) API key sanitization Security headers via vercel.json Accessibility (2026-02) Decision: Achieve WCAG 2.1 compliance. Implemented: Screen reader support Keyboard navigation Mobile-friendly touch targets Development Decisions GitHub Auth (2026-02) Decision: Switch from SSH to HTTPS authentication. Reason: ~/.zshenv had GITHUB_TOKEN=CHANGE_ME placeholder that overrode gh CLI token. Fix: Commented out line 40, use gh CLI token (ghp_ PAT in ~/.config/gh/hosts.yml). Test Strategy (Current) Status: 42/65 tests passing Blocker: 23 tests fail due to backend algorithm issues (factScore too high for known fake news) Next step: Backend import required before test fixes Operational Decisions Email Domain Domain: basicfakta.no Status: Email monitoring blocked (task #79) Issue: Missing IMAP credentials (host/port/user) Required from Alem: IMAP access details Project Overview Last Verified: 2026-02-17 | Owner: John BasicFakta — Project Overview What is BasicFakta? BasicFakta (basicfakta.no) is a SaaS fact-checking tool that analyzes news articles and claims to detect misinformation. It uses AI-powered algorithms to generate "fact scores" indicating the likelihood that content is fake news. Current Status Phase: Deployed (live at basicfakta.no) Type: Internal product / SaaS offering Backend: External hosted API (not in main repo) Frontend: Repository available Features Fact Checking — Analyze news articles and claims Fact Scoring — 0-100 score (lower = more likely fake) URL Extraction — Extract and analyze URLs from articles Share Results — Share fact-check results Mobile Support — Responsive design Tech Stack Frontend: Modern web framework Backend API: Hosted separately at basicfakta.no Algorithm: Proprietary fake news detection (not open source) Recent Work Audit & Fixes (2026-02) 13 audit items fixed and deployed (commit ce800c2): Critical Fixes url-extractor.js created — Was missing, causing extraction failures XSS vulnerability — Input sanitization implemented Rate limit bypass — Fixed authentication bypass API key sanitization — Sensitive data protection Medium Improvements Security headers — Added via vercel.json Email validation — Enhanced validation SEO meta tags — Improved search visibility WCAG accessibility — Screen reader support, keyboard navigation Mobile UX — Touch-friendly interface Share results — Social sharing functionality Loading states — Improved user feedback Known Issues Backend Separation Backend code not in repo — Hosted separately, not accessible for improvements Algorithm improvements blocked — Cannot improve detection accuracy without backend access Test failures — 23/65 tests fail because factScore > 30 for known fake news Resolution needed — Backend must be imported or accessed before further accuracy work Key Documents Repository: GitHub (switched from SSH to HTTPS auth) Deployment: Vercel auto-deploy from main branch Audit Report: ~/system/reports/ (details TBD) Specifications Index Last Verified: 2026-02-17 | Owner: John BasicFakta — Specifications Index Frontend Code Repository: GitHub (HTTPS auth, gh CLI token) Main branch: Auto-deploys to basicfakta.no via Vercel Framework: Modern web stack (details in repo) Backend API Hosting: Separate external API at basicfakta.no Source code: Not in repo (blocks accuracy improvements) Algorithm: Proprietary fake news detection Status: Access required for further development Security Specifications Implemented (2026-02) XSS prevention via input sanitization Rate limiting with authentication API key sanitization Security headers (vercel.json) Pending Backend security audit (requires backend access) Penetration testing (scheduled TBD) Accessibility Specifications WCAG 2.1 Compliance Screen reader support Keyboard navigation Mobile touch targets (44x44px minimum) Color contrast ratios Loading state announcements Testing Specifications Current Status 42/65 tests passing (64.6% pass rate) 23 tests failing — factScore > 30 for known fake news sources Test Categories URL extraction tests Fact scoring accuracy tests XSS prevention tests Rate limiting tests API integration tests Blockers Backend algorithm not accessible Cannot tune scoring thresholds Cannot improve detection accuracy Audit Reports 2026-02 Audit (13 items) Critical: url-extractor.js (CREATED) XSS fix (FIXED) Rate limit bypass (FIXED) API key sanitization (FIXED) Medium: Security headers (ADDED) Email validation (IMPROVED) SEO meta tags (ADDED) WCAG accessibility (IMPLEMENTED) Mobile UX (IMPROVED) Share results (ADDED) Loading states (IMPROVED) Deployment: Commit ce800c2, Vercel auto-deployed Dependencies Required from Alem Backend source code — For algorithm improvements (task #100) IMAP credentials — For email monitoring (task #79) Test data — Known fake news URLs for accuracy testing External Services Vercel (hosting) GitHub (version control) basicfakta.no API (backend) 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/*.js files are Vercel serverless entry points invoked by the platform router (per vercel.json rewrites), not imported by other modules — knip has no visibility into that root. src/sentry.js and src/url-extractor.js are both required by api/analyze.js (confirmed: grep -rn "require.*sentry" api/analyze.js and grep -rln "require.*url-extractor" api both hit) — knip misses this because it doesn't trace api/ as an entry root either. Genuine findings: tests/run-manual-tests.js and tests/run-tests.js are NOT referenced by any package.json script, CI workflow, or other source file (grep confirmed empty). Superseded by tests/unit-deep.test.js / tests/heuristics.test.js per naming and content overlap. Safe deletion candidates. Unused dependency (1): @sentry/node in 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 untraced api/ 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 by api/*.js files 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.js combines the highest complexity in the codebase with the lowest coverage. combineResults (complexity 29) and analyzeText (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 refactor combineResults and analyzeText to 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 on sanitize , validateAnalyzeInput , errorHandler , and corsConfig before touching complexity/dead-code cleanup here. typecheck is a no-op safety net. checkJs: false + strict: false means tsc --noEmit only 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, enabling checkJs: 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 (all quotes ) 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 file lint-output.txt — full npm run lint output typecheck-output.txt — full npm run typecheck output complexity-output.txt — eslint with complexity/max-depth/max-lines-per-function rules deadcode-output.txt , ts-prune-output.txt , knip-output.txt — dead code detection raw outputs coverage-summary.txt — copy of project's coverage/coverage-summary.json coverage-run-output.txt — fresh c8 run, unit-deep suite only coverage-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)