voidaccess 2.0.2__tar.gz → 2.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {voidaccess-2.0.2/voidaccess.egg-info → voidaccess-2.1.0}/PKG-INFO +243 -242
- voidaccess-2.1.0/api/actor_views.py +91 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/auth.py +15 -2
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/main.py +182 -60
- voidaccess-2.1.0/api/ownership.py +58 -0
- voidaccess-2.1.0/api/rate_limit.py +81 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/routes/actors.py +45 -34
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/routes/admin.py +41 -13
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/routes/auth.py +18 -19
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/routes/entities.py +30 -25
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/routes/export.py +3 -2
- voidaccess-2.1.0/api/routes/ingest.py +169 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/routes/investigations.py +431 -156
- voidaccess-2.1.0/api/routes/monitors.py +151 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/routes/search.py +9 -6
- voidaccess-2.1.0/auth/token_blacklist.py +178 -0
- voidaccess-2.1.0/benchmark/__init__.py +11 -0
- voidaccess-2.1.0/benchmark/artifact.py +115 -0
- voidaccess-2.1.0/benchmark/data/benchmark_queries.json +18 -0
- voidaccess-2.1.0/benchmark/engine_cull.py +123 -0
- voidaccess-2.1.0/benchmark/engine_probe.py +345 -0
- voidaccess-2.1.0/benchmark/metrics.py +362 -0
- voidaccess-2.1.0/benchmark/queries.py +95 -0
- voidaccess-2.1.0/config.py +447 -0
- voidaccess-2.1.0/credential_presence/__init__.py +209 -0
- voidaccess-2.1.0/db/entity_views.py +47 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/env.py +16 -0
- voidaccess-2.1.0/db/migrations/versions/0027_add_shared_corpus_tier.py +139 -0
- voidaccess-2.1.0/db/migrations/versions/0028_add_shared_provenance.py +42 -0
- voidaccess-2.1.0/db/migrations/versions/0029_add_job_queue.py +79 -0
- voidaccess-2.1.0/db/migrations/versions/0030_add_onion_consecutive_dead.py +46 -0
- voidaccess-2.1.0/db/migrations/versions/0031_add_source_reputation.py +60 -0
- voidaccess-2.1.0/db/migrations/versions/0032_add_global_entity_source.py +63 -0
- voidaccess-2.1.0/db/migrations/versions/0033_add_ingest_tables.py +58 -0
- voidaccess-2.1.0/db/migrations/versions/0034_add_global_entity_disposition.py +40 -0
- voidaccess-2.1.0/db/migrations/versions/0035_add_global_entity_source_contributor.py +41 -0
- voidaccess-2.1.0/db/migrations/versions/0036_multiuser_security.py +87 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/models.py +68 -3
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/queries.py +40 -22
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/session.py +2 -2
- {voidaccess-2.0.2 → voidaccess-2.1.0}/export/ioc_package.py +1 -1
- {voidaccess-2.0.2 → voidaccess-2.1.0}/export/stix.py +2 -1
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/llm_extract.py +55 -5
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/ner.py +13 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/normalizer.py +18 -98
- voidaccess-2.1.0/extractor/org_filter.py +96 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/pipeline.py +3 -3
- voidaccess-2.1.0/feeds/__init__.py +503 -0
- voidaccess-2.1.0/freshness/__init__.py +60 -0
- voidaccess-2.1.0/freshness/recrawl.py +216 -0
- voidaccess-2.1.0/freshness/scheduler.py +188 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/graph/builder.py +6 -0
- voidaccess-2.1.0/hygiene/__init__.py +119 -0
- voidaccess-2.1.0/index_population/__init__.py +45 -0
- voidaccess-2.1.0/index_population/seeds.py +286 -0
- voidaccess-2.1.0/index_population/usage.py +235 -0
- voidaccess-2.1.0/ingest/__init__.py +48 -0
- voidaccess-2.1.0/ingest/control.py +45 -0
- voidaccess-2.1.0/ingest/keys.py +124 -0
- voidaccess-2.1.0/ingest/models.py +92 -0
- voidaccess-2.1.0/ingest/service.py +82 -0
- voidaccess-2.1.0/jobqueue/__init__.py +51 -0
- voidaccess-2.1.0/jobqueue/models.py +101 -0
- voidaccess-2.1.0/jobqueue/queue.py +245 -0
- voidaccess-2.1.0/jobqueue/worker.py +162 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/monitor/_db.py +2 -2
- {voidaccess-2.0.2 → voidaccess-2.1.0}/monitor/alerts.py +1 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/monitor/config.py +14 -1
- {voidaccess-2.0.2 → voidaccess-2.1.0}/monitor/jobs.py +8 -8
- voidaccess-2.1.0/monitor/migration.py +18 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/monitor/scheduler.py +15 -1
- voidaccess-2.1.0/netpool/__init__.py +109 -0
- voidaccess-2.1.0/observability/__init__.py +13 -0
- voidaccess-2.1.0/observability/corpus_health.py +264 -0
- voidaccess-2.1.0/owned_index/__init__.py +72 -0
- voidaccess-2.1.0/owned_index/client.py +334 -0
- voidaccess-2.1.0/owned_index/index.py +268 -0
- voidaccess-2.1.0/owned_index/schema.py +222 -0
- voidaccess-2.1.0/progress/__init__.py +493 -0
- voidaccess-2.1.0/progress/schema/progress-v2.schema.json +227 -0
- voidaccess-2.1.0/progress/trace.py +769 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/pyproject.toml +31 -3
- voidaccess-2.1.0/ratelimit/__init__.py +38 -0
- voidaccess-2.1.0/ratelimit/limiter.py +118 -0
- voidaccess-2.1.0/sanitizer/__init__.py +38 -0
- voidaccess-2.1.0/sanitizer/detectors.py +202 -0
- voidaccess-2.1.0/sanitizer/gate.py +99 -0
- voidaccess-2.1.0/sanitizer/provenance.py +66 -0
- voidaccess-2.1.0/sanitizer/validate.py +35 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/scraper/scrape.py +153 -51
- voidaccess-2.1.0/search/__init__.py +49 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/search/config.py +26 -0
- voidaccess-2.1.0/search/engine_catalog.py +66 -0
- voidaccess-2.1.0/search/ranking.py +268 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/search/search.py +176 -24
- voidaccess-2.1.0/search/selection.py +153 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/search/tor_isolation.py +9 -11
- {voidaccess-2.0.2 → voidaccess-2.1.0}/setup.cfg +4 -4
- voidaccess-2.1.0/shared_corpus/__init__.py +62 -0
- voidaccess-2.1.0/shared_corpus/access.py +701 -0
- voidaccess-2.1.0/shared_corpus/consent.py +30 -0
- voidaccess-2.1.0/shared_corpus/models.py +413 -0
- voidaccess-2.1.0/shared_corpus/promote.py +463 -0
- voidaccess-2.1.0/shared_corpus/read.py +422 -0
- voidaccess-2.1.0/snapshot_store/__init__.py +39 -0
- voidaccess-2.1.0/snapshot_store/s3.py +244 -0
- voidaccess-2.1.0/snapshot_store/store.py +203 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/__init__.py +9 -10
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/actor_profiles.py +6 -1
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/blockchain.py +22 -6
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/breach_lookup.py +29 -6
- voidaccess-2.1.0/sources/cache.py +165 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/cisa.py +23 -6
- voidaccess-2.1.0/sources/cve_intel.py +322 -0
- voidaccess-2.1.0/sources/data/onion_seeds.json +2205 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/dns_enrichment.py +49 -14
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/domain_reputation.py +23 -11
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/email_reputation.py +24 -7
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/engines.py +17 -84
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/enrichment.py +653 -309
- voidaccess-2.1.0/sources/enrichment_allowlist.py +143 -0
- voidaccess-2.1.0/sources/epss.py +133 -0
- voidaccess-2.1.0/sources/exploitdb.py +103 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/github_scraper.py +4 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/gitlab_scraper.py +4 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/hash_reputation.py +38 -11
- voidaccess-2.1.0/sources/historical_intel.py +306 -0
- voidaccess-2.1.0/sources/http_pool.py +160 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/infostealer.py +11 -2
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/ip_reputation.py +27 -8
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/nvd.py +42 -25
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/paste_scraper.py +31 -7
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/proxy_client.py +21 -4
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/rss_scraper.py +58 -16
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/shodan.py +14 -3
- voidaccess-2.1.0/sources/source_control.py +653 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/telegram.py +4 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/virustotal.py +10 -2
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_api.py +40 -29
- voidaccess-2.1.0/tests/test_api_monitors.py +24 -0
- voidaccess-2.1.0/tests/test_benchmark.py +414 -0
- voidaccess-2.1.0/tests/test_cancel_checkpoints.py +574 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_cli_proxy_config.py +33 -0
- voidaccess-2.1.0/tests/test_content_safety_parity.py +284 -0
- voidaccess-2.1.0/tests/test_corpus_promotion.py +319 -0
- voidaccess-2.1.0/tests/test_credential_presence.py +172 -0
- voidaccess-2.1.0/tests/test_cve_intel.py +189 -0
- voidaccess-2.1.0/tests/test_defang.py +96 -0
- voidaccess-2.1.0/tests/test_defang_api_integration.py +105 -0
- voidaccess-2.1.0/tests/test_disabled_sources.py +414 -0
- voidaccess-2.1.0/tests/test_e5_fetch.py +292 -0
- voidaccess-2.1.0/tests/test_e5_org_filter.py +58 -0
- voidaccess-2.1.0/tests/test_e5_sources.py +502 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_email_reputation.py +14 -13
- voidaccess-2.1.0/tests/test_embedding_backend_health.py +101 -0
- voidaccess-2.1.0/tests/test_enrich_deadline.py +293 -0
- voidaccess-2.1.0/tests/test_enrichment_allowlist.py +382 -0
- voidaccess-2.1.0/tests/test_feeds.py +200 -0
- voidaccess-2.1.0/tests/test_freshness.py +388 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_graph.py +2 -1
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_graph_integration.py +10 -0
- voidaccess-2.1.0/tests/test_hygiene.py +81 -0
- voidaccess-2.1.0/tests/test_index_population.py +378 -0
- voidaccess-2.1.0/tests/test_ingest.py +335 -0
- voidaccess-2.1.0/tests/test_jobqueue.py +258 -0
- voidaccess-2.1.0/tests/test_legacy_backfill.py +124 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_llm.py +18 -12
- voidaccess-2.1.0/tests/test_low_noise_ranking.py +193 -0
- voidaccess-2.1.0/tests/test_malwarebazaar_auth.py +63 -0
- voidaccess-2.1.0/tests/test_migration_persistence.py +95 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_monitor.py +3 -3
- voidaccess-2.1.0/tests/test_multiuser_security.py +225 -0
- voidaccess-2.1.0/tests/test_multiuser_upgrade.py +68 -0
- voidaccess-2.1.0/tests/test_netpool.py +111 -0
- voidaccess-2.1.0/tests/test_observability.py +113 -0
- voidaccess-2.1.0/tests/test_owned_index.py +586 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_pacing_quotas.py +7 -0
- voidaccess-2.1.0/tests/test_packaging.py +217 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_pagination.py +4 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_priority_score_cli_api_parity.py +66 -0
- voidaccess-2.1.0/tests/test_progress.py +209 -0
- voidaccess-2.1.0/tests/test_quiet_mode.py +138 -0
- voidaccess-2.1.0/tests/test_ratelimit.py +76 -0
- voidaccess-2.1.0/tests/test_redteam_moat.py +245 -0
- voidaccess-2.1.0/tests/test_sanitizer.py +180 -0
- voidaccess-2.1.0/tests/test_search_consolidation.py +117 -0
- voidaccess-2.1.0/tests/test_search_ranking.py +183 -0
- voidaccess-2.1.0/tests/test_shared_corpus.py +304 -0
- voidaccess-2.1.0/tests/test_shared_read.py +284 -0
- voidaccess-2.1.0/tests/test_snapshot_store.py +324 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_sources.py +9 -132
- voidaccess-2.1.0/tests/test_sources_status.py +360 -0
- voidaccess-2.1.0/tests/test_speed_controls.py +146 -0
- voidaccess-2.1.0/tests/test_summary_fallback.py +284 -0
- voidaccess-2.1.0/tests/test_temporal_regression.py +76 -0
- voidaccess-2.1.0/tests/test_token_blacklist.py +55 -0
- voidaccess-2.1.0/tests/test_trace_events.py +924 -0
- voidaccess-2.1.0/tests/test_trust_gate.py +404 -0
- voidaccess-2.1.0/trust_gate/__init__.py +62 -0
- voidaccess-2.1.0/trust_gate/anomaly.py +94 -0
- voidaccess-2.1.0/trust_gate/gate.py +476 -0
- voidaccess-2.1.0/trust_gate/model.py +334 -0
- voidaccess-2.1.0/trust_gate/thresholds.py +99 -0
- voidaccess-2.1.0/utils/cancel.py +207 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/utils/content_safety.py +153 -1
- voidaccess-2.1.0/utils/defang.py +142 -0
- voidaccess-2.1.0/utils/entity_priority.py +360 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/utils/investigation_metrics.py +15 -0
- voidaccess-2.1.0/vector/model_singleton.py +161 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/vector/search.py +8 -6
- {voidaccess-2.0.2 → voidaccess-2.1.0}/vector/store.py +47 -2
- voidaccess-2.1.0/voidaccess/backfill.py +251 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess/llm.py +946 -904
- voidaccess-2.1.0/voidaccess/summary_fallback.py +168 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0/voidaccess.egg-info}/PKG-INFO +243 -242
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess.egg-info/SOURCES.txt +135 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess.egg-info/requires.txt +2 -1
- voidaccess-2.1.0/voidaccess.egg-info/top_level.txt +38 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/__init__.py +1 -1
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/adapters/sqlite.py +78 -3
- voidaccess-2.1.0/voidaccess_cli/commands/admin.py +16 -0
- voidaccess-2.1.0/voidaccess_cli/commands/benchmark.py +73 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/commands/investigate.py +1177 -283
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/config.py +15 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/display.py +36 -5
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/main.py +25 -2
- voidaccess-2.1.0/voidaccess_cli/reporter.py +53 -0
- voidaccess-2.0.2/api/routes/monitors.py +0 -404
- voidaccess-2.0.2/auth/token_blacklist.py +0 -140
- voidaccess-2.0.2/config.py +0 -251
- voidaccess-2.0.2/search/__init__.py +0 -392
- voidaccess-2.0.2/search/engine_catalog.py +0 -30
- voidaccess-2.0.2/sources/cache.py +0 -92
- voidaccess-2.0.2/sources/data/onion_seeds.json +0 -523
- voidaccess-2.0.2/sources/historical_intel.py +0 -262
- voidaccess-2.0.2/tests/test_api_monitors.py +0 -127
- voidaccess-2.0.2/utils/defang.py +0 -94
- voidaccess-2.0.2/utils/entity_priority.py +0 -189
- voidaccess-2.0.2/vector/model_singleton.py +0 -92
- voidaccess-2.0.2/voidaccess.egg-info/top_level.txt +0 -21
- {voidaccess-2.0.2 → voidaccess-2.1.0}/LICENSE +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/README.md +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/alembic.ini +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/analysis/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/analysis/opsec.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/analysis/patterns.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/analysis/temporal.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/errors.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/routes/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/api/routes/settings.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/auth/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/crawler/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/crawler/dedup.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/crawler/frontier.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/crawler/spider.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/crawler/utils.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/data/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/data/common_words_en.txt +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/data/domain_stopwords_en.txt +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/data/monitors.yaml +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/data/seed_data.json.gz +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/data/threat_gazetteer.json +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0001_initial_schema.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0002_add_investigation_status_column.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0002_add_missing_tables.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0003_add_canonical_value_and_entity_links.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0004_add_page_posted_at.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0005_add_extraction_method.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0006_add_monitor_alerts.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0007_add_actor_style_profiles.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0008_add_users_table.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0009_add_investigation_id_to_relationships.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0010_add_composite_index_entity_relationships.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0011_add_page_extraction_cache.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0013_add_graph_status.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0015_add_progress_fields.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0016_backfill_graph_status.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0017_add_user_api_keys.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0018_add_user_id_to_investigations.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0019_add_content_safety_log.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0020_add_entity_source_tracking.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0021_add_search_engine_stats.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0022_add_actor_profiles.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0023_add_investigation_metadata.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0024_add_investigation_step_metrics.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0025_add_cancellation_requested.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/migrations/versions/0026_add_entity_investigation_count.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/db/search_engine_stats.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/export/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/export/_entity_loading.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/export/misp.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/export/relationships.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/export/sigma.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/export/snort_export.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/export/yara_export.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/confidence.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/dependency_relationship.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/entity_shape.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/gazetteer.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/identity.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/regex_patterns.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/relationship_extract.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/extractor/software_suppression.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/fingerprint/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/fingerprint/calibration.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/fingerprint/profiler.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/fingerprint/stylometry.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/graph/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/graph/export.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/graph/model.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/graph/queries.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/graph/visualize.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/i18n/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/i18n/detect.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/i18n/query_expand.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/i18n/translate.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/monitor/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/monitor/diff.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/pacing/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/scraper/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/scraper/scrape_js.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/scraper/tor_pool.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/search/circuit_breaker.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/search/query_builder.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/data/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/pastes.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/seed_manager.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/sources/seeds.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_actor_extraction_gap.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_analysis_opsec.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_analysis_stylometry.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_analysis_temporal.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_blockchain.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_breach_lookup.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_cli_manifest.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_community_detection_parity.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_confidence_calibration.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_config.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_consolidated_contracts.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_crawler.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_db.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_dependency_relationship.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_dns_enrichment.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_domain_reputation.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_entity_priority.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_extractor_llm_pipeline.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_filter_e2e_manual.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_filter_parser_manual.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_fingerprint.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_gazetteer.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_github_scraper.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_gitlab_scraper.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_hash_reputation.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_heuristic_expansion.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_i18n.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_infostealer.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_ioc_package_export.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_ip_reputation.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_llm_utils.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_model_singleton.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_monitor_integration.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_nvd.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_pacing.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_pacing_enrichment.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_paste_scraper.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_proxy_client.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_ransomlook.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_regex_patterns.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_relationship_extract.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_requirement_bugs.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_rss_scraper.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_scrape_isolation.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_scrape_js.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_settings.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_sigma_export.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_snort_export.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_software_suppression.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_sources_enrichment_new.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_stix_export.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_vector.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/tests/test_yara_export.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/utils/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/utils/async_utils.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/utils/content_dedup.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/utils/encryption.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/utils/enrichment_cache.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/utils/ioc_freshness.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/utils/user_keys.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/vector/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/vector/embedder.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess/config.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess/llm_utils.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess.egg-info/dependency_links.txt +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess.egg-info/entry_points.txt +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/adapters/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/browser.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/commands/__init__.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/commands/actors.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/commands/configure.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/commands/enrich.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/commands/export.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/commands/show.py +0 -0
- {voidaccess-2.0.2 → voidaccess-2.1.0}/voidaccess_cli/tor_detect.py +0 -0
|
@@ -1,242 +1,243 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: voidaccess
|
|
3
|
-
Version: 2.0
|
|
4
|
-
Summary: Dark web OSINT CLI — automated threat intelligence from query to report
|
|
5
|
-
Author: VoidAccess
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Keywords: osint,darkweb,threat-intelligence,tor,cli
|
|
8
|
-
Classifier: Development Status :: 4 - Beta
|
|
9
|
-
Classifier: Environment :: Console
|
|
10
|
-
Classifier: Intended Audience :: Information Technology
|
|
11
|
-
Classifier: Operating System :: OS Independent
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Classifier: Topic :: Security
|
|
16
|
-
Requires-Python: >=3.10
|
|
17
|
-
Description-Content-Type: text/markdown
|
|
18
|
-
License-File: LICENSE
|
|
19
|
-
Requires-Dist: typer==0.24.1
|
|
20
|
-
Requires-Dist: rich==15.0.0
|
|
21
|
-
Requires-Dist: textual==8.2.7
|
|
22
|
-
Requires-Dist: click==8.3.2
|
|
23
|
-
Requires-Dist: fastapi==0.136.0
|
|
24
|
-
Requires-Dist: aiohttp==3.13.5
|
|
25
|
-
Requires-Dist: aiohttp-socks==0.11.0
|
|
26
|
-
Requires-Dist: alembic==1.18.4
|
|
27
|
-
Requires-Dist: apscheduler==3.11.2
|
|
28
|
-
Requires-Dist: pillow==12.2.0
|
|
29
|
-
Requires-Dist: sqlalchemy[asyncio]==2.0.49
|
|
30
|
-
Requires-Dist: aiosqlite==0.22.1
|
|
31
|
-
Requires-Dist: filelock==3.29.0
|
|
32
|
-
Requires-Dist: numpy
|
|
33
|
-
Requires-Dist: langchain==0.3.25
|
|
34
|
-
Requires-Dist: langchain-openai==0.3.19
|
|
35
|
-
Requires-Dist: langchain-anthropic==0.3.22
|
|
36
|
-
Requires-Dist: langchain-google-genai==2.1.12
|
|
37
|
-
Requires-Dist: langchain-groq==0.3.8
|
|
38
|
-
Requires-Dist: langchain-ollama==0.3.10
|
|
39
|
-
Requires-Dist: python-dotenv==1.2.2
|
|
40
|
-
Requires-Dist: httpx==0.28.1
|
|
41
|
-
Requires-Dist: spacy==3.8.14
|
|
42
|
-
Requires-Dist: beautifulsoup4==4.14.3
|
|
43
|
-
Requires-Dist: feedparser==6.0.11
|
|
44
|
-
Requires-Dist: networkx==3.4.2
|
|
45
|
-
Requires-Dist: pydantic==2.13.3
|
|
46
|
-
Requires-Dist: python-jose[cryptography]==3.5.0
|
|
47
|
-
Requires-Dist: passlib[bcrypt]==1.7.4
|
|
48
|
-
Requires-Dist: bcrypt<4.1,>=3.1.0
|
|
49
|
-
Requires-Dist: slowapi==0.1.9
|
|
50
|
-
Requires-Dist: redis==7.4.0
|
|
51
|
-
Requires-Dist: pyyaml==6.0.3
|
|
52
|
-
Requires-Dist: openai==1.109.1
|
|
53
|
-
Requires-Dist: cryptography==46.0.7
|
|
54
|
-
Requires-Dist: python-dateutil==2.9.0.post0
|
|
55
|
-
Requires-Dist: langdetect==1.0.9
|
|
56
|
-
Requires-Dist: pyvis==0.3.2
|
|
57
|
-
Requires-Dist: urllib3==2.6.3
|
|
58
|
-
Requires-Dist: trafilatura==2.0.0
|
|
59
|
-
Requires-Dist: lxml_html_clean>=0.4.2
|
|
60
|
-
Requires-Dist: requests==2.33.1
|
|
61
|
-
Requires-Dist: python-socks[asyncio]==2.8.1
|
|
62
|
-
Requires-Dist: tldextract==5.3.1
|
|
63
|
-
Requires-Dist: stix2==3.0.2
|
|
64
|
-
Provides-Extra: dev
|
|
65
|
-
Requires-Dist: pytest; extra == "dev"
|
|
66
|
-
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
67
|
-
Requires-Dist: aioresponses>=0.7.6; extra == "dev"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
Requires-Dist:
|
|
71
|
-
Requires-Dist:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
Requires-Dist:
|
|
75
|
-
Requires-Dist:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
Requires-Dist:
|
|
83
|
-
Requires-Dist:
|
|
84
|
-
Requires-Dist:
|
|
85
|
-
Requires-Dist:
|
|
86
|
-
Requires-Dist:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
<a href="
|
|
98
|
-
<a href="
|
|
99
|
-
<a href="
|
|
100
|
-
<a href="https://pypi.org/project/voidaccess/"><img src="https://img.shields.io/pypi/
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
voidaccess
|
|
115
|
-
voidaccess
|
|
116
|
-
voidaccess
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
- **
|
|
125
|
-
- **
|
|
126
|
-
- **
|
|
127
|
-
- **
|
|
128
|
-
- **
|
|
129
|
-
- **
|
|
130
|
-
- **
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
|
|
|
141
|
-
|
|
|
142
|
-
|
|
|
143
|
-
|
|
|
144
|
-
|
|
|
145
|
-
|
|
|
146
|
-
|
|
|
147
|
-
|
|
|
148
|
-
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
|
158
|
-
|
|
|
159
|
-
|
|
|
160
|
-
|
|
|
161
|
-
|
|
|
162
|
-
|
|
|
163
|
-
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
|
171
|
-
|
|
|
172
|
-
|
|
|
173
|
-
|
|
|
174
|
-
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
|
195
|
-
|
|
|
196
|
-
|
|
|
197
|
-
|
|
|
198
|
-
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
| `voidaccess
|
|
206
|
-
| `voidaccess
|
|
207
|
-
| `voidaccess
|
|
208
|
-
| `voidaccess
|
|
209
|
-
| `voidaccess
|
|
210
|
-
| `voidaccess
|
|
211
|
-
| `voidaccess
|
|
212
|
-
| `voidaccess
|
|
213
|
-
| `voidaccess actor HANDLE
|
|
214
|
-
| `voidaccess actor HANDLE --
|
|
215
|
-
| `voidaccess
|
|
216
|
-
| `voidaccess
|
|
217
|
-
| `voidaccess configure
|
|
218
|
-
| `voidaccess configure
|
|
219
|
-
| `voidaccess configure
|
|
220
|
-
| `voidaccess
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
| [
|
|
234
|
-
| [
|
|
235
|
-
| [
|
|
236
|
-
| [
|
|
237
|
-
| [
|
|
238
|
-
| [
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: voidaccess
|
|
3
|
+
Version: 2.1.0
|
|
4
|
+
Summary: Dark web OSINT CLI — automated threat intelligence from query to report
|
|
5
|
+
Author: VoidAccess
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: osint,darkweb,threat-intelligence,tor,cli
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Information Technology
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Security
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: typer==0.24.1
|
|
20
|
+
Requires-Dist: rich==15.0.0
|
|
21
|
+
Requires-Dist: textual==8.2.7
|
|
22
|
+
Requires-Dist: click==8.3.2
|
|
23
|
+
Requires-Dist: fastapi==0.136.0
|
|
24
|
+
Requires-Dist: aiohttp==3.13.5
|
|
25
|
+
Requires-Dist: aiohttp-socks==0.11.0
|
|
26
|
+
Requires-Dist: alembic==1.18.4
|
|
27
|
+
Requires-Dist: apscheduler==3.11.2
|
|
28
|
+
Requires-Dist: pillow==12.2.0
|
|
29
|
+
Requires-Dist: sqlalchemy[asyncio]==2.0.49
|
|
30
|
+
Requires-Dist: aiosqlite==0.22.1
|
|
31
|
+
Requires-Dist: filelock==3.29.0
|
|
32
|
+
Requires-Dist: numpy<2,>=1.26
|
|
33
|
+
Requires-Dist: langchain==0.3.25
|
|
34
|
+
Requires-Dist: langchain-openai==0.3.19
|
|
35
|
+
Requires-Dist: langchain-anthropic==0.3.22
|
|
36
|
+
Requires-Dist: langchain-google-genai==2.1.12
|
|
37
|
+
Requires-Dist: langchain-groq==0.3.8
|
|
38
|
+
Requires-Dist: langchain-ollama==0.3.10
|
|
39
|
+
Requires-Dist: python-dotenv==1.2.2
|
|
40
|
+
Requires-Dist: httpx==0.28.1
|
|
41
|
+
Requires-Dist: spacy==3.8.14
|
|
42
|
+
Requires-Dist: beautifulsoup4==4.14.3
|
|
43
|
+
Requires-Dist: feedparser==6.0.11
|
|
44
|
+
Requires-Dist: networkx==3.4.2
|
|
45
|
+
Requires-Dist: pydantic==2.13.3
|
|
46
|
+
Requires-Dist: python-jose[cryptography]==3.5.0
|
|
47
|
+
Requires-Dist: passlib[bcrypt]==1.7.4
|
|
48
|
+
Requires-Dist: bcrypt<4.1,>=3.1.0
|
|
49
|
+
Requires-Dist: slowapi==0.1.9
|
|
50
|
+
Requires-Dist: redis==7.4.0
|
|
51
|
+
Requires-Dist: pyyaml==6.0.3
|
|
52
|
+
Requires-Dist: openai==1.109.1
|
|
53
|
+
Requires-Dist: cryptography==46.0.7
|
|
54
|
+
Requires-Dist: python-dateutil==2.9.0.post0
|
|
55
|
+
Requires-Dist: langdetect==1.0.9
|
|
56
|
+
Requires-Dist: pyvis==0.3.2
|
|
57
|
+
Requires-Dist: urllib3==2.6.3
|
|
58
|
+
Requires-Dist: trafilatura==2.0.0
|
|
59
|
+
Requires-Dist: lxml_html_clean>=0.4.2
|
|
60
|
+
Requires-Dist: requests==2.33.1
|
|
61
|
+
Requires-Dist: python-socks[asyncio]==2.8.1
|
|
62
|
+
Requires-Dist: tldextract==5.3.1
|
|
63
|
+
Requires-Dist: stix2==3.0.2
|
|
64
|
+
Provides-Extra: dev
|
|
65
|
+
Requires-Dist: pytest; extra == "dev"
|
|
66
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
67
|
+
Requires-Dist: aioresponses>=0.7.6; extra == "dev"
|
|
68
|
+
Requires-Dist: jsonschema>=4.18; extra == "dev"
|
|
69
|
+
Provides-Extra: nlp
|
|
70
|
+
Requires-Dist: sentence-transformers>=3.0; extra == "nlp"
|
|
71
|
+
Requires-Dist: torch>=2.3; extra == "nlp"
|
|
72
|
+
Requires-Dist: transformers>=4.42; extra == "nlp"
|
|
73
|
+
Provides-Extra: vector
|
|
74
|
+
Requires-Dist: chromadb>=0.5; extra == "vector"
|
|
75
|
+
Requires-Dist: sentence-transformers>=3.0; extra == "vector"
|
|
76
|
+
Requires-Dist: torch>=2.3; extra == "vector"
|
|
77
|
+
Provides-Extra: telegram
|
|
78
|
+
Requires-Dist: telethon>=1.36; extra == "telegram"
|
|
79
|
+
Provides-Extra: js
|
|
80
|
+
Requires-Dist: playwright>=1.45; extra == "js"
|
|
81
|
+
Provides-Extra: all
|
|
82
|
+
Requires-Dist: chromadb>=0.5; extra == "all"
|
|
83
|
+
Requires-Dist: playwright>=1.45; extra == "all"
|
|
84
|
+
Requires-Dist: sentence-transformers>=3.0; extra == "all"
|
|
85
|
+
Requires-Dist: telethon>=1.36; extra == "all"
|
|
86
|
+
Requires-Dist: torch>=2.3; extra == "all"
|
|
87
|
+
Requires-Dist: transformers>=4.42; extra == "all"
|
|
88
|
+
Dynamic: license-file
|
|
89
|
+
|
|
90
|
+
<p align="center">
|
|
91
|
+
<img src="public/logo_circle.png" width="160" alt="VoidAccess logo">
|
|
92
|
+
</p>
|
|
93
|
+
|
|
94
|
+
<h1 align="center">VoidAccess</h1>
|
|
95
|
+
|
|
96
|
+
<p align="center">
|
|
97
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
|
|
98
|
+
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/Python-3.10%2B-blue.svg" alt="Python 3.10+"></a>
|
|
99
|
+
<a href="docker-compose.yml"><img src="https://img.shields.io/badge/Docker-Compose-blue.svg" alt="Docker Compose"></a>
|
|
100
|
+
<a href="https://pypi.org/project/voidaccess/"><img src="https://img.shields.io/pypi/v/voidaccess?logo=pypi&logoColor=white" alt="PyPI version"></a>
|
|
101
|
+
<a href="https://pypi.org/project/voidaccess/"><img src="https://img.shields.io/pypi/dm/voidaccess" alt="PyPI downloads"></a>
|
|
102
|
+
</p>
|
|
103
|
+
|
|
104
|
+
Self-hostable OSINT for turning dark-web research queries into structured threat intelligence. Built for security researchers, threat-intelligence teams, and authorized investigators who need collection, enrichment, relationship mapping, and export in one workflow.
|
|
105
|
+
|
|
106
|
+
## Terminal Output
|
|
107
|
+
|
|
108
|
+

|
|
109
|
+
|
|
110
|
+
## Quick Start
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pip install voidaccess
|
|
114
|
+
voidaccess investigate "LockBit ransomware" --no-llm --no-tor --depth shallow
|
|
115
|
+
voidaccess list
|
|
116
|
+
voidaccess actors
|
|
117
|
+
voidaccess status
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+

|
|
121
|
+
|
|
122
|
+
## What It Does
|
|
123
|
+
|
|
124
|
+
- **Parallel collection** - searches Tor indexes, paste sites, code forges, security feeds, and curated `.onion` seeds.
|
|
125
|
+
- **Entity extraction** - finds IOCs, wallets, credentials, handles, vulnerabilities, actors, malware, people, and organizations.
|
|
126
|
+
- **Multi-source enrichment** - adds reputation, breach, passive DNS, sandbox, blockchain, and threat-feed context.
|
|
127
|
+
- **Actor intelligence** - persists aliases, infrastructure, notes, timelines, and cross-investigation relationships.
|
|
128
|
+
- **Relationship graphs** - builds co-occurrence graphs, communities, paths, and infrastructure clusters.
|
|
129
|
+
- **Content safety** - filters prohibited queries, URLs, content, and extracted entities at mandatory pipeline gates.
|
|
130
|
+
- **Structured exports** - produces STIX 2.1, MISP, Sigma, YARA, Snort, Suricata, CSV, Markdown, JSON, and IOC packages.
|
|
131
|
+
- **CLI and web UI** - runs locally with SQLite or as a Docker Compose stack with PostgreSQL and a browser interface.
|
|
132
|
+
|
|
133
|
+
## Pipeline
|
|
134
|
+
|
|
135
|
+
| Stage | Action |
|
|
136
|
+
|---|---|
|
|
137
|
+
| 1 | Refine the investigation query with the selected LLM |
|
|
138
|
+
| 2 | Collect from Tor search, paste sites, code forges, RSS feeds, and curated seeds in parallel |
|
|
139
|
+
| 3 | Filter noisy or irrelevant pages |
|
|
140
|
+
| 4 | Enrich the query and early indicators from threat-intelligence sources |
|
|
141
|
+
| 5 | Discover additional `.onion` links recursively |
|
|
142
|
+
| 6 | Reuse recently processed pages from the vector cache |
|
|
143
|
+
| 7 | Fetch selected pages through Tor with response-size limits |
|
|
144
|
+
| 8 | Persist newly collected content |
|
|
145
|
+
| 9 | Merge collected and enriched intelligence |
|
|
146
|
+
| 10 | Extract entities with regex, NER, and optional LLM analysis |
|
|
147
|
+
| 11 | Cross-reference entities against historical and seed datasets |
|
|
148
|
+
| 12 | Build relationships, communities, and infrastructure clusters |
|
|
149
|
+
| 13 | Generate the final intelligence summary and export-ready result |
|
|
150
|
+
|
|
151
|
+
Full pipeline behavior, timeouts, recovery, and data flow are documented in [Architecture](docs/architecture.md).
|
|
152
|
+
|
|
153
|
+
## Entity Types
|
|
154
|
+
|
|
155
|
+
| Category | Examples |
|
|
156
|
+
|---|---|
|
|
157
|
+
| Cryptocurrency | Bitcoin, Ethereum, Monero, Litecoin, Zcash, Solana, Tron, ENS |
|
|
158
|
+
| Network indicators | IPv4, IPv6, domains, URLs, `.onion` addresses, MAC addresses, PGP keys |
|
|
159
|
+
| File indicators | MD5, SHA-1, SHA-256, malware families |
|
|
160
|
+
| Credentials | Cloud keys, tokens, JWTs, API keys, stealer logs, combo-list entries |
|
|
161
|
+
| Messaging | Telegram, Discord, XMPP, Tox, Session, Matrix, Wire, ICQ, Wickr |
|
|
162
|
+
| Vulnerabilities | CVEs, MITRE ATT&CK techniques and tactics, Exploit-DB IDs |
|
|
163
|
+
| Detection content | YARA rules, Nuclei templates, Snort and Suricata indicators |
|
|
164
|
+
| Threat intelligence | Actor handles, ransomware groups, paste links, people, organizations, locations |
|
|
165
|
+
|
|
166
|
+
## Collection and Enrichment
|
|
167
|
+
|
|
168
|
+
| Layer | Sources |
|
|
169
|
+
|---|---|
|
|
170
|
+
| Dark-web search | 16+ Tor search engines and curated `.onion` seeds |
|
|
171
|
+
| Open-web collection | Pastebin, dpaste, paste.ee, Rentry, GitHub, GitLab, and curated RSS feeds |
|
|
172
|
+
| Threat feeds | AlienVault OTX, abuse.ch, MalwareBazaar, ThreatFox, URLhaus, ransomware.live, CISA KEV |
|
|
173
|
+
| IP and domain context | Shodan InternetDB, GreyNoise, AbuseIPDB, Feodo Tracker, C2IntelFeeds, crt.sh, URLScan.io, Wayback Machine, CIRCL PDNS, RDAP |
|
|
174
|
+
| File and identity context | VirusTotal, Hybrid Analysis, Have I Been Pwned, EmailRep |
|
|
175
|
+
| Blockchain | BlockCypher and Etherscan |
|
|
176
|
+
|
|
177
|
+
Sources that need API keys skip cleanly when their keys are absent. The complete key and configuration reference is in [Architecture](docs/architecture.md#13-configuration-reference).
|
|
178
|
+
|
|
179
|
+
### Optional vector embeddings
|
|
180
|
+
|
|
181
|
+
The default installation can run without PyTorch. When the embedding stack is
|
|
182
|
+
unavailable, VoidAccess logs that it is using a deterministic SHA-256 fallback
|
|
183
|
+
encoder. Install the optional NLP dependencies to enable full
|
|
184
|
+
sentence-transformer vector embeddings:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
pip install "voidaccess[nlp]"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## LLM Providers
|
|
191
|
+
|
|
192
|
+
| Provider | Typical models | Notes |
|
|
193
|
+
|---|---|---|
|
|
194
|
+
| OpenRouter | DeepSeek, Llama, Claude | Default route; free models are available |
|
|
195
|
+
| Groq | Llama | Fast hosted inference with a free tier |
|
|
196
|
+
| OpenAI | GPT models | API key required |
|
|
197
|
+
| Anthropic | Claude | Claude Haiku is the tested default |
|
|
198
|
+
| Google Gemini | Gemini Flash and Pro | Google AI Studio key required |
|
|
199
|
+
| Ollama | Any installed local model | Local and suitable for air-gapped deployments |
|
|
200
|
+
|
|
201
|
+
## CLI Reference
|
|
202
|
+
|
|
203
|
+
| Command | Description |
|
|
204
|
+
|---------|-------------|
|
|
205
|
+
| `voidaccess investigate "QUERY"` | Run an investigation |
|
|
206
|
+
| `voidaccess show` | Open the interactive entity browser |
|
|
207
|
+
| `voidaccess export INVESTIGATION_ID --format FORMAT` | Export as STIX, MISP, Sigma, YARA, Snort, Suricata, package, CSV, Markdown, or JSON |
|
|
208
|
+
| `voidaccess package INVESTIGATION_ID` | Build an IOC package ZIP |
|
|
209
|
+
| `voidaccess enrich INVESTIGATION_ID` | Re-enrich a saved investigation |
|
|
210
|
+
| `voidaccess list` | List saved investigations |
|
|
211
|
+
| `voidaccess status` | Show configuration, Tor, cache, engine, and seed status |
|
|
212
|
+
| `voidaccess actors` | List persistent actor profiles |
|
|
213
|
+
| `voidaccess actor HANDLE` | Show an actor profile |
|
|
214
|
+
| `voidaccess actor HANDLE --timeline` | Show an actor activity timeline |
|
|
215
|
+
| `voidaccess actor HANDLE --note "TEXT"` | Add an analyst note to an actor profile |
|
|
216
|
+
| `voidaccess timeline HANDLE` | Open an actor timeline directly |
|
|
217
|
+
| `voidaccess configure` | Run the setup wizard |
|
|
218
|
+
| `voidaccess configure llm` | Configure the LLM provider, model, and key |
|
|
219
|
+
| `voidaccess configure keys` | Configure enrichment API keys |
|
|
220
|
+
| `voidaccess configure tor` | Override the Tor proxy host and port |
|
|
221
|
+
| `voidaccess version` | Print the installed version |
|
|
222
|
+
|
|
223
|
+
Optional clearnet requests can use [ScrapingAnt](https://scrapingant.com/?ref=mzliyzh) with `--use-scraping-api` or `--use-proxies`; Tor, `.onion`, GitHub, and GitLab traffic are unaffected.
|
|
224
|
+
|
|
225
|
+
## Self-Hosting
|
|
226
|
+
|
|
227
|
+
Run the full PostgreSQL, Tor, FastAPI, and Next.js stack with Docker Compose. The [self-hosting guide](docs/self-hosting.md) covers guided setup, environment configuration, operations, and troubleshooting.
|
|
228
|
+
|
|
229
|
+
## Links
|
|
230
|
+
|
|
231
|
+
| | |
|
|
232
|
+
|-|-|
|
|
233
|
+
| [Self-hosting guide](docs/self-hosting.md) | Docker Compose, environment setup, operations, and troubleshooting |
|
|
234
|
+
| [Architecture](docs/architecture.md) | Pipeline internals, modules, schema, API, enrichment, graph, and configuration reference |
|
|
235
|
+
| [Contributing](CONTRIBUTING.md) | Development setup, standards, and pull requests |
|
|
236
|
+
| [Security](SECURITY.md) | Supported versions and private vulnerability reporting |
|
|
237
|
+
| [Usage policy](docs/USAGE_POLICY.md) | Authorized-use requirements and prohibited activity |
|
|
238
|
+
| [PyPI](https://pypi.org/project/voidaccess/) | Published package and release files |
|
|
239
|
+
| [GitHub](https://github.com/KatrielMoses/VoidAccess) | Source, issues, and releases |
|
|
240
|
+
|
|
241
|
+
## License
|
|
242
|
+
|
|
243
|
+
MIT. Use VoidAccess only for authorized security research and threat-intelligence work; see the [Usage Policy](docs/USAGE_POLICY.md).
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Actor API views derived only from the caller's investigation evidence."""
|
|
2
|
+
import uuid
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
from sqlalchemy import or_
|
|
5
|
+
from db.models import ActorProfile, ActorAlias, ActorInfrastructure, ActorNote, Investigation
|
|
6
|
+
from db.session import get_session
|
|
7
|
+
from sources.actor_profiles import _serialize_profile
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ScopedActorManager:
|
|
11
|
+
_TIMELINE_EVENT_TYPES = {"FIRST_SEEN", "INVESTIGATION", "NEW_ALIAS", "NEW_INFRASTRUCTURE", "NOTE_ADDED"}
|
|
12
|
+
|
|
13
|
+
def __init__(self, current):
|
|
14
|
+
self.owner = current.user.id
|
|
15
|
+
self.admin = current.user.role == "admin"
|
|
16
|
+
|
|
17
|
+
async def get_profile(self, handle):
|
|
18
|
+
canonical = handle.strip().lower().lstrip("@")
|
|
19
|
+
with get_session() as session:
|
|
20
|
+
aliases = session.query(ActorAlias).filter(ActorAlias.alias_value == handle)
|
|
21
|
+
if not self.admin:
|
|
22
|
+
aliases = aliases.filter(ActorAlias.user_id == self.owner)
|
|
23
|
+
alias_ids = [a.actor_id for a in aliases.all()]
|
|
24
|
+
row = session.query(ActorProfile).filter(or_(ActorProfile.canonical_handle == canonical, ActorProfile.id.in_(alias_ids))).first()
|
|
25
|
+
if row is None:
|
|
26
|
+
return None
|
|
27
|
+
owned = session.query(Investigation.id).filter_by(user_id=self.owner)
|
|
28
|
+
aq = session.query(ActorAlias).filter_by(actor_id=row.id)
|
|
29
|
+
iq = session.query(ActorInfrastructure).filter_by(actor_id=row.id)
|
|
30
|
+
if not self.admin:
|
|
31
|
+
aq = aq.filter(ActorAlias.user_id == self.owner)
|
|
32
|
+
iq = iq.filter(ActorInfrastructure.source_investigation_id.in_(owned))
|
|
33
|
+
aliases, infra = aq.all(), iq.all()
|
|
34
|
+
if not self.admin and not (aliases or infra):
|
|
35
|
+
return None
|
|
36
|
+
result = _serialize_profile(row, aliases, infra)
|
|
37
|
+
nq = session.query(ActorNote).filter_by(actor_id=row.id)
|
|
38
|
+
if not self.admin:
|
|
39
|
+
nq = nq.filter_by(user_id=self.owner)
|
|
40
|
+
notes = nq.order_by(ActorNote.created_at).all()
|
|
41
|
+
result["notes"] = "\n".join(n.text for n in notes)
|
|
42
|
+
if not self.admin:
|
|
43
|
+
times = [x.first_seen_at for x in aliases + infra if x.first_seen_at]
|
|
44
|
+
result["first_seen_at"] = min(times).isoformat() if times else None
|
|
45
|
+
result["last_seen_at"] = max(times).isoformat() if times else None
|
|
46
|
+
result["created_at"] = result["first_seen_at"]
|
|
47
|
+
result["updated_at"] = result["last_seen_at"]
|
|
48
|
+
result["investigation_count"] = len(result["investigation_ids"])
|
|
49
|
+
result["confidence"] = max([x.confidence or 0 for x in aliases + infra], default=0)
|
|
50
|
+
return result
|
|
51
|
+
|
|
52
|
+
async def add_alias(self, actor_id, alias_value, alias_type, investigation_id, confidence=None):
|
|
53
|
+
with get_session() as session:
|
|
54
|
+
row = session.query(ActorAlias).filter_by(actor_id=uuid.UUID(actor_id), alias_value=alias_value, user_id=self.owner).first()
|
|
55
|
+
if row:
|
|
56
|
+
row.confidence = max(row.confidence or 0, confidence or 0)
|
|
57
|
+
else:
|
|
58
|
+
session.add(ActorAlias(actor_id=uuid.UUID(actor_id), alias_value=alias_value,
|
|
59
|
+
alias_type=alias_type, user_id=self.owner, confidence=confidence,
|
|
60
|
+
first_seen_at=datetime.now(timezone.utc)))
|
|
61
|
+
|
|
62
|
+
async def find_alias_candidates(self, actor_id, min_confidence=0.60):
|
|
63
|
+
# Candidate evidence must itself be owner-scoped. Analyst annotations
|
|
64
|
+
# are the authoritative candidates; global aggregate scoring is CLI-only.
|
|
65
|
+
with get_session() as session:
|
|
66
|
+
query = session.query(ActorAlias).filter_by(actor_id=uuid.UUID(actor_id))
|
|
67
|
+
if not self.admin:
|
|
68
|
+
query = query.filter_by(user_id=self.owner)
|
|
69
|
+
return [{"candidate_handle": a.alias_value, "confidence": a.confidence, "signals": ["owned_alias"]}
|
|
70
|
+
for a in query.all() if (a.confidence or 0) >= min_confidence]
|
|
71
|
+
|
|
72
|
+
async def get_actor_timeline(self, handle, limit=50, event_types=None):
|
|
73
|
+
profile = await self.get_profile(handle)
|
|
74
|
+
if not profile:
|
|
75
|
+
return []
|
|
76
|
+
events = []
|
|
77
|
+
for item in profile["aliases"]:
|
|
78
|
+
events.append({"event_type": "NEW_ALIAS", "timestamp": item["first_seen_at"],
|
|
79
|
+
"description": item["alias_value"], "metadata": item})
|
|
80
|
+
for item in profile["infrastructure"]:
|
|
81
|
+
events.append({"event_type": "NEW_INFRASTRUCTURE", "timestamp": item["first_seen_at"],
|
|
82
|
+
"description": item["entity_value"], "metadata": item})
|
|
83
|
+
with get_session() as session:
|
|
84
|
+
query = session.query(ActorNote).filter_by(actor_id=uuid.UUID(profile["id"]))
|
|
85
|
+
if not self.admin:
|
|
86
|
+
query = query.filter_by(user_id=self.owner)
|
|
87
|
+
for n in query.all():
|
|
88
|
+
events.append({"event_type": "NOTE_ADDED", "timestamp": n.created_at.isoformat(),
|
|
89
|
+
"description": n.text, "metadata": {}})
|
|
90
|
+
return sorted([e for e in events if not event_types or e["event_type"] in event_types],
|
|
91
|
+
key=lambda e: e["timestamp"] or "")[-limit:]
|