Files
BoltClam/docs/ARCHITECTURE.md
TheMajesticMagicianandClaude Code addd00364d BoltClam 1.0.0: ClamAV desktop protection with Bolt sign-in
Adds the PyQt6 Windows client (Homepage, Scan & results, About & updates, Settings), ClamAV scanning and quarantine, browser-download watch with an exclusive scan gate, Bolt loopback/PKCE sign-in with DPAPI key storage, Gitea release feed with checksum verification, opt-in diagnostics, and Windows/portable build tooling.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-25 16:21:14 -06:00

5.0 KiB

BoltClam architecture

Process layout

BoltClam is one PyQt6 process on the user's Windows desktop. It starts no Windows service and installs no driver. ClamAV remains an external program.

BoltClam.exe (PyInstaller or portable launcher)
  └─ boltclam.app
       ├─ MainWindow ── HomePage / ScanPage / AboutPage / SettingsPage
       ├─ RealtimeProtection ── DownloadWatcher + QThreadPool scan tasks
       ├─ ScanWorker / DefinitionWorker (QThread)
       ├─ Storage (SQLite, WAL)
       ├─ QuarantineService
       ├─ ClamAVService → clamscan.exe / freshclam.exe
       └─ ApiClient → https://api.themajesticnetwork.com

Settings are JSON under %APPDATA%\BoltClam; history and quarantine live under %LOCALAPPDATA%\BoltClam. BOLTCLAM_CONFIG_DIR and BOLTCLAM_DATA_DIR override both for tests and portable/development use.

Page responsibilities

  • HomePage calls system_info.collect() on a worker. PowerShell supplies Defender/firewall/network facts on Windows; missing data is "not reported". The shell gauge and concern list are derived from ClamAV state, definition age, real-time state, firewall, last scan, active detections and quarantine count. It never labels an unknown state as protected.
  • ScanPage persists scope/auto-response preferences immediately, runs ScanWorker, records each detection in SQLite before remediation, and exposes manual quarantine/delete/ignore after a scan. Quarantine management restores to the original path or a chosen path and refuses overwrites.
  • AboutPage calls /boltclam/account for user/plan data and /boltclam/updates for the release feed. Downloads use the API asset proxy and optionally verify SHA256SUMS.txt.
  • SettingsPage validates ClamAV paths and extra options, applies logging changes, updates the real-time watcher, and creates/uploads diagnostics bundles only when the user has opted in.

Sign-in sequence

BoltClam                      Browser                    Bolt desk API
  |-- PKCE verifier/challenge --|                            |
  |-- loopback listener :port/cb|                            |
  |-- open /desk/auth/boltclam/start?... ------------------->|
  |                             |<-- branded login page -----|
  |                             |-- email/password or OAuth->|
  |<-- 302 /cb?code=...&state=... ----------------------------|
  |-- POST /desk/auth/oauth/exchange (code+verifier) -------->|
  |<-- {api_key, user} --------------------------------------|
  |-- DPAPI-store key, GET /boltclam/account ---------------->|

The one-time code is bound to the PKCE challenge, the exact loopback URI and a short TTL. The app rejects a callback whose state does not match. The API burns an exchange code on the first attempt, successful or not.

Scan sequence

  1. ClamAVService.info() locates clamscan.exe, runs --version, and chooses the managed database if it contains signatures.
  2. scan_targets("homes") reads the Windows ProfileList registry and falls back to C:\Users; "full" enumerates fixed local drives.
  3. ScanWorker starts clamscan with an argv list, no shell, and parses detections/progress/summary. Each path: Signature FOUND becomes a Detection row first, then quarantine/delete/notify is applied.
  4. The scan row is finished even on cancellation or process failure. The UI reloads history and the Homepage aggregates.

Real-time sequence

DownloadWatcher polls each watched download folder at 1.5 s intervals (and refreshes browser preferences every 30 s), ignores in-progress suffixes, and waits for a stable size/mtime. RealtimeScanTask runs in a QThreadPool:

stable file → exclusive handle (share=0) → copy → ClamAV scans copy
            → clean: release           → detection: release + quarantine/delete

The exclusive handle is held for the entire scan. A fallback copy is used when the file is already open, with that fact recorded in the event detail.

Update flow

  • The Bolt API reads Gitea's /api/v1/repos/TheMajesticNetwork/BoltClam/releases, caches for five minutes, filters draft/prerelease by channel, and returns normalized release metadata.
  • Asset downloads go through the API, so a future private repository needs no desktop token. The API streams the Gitea asset with its own token.
  • The client compares semantic versions, selects a Windows .exe/.zip asset, downloads it to %LOCALAPPDATA%\BoltClam\updates, and verifies the release checksum when published.

Storage schema

  • scans — scope, status, paths JSON, counts, engine/DB versions, duration.
  • detections — scan id, path, signature, action, quarantine id, timestamp.
  • quarantine — id, original/quarantine path, signature, SHA-256, status.
  • realtime_events — download path, signature, action, detail, timestamp.

All writes open their own SQLite connection; WAL mode lets the UI read while a scan thread writes. Quarantine sidecars are JSON, so the record survives a database rebuild.