Quick Scan feature (v1.1.0 candidate)#2
Merged
Merged
Conversation
…sions and quick_scan_findings Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…_scan.py Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ntegration Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds start/status/sessions/findings endpoints plus the /quick-scan page route, all @require_login. Ownership checks return 403; a DB-backed active-scan guard returns 409. Adds dpaste.org to ALLOWED_EXTERNAL_HOSTS for the clearnet paste path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two concurrent first requests could both instantiate Storage and race Base.metadata.create_all in Postgres (UniqueViolation on pg_type_typname_nsp_index). Guard the storage_helper singleton with double-checked locking; the CLI path keeps _create_tables in Storage.__init__ unchanged. Also make checkfirst=True explicit on create_all. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011pZtyQhe6HVvB6Pq3UQzvP
…nd progress logging - POST /api/quick-scan/cancel/<session_id>: owner-only (404/403/400 guards), flips status to cancelled and stamps completed_at. - run_quick_scan honors cancellation at every source and fetch boundary via _is_cancelled; on cancel it stops early, syncs counters, and never stamps completed. Also refuses to start a session already cancelled while pending. - INFO logging at each stage: source query start/complete with URL count, fetch start/complete/timeout, finding created, cancellation detected. - Cancel button in the Activity panel, visible only while pending/running. - Integration tests: mid-run cancel with a real worker thread (event-gated fetch stub), plus 404/403 cancel guards. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011pZtyQhe6HVvB6Pq3UQzvP
Owner
Author
|
Smoke tested on the VPS against the feature branch. Verified:
Merging as v1.1.0 candidate. Documentation and release commit to follow in a separate PR. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an ad-hoc Quick Scan feature for target investigation, independent of the existing project/keyword/IOC pipeline. Delivered as six layered, reviewable commits. Full suite green: 133 passed, 2 skipped (71/2 baseline + 62 new, zero regressions). New files pass ruff with no new lint errors.
Files changed, grouped by commit
Commit 1 — storage models and Storage methods
src/darkweb_scanner/storage.py(+146):QuickScanSession+QuickScanFindingmodels and 7 Storage methods.Commit 2 — source config module and normalization logic
src/darkweb_scanner/quick_scan_sources.py(+180, new): typedQuickScanSourceregistry.src/darkweb_scanner/quick_scan.py(+164, new): pure detection / normalization / high-signal / context logic.Commit 3 — orchestrator run_quick_scan
src/darkweb_scanner/quick_scan.py(+229): async orchestrator with Tor +safe_fetchdispatch, depth/URL/timeout caps.Commit 4 — /api/quick-scan/ routes*
src/darkweb_scanner/dashboard/dashboard_routes.py(+169): start/status/sessions/findings +/quick-scanpage.src/darkweb_scanner/dashboard/http_client.py(+4): allowlist entry.Commit 5 — Quick Scan tab UI
src/darkweb_scanner/dashboard/templates/quick_scan.html(+357, new): standalone page + vanilla-JS polling.src/darkweb_scanner/dashboard/templates/index.html(+1): sidebar nav link.Commit 6 — unit and integration test suite
tests/unit/test_quick_scan_target_detection.py(+80)tests/unit/test_quick_scan_high_signal.py(+76)tests/integration/test_quick_scan_orchestration.py(+155)tests/integration/test_quick_scan_routes.py(+179)Deviations from spec, with justification
index.htmlwith nostatic/dir. This honors the spec's literalGET /quick-scan→quick_scan.htmlrequirement; the sidebar entry navigates there.dpaste.organdrentry.coship disabled. Neither exposes a documented public search endpoint, so per the spec's own "otherwise skip cleanly" clause both are registered with emptyurl_templates. The clearnetsafe_fetchpath is fully implemented and tested (test_clearnet_path_uses_safe_fetch); enabling a paste source is a one-line change once an endpoint exists.@require_logindecorator redirects to the login page; shared auth behavior was not altered. Cross-user (403) and double-start (409) match the spec exactly.has_active_quick_scanoverpending/running) rather than an in-process global like the existing crawler. Correct across gunicorn workers — addresses SECURITY_REVIEW_FABLE finding #5 rather than replicating that flaw.test_total_timeout_marks_session_completed_with_warning(markscompleted+ warning).Allowlist additions to
http_client.pyExactly one host added to
ALLOWED_EXTERNAL_HOSTS:dpaste.org— clearnet paste source, fetched viasafe_fetch(HTTPS-only, IP-blocklisted). Added with a comment noting the source ships disabled pending a search endpoint.rentry.cowas not added (disabled source, no outbound calls). Onion sources (Ahmia, Torch, Haystak, ransomware seeds) need no allowlist entry — they route through Tor.Smoke test pending
Manual smoke test against a benign domain (e.g.
example.com) on a deployed instance with a live Tor daemon is not yet run — it requires the running stack. Expected: UI updates live, findings are stored, and the session completes cleanly.🤖 Generated with Claude Code