voidaccess 2.0.0__tar.gz → 2.0.2__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.0/voidaccess.egg-info → voidaccess-2.0.2}/PKG-INFO +1 -1
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/main.py +1 -1
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/routes/entities.py +102 -4
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/routes/export.py +16 -0
- voidaccess-2.0.2/data/__init__.py +13 -0
- voidaccess-2.0.2/data/common_words_en.txt +370079 -0
- voidaccess-2.0.2/data/domain_stopwords_en.txt +192 -0
- voidaccess-2.0.2/data/monitors.yaml +1 -0
- voidaccess-2.0.2/data/seed_data.json.gz +0 -0
- voidaccess-2.0.2/data/threat_gazetteer.json +63847 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/export/__init__.py +2 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/export/ioc_package.py +3 -47
- {voidaccess-2.0.0 → voidaccess-2.0.2}/export/sigma.py +58 -1
- {voidaccess-2.0.0 → voidaccess-2.0.2}/pyproject.toml +21 -2
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_api.py +54 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_cli_proxy_config.py +8 -2
- voidaccess-2.0.2/tests/test_community_detection_parity.py +201 -0
- voidaccess-2.0.2/tests/test_ioc_package_export.py +128 -0
- voidaccess-2.0.2/tests/test_priority_score_cli_api_parity.py +76 -0
- voidaccess-2.0.2/tests/test_sigma_export.py +85 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2/voidaccess.egg-info}/PKG-INFO +1 -1
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess.egg-info/SOURCES.txt +9 -0
- voidaccess-2.0.2/voidaccess.egg-info/entry_points.txt +2 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess.egg-info/top_level.txt +1 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/__init__.py +1 -1
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/adapters/sqlite.py +13 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/commands/export.py +53 -17
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/commands/investigate.py +60 -37
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/main.py +20 -1
- voidaccess-2.0.0/tests/test_community_detection_parity.py +0 -92
- voidaccess-2.0.0/voidaccess.egg-info/entry_points.txt +0 -2
- {voidaccess-2.0.0 → voidaccess-2.0.2}/LICENSE +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/README.md +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/alembic.ini +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/analysis/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/analysis/opsec.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/analysis/patterns.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/analysis/temporal.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/auth.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/errors.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/routes/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/routes/actors.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/routes/admin.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/routes/auth.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/routes/investigations.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/routes/monitors.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/routes/search.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/api/routes/settings.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/auth/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/auth/token_blacklist.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/config.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/crawler/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/crawler/dedup.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/crawler/frontier.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/crawler/spider.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/crawler/utils.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/env.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0001_initial_schema.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0002_add_investigation_status_column.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0002_add_missing_tables.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0003_add_canonical_value_and_entity_links.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0004_add_page_posted_at.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0005_add_extraction_method.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0006_add_monitor_alerts.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0007_add_actor_style_profiles.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0008_add_users_table.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0009_add_investigation_id_to_relationships.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0010_add_composite_index_entity_relationships.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0011_add_page_extraction_cache.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0013_add_graph_status.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0015_add_progress_fields.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0016_backfill_graph_status.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0017_add_user_api_keys.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0018_add_user_id_to_investigations.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0019_add_content_safety_log.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0020_add_entity_source_tracking.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0021_add_search_engine_stats.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0022_add_actor_profiles.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0023_add_investigation_metadata.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0024_add_investigation_step_metrics.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0025_add_cancellation_requested.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/migrations/versions/0026_add_entity_investigation_count.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/models.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/queries.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/search_engine_stats.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/db/session.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/export/_entity_loading.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/export/misp.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/export/relationships.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/export/snort_export.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/export/stix.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/export/yara_export.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/confidence.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/dependency_relationship.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/entity_shape.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/gazetteer.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/identity.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/llm_extract.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/ner.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/normalizer.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/pipeline.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/regex_patterns.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/relationship_extract.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/extractor/software_suppression.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/fingerprint/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/fingerprint/calibration.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/fingerprint/profiler.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/fingerprint/stylometry.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/graph/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/graph/builder.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/graph/export.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/graph/model.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/graph/queries.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/graph/visualize.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/i18n/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/i18n/detect.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/i18n/query_expand.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/i18n/translate.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/monitor/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/monitor/_db.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/monitor/alerts.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/monitor/config.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/monitor/diff.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/monitor/jobs.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/monitor/scheduler.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/pacing/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/scraper/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/scraper/scrape.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/scraper/scrape_js.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/scraper/tor_pool.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/search/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/search/circuit_breaker.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/search/config.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/search/engine_catalog.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/search/query_builder.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/search/search.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/search/tor_isolation.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/setup.cfg +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/actor_profiles.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/blockchain.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/breach_lookup.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/cache.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/cisa.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/data/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/data/onion_seeds.json +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/dns_enrichment.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/domain_reputation.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/email_reputation.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/engines.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/enrichment.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/github_scraper.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/gitlab_scraper.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/hash_reputation.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/historical_intel.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/infostealer.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/ip_reputation.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/nvd.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/paste_scraper.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/pastes.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/proxy_client.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/rss_scraper.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/seed_manager.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/seeds.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/shodan.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/telegram.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/sources/virustotal.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_actor_extraction_gap.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_analysis_opsec.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_analysis_stylometry.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_analysis_temporal.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_api_monitors.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_blockchain.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_breach_lookup.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_cli_manifest.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_confidence_calibration.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_config.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_consolidated_contracts.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_crawler.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_db.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_dependency_relationship.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_dns_enrichment.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_domain_reputation.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_email_reputation.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_entity_priority.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_extractor_llm_pipeline.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_filter_e2e_manual.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_filter_parser_manual.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_fingerprint.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_gazetteer.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_github_scraper.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_gitlab_scraper.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_graph.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_graph_integration.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_hash_reputation.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_heuristic_expansion.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_i18n.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_infostealer.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_ip_reputation.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_llm.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_llm_utils.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_model_singleton.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_monitor.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_monitor_integration.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_nvd.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_pacing.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_pacing_enrichment.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_pacing_quotas.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_pagination.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_paste_scraper.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_proxy_client.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_ransomlook.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_regex_patterns.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_relationship_extract.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_requirement_bugs.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_rss_scraper.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_scrape_isolation.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_scrape_js.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_settings.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_snort_export.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_software_suppression.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_sources.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_sources_enrichment_new.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_stix_export.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_vector.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/tests/test_yara_export.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/utils/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/utils/async_utils.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/utils/content_dedup.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/utils/content_safety.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/utils/defang.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/utils/encryption.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/utils/enrichment_cache.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/utils/entity_priority.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/utils/investigation_metrics.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/utils/ioc_freshness.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/utils/user_keys.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/vector/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/vector/embedder.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/vector/model_singleton.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/vector/search.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/vector/store.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess/config.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess/llm.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess/llm_utils.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess.egg-info/dependency_links.txt +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess.egg-info/requires.txt +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/adapters/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/browser.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/commands/__init__.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/commands/actors.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/commands/configure.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/commands/enrich.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/commands/show.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/config.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/display.py +0 -0
- {voidaccess-2.0.0 → voidaccess-2.0.2}/voidaccess_cli/tor_detect.py +0 -0
|
@@ -332,7 +332,7 @@ async def _periodic_stuck_sweep() -> None:
|
|
|
332
332
|
app = FastAPI(
|
|
333
333
|
title="VoidAccess Intelligence API",
|
|
334
334
|
description="VoidAccess: Dark Web Intelligence Platform",
|
|
335
|
-
version="2.0.
|
|
335
|
+
version="2.0.2",
|
|
336
336
|
docs_url="/docs",
|
|
337
337
|
redoc_url="/redoc",
|
|
338
338
|
lifespan=lifespan,
|
|
@@ -85,6 +85,10 @@ async def list_entities(
|
|
|
85
85
|
.limit(limit)
|
|
86
86
|
.all()
|
|
87
87
|
)
|
|
88
|
+
# Score each row against its own investigation (cached per
|
|
89
|
+
# investigation id so a page of same-investigation entities builds
|
|
90
|
+
# the map once), matching the CLI export and /entities/{id} exactly.
|
|
91
|
+
priority_cache: dict = {}
|
|
88
92
|
return {
|
|
89
93
|
"items": [
|
|
90
94
|
{
|
|
@@ -98,6 +102,7 @@ async def list_entities(
|
|
|
98
102
|
"investigation_id": str(e.investigation_id) if e.investigation_id else None,
|
|
99
103
|
"investigation_count": getattr(e, "investigation_count", 1) or 1,
|
|
100
104
|
"created_at": e.created_at.isoformat() if e.created_at else None,
|
|
105
|
+
**_entity_priority_fields(session, e, priority_cache),
|
|
101
106
|
}
|
|
102
107
|
for e in entities
|
|
103
108
|
],
|
|
@@ -150,7 +155,10 @@ async def export_entity_stix(
|
|
|
150
155
|
})
|
|
151
156
|
except Exception as exc:
|
|
152
157
|
logger.warning("STIX export for entity %s failed, falling back to raw JSON: %s", entity_id, exc)
|
|
153
|
-
json_str = json.dumps(
|
|
158
|
+
json_str = json.dumps(
|
|
159
|
+
_entity_to_dict(entity, _entity_priority_fields(session, entity)),
|
|
160
|
+
indent=2,
|
|
161
|
+
)
|
|
154
162
|
|
|
155
163
|
filename = f"voidaccess_entity_{entity_id}_stix.json"
|
|
156
164
|
return Response(
|
|
@@ -184,7 +192,7 @@ async def export_entity_json(
|
|
|
184
192
|
_assert_entity_accessible(session, eid, current_user.user.id)
|
|
185
193
|
|
|
186
194
|
appearances = get_entity_appearances(session, eid, current_user.user.id)
|
|
187
|
-
data = _entity_to_dict(entity)
|
|
195
|
+
data = _entity_to_dict(entity, _entity_priority_fields(session, entity))
|
|
188
196
|
data["appearances"] = appearances
|
|
189
197
|
json_str = json.dumps(data, indent=2, default=str)
|
|
190
198
|
|
|
@@ -629,8 +637,10 @@ async def get_entity(
|
|
|
629
637
|
if entity.context:
|
|
630
638
|
display_context = defang_text(entity.context)
|
|
631
639
|
|
|
640
|
+
priority = _entity_priority_fields(session, entity)
|
|
641
|
+
|
|
632
642
|
return {
|
|
633
|
-
**_entity_to_dict(entity),
|
|
643
|
+
**_entity_to_dict(entity, priority),
|
|
634
644
|
"value": display_value,
|
|
635
645
|
"canonical_value": display_canonical,
|
|
636
646
|
"context": display_context,
|
|
@@ -798,7 +808,90 @@ def _assert_entity_accessible(session, entity_id: uuid.UUID, user_id: int) -> No
|
|
|
798
808
|
raise HTTPException(status_code=404, detail="Entity not found")
|
|
799
809
|
|
|
800
810
|
|
|
801
|
-
|
|
811
|
+
# Default priority fields for an entity we could not (or chose not to) score.
|
|
812
|
+
# Mirrors the zero-defaults the investigation entities endpoint uses so the two
|
|
813
|
+
# API surfaces are shape-identical.
|
|
814
|
+
_EMPTY_PRIORITY: dict = {
|
|
815
|
+
"priority_score": 0.0,
|
|
816
|
+
"priority_score_components": {},
|
|
817
|
+
"priority_score_centrality_contribution": 0.0,
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
def _investigation_priority_map(session, investigation_id) -> dict:
|
|
822
|
+
"""Return ``score_map`` for a whole investigation, scoped identically to the
|
|
823
|
+
investigation entities endpoint and the CLI export.
|
|
824
|
+
|
|
825
|
+
Prioritization is normalized against the *complete* investigation (direct +
|
|
826
|
+
linked entities, all relationships), never a single entity or a filtered
|
|
827
|
+
page — that is what makes the value returned here byte-for-byte comparable
|
|
828
|
+
to ``GET /investigations/{id}/entities`` and to the CLI JSON/CSV/MD export
|
|
829
|
+
for the same entity (see ``api/routes/investigations.py`` and
|
|
830
|
+
``voidaccess_cli/commands/export.py``).
|
|
831
|
+
"""
|
|
832
|
+
from db.models import Entity, EntityRelationship, InvestigationEntityLink # noqa: PLC0415
|
|
833
|
+
import sqlalchemy as sa # noqa: PLC0415
|
|
834
|
+
from utils.entity_priority import score_map # noqa: PLC0415
|
|
835
|
+
|
|
836
|
+
linked_ids = (
|
|
837
|
+
sa.select(InvestigationEntityLink.entity_id)
|
|
838
|
+
.where(InvestigationEntityLink.investigation_id == investigation_id)
|
|
839
|
+
)
|
|
840
|
+
scoped = (
|
|
841
|
+
session.query(Entity)
|
|
842
|
+
.filter(
|
|
843
|
+
(Entity.investigation_id == investigation_id)
|
|
844
|
+
| Entity.id.in_(linked_ids)
|
|
845
|
+
)
|
|
846
|
+
.all()
|
|
847
|
+
)
|
|
848
|
+
relationships = (
|
|
849
|
+
session.query(EntityRelationship)
|
|
850
|
+
.filter(EntityRelationship.investigation_id == investigation_id)
|
|
851
|
+
.all()
|
|
852
|
+
)
|
|
853
|
+
return score_map(scoped, relationships)
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
def _entity_priority_fields(session, entity, cache: Optional[dict] = None) -> dict:
|
|
857
|
+
"""Return the three ``priority_score`` fields for *entity*, computed with the
|
|
858
|
+
same function and the same investigation-wide input set the CLI export uses.
|
|
859
|
+
|
|
860
|
+
``cache`` (an optional ``dict`` keyed by investigation id) lets a list
|
|
861
|
+
endpoint score many entities from the same investigation without rebuilding
|
|
862
|
+
the score map per row. Any failure degrades to zero defaults rather than
|
|
863
|
+
breaking the response.
|
|
864
|
+
"""
|
|
865
|
+
inv_id = getattr(entity, "investigation_id", None)
|
|
866
|
+
if inv_id is None:
|
|
867
|
+
return dict(_EMPTY_PRIORITY)
|
|
868
|
+
try:
|
|
869
|
+
if cache is not None and inv_id in cache:
|
|
870
|
+
pmap = cache[inv_id]
|
|
871
|
+
else:
|
|
872
|
+
pmap = _investigation_priority_map(session, inv_id)
|
|
873
|
+
if cache is not None:
|
|
874
|
+
cache[inv_id] = pmap
|
|
875
|
+
entry = pmap.get(str(entity.id), {})
|
|
876
|
+
return {
|
|
877
|
+
"priority_score": entry.get("priority_score", 0.0),
|
|
878
|
+
"priority_score_components": entry.get("priority_score_components", {}),
|
|
879
|
+
"priority_score_centrality_contribution": entry.get(
|
|
880
|
+
"priority_score_centrality_contribution", 0.0
|
|
881
|
+
),
|
|
882
|
+
}
|
|
883
|
+
except Exception as exc: # pragma: no cover - defensive
|
|
884
|
+
logger.warning("entity priority computation failed: %s", exc)
|
|
885
|
+
return dict(_EMPTY_PRIORITY)
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
def _entity_to_dict(entity, priority: Optional[dict] = None) -> dict: # type: ignore[type-arg]
|
|
889
|
+
# ``priority`` carries the three prioritization fields (see
|
|
890
|
+
# ``_entity_priority_fields``). It is passed in by callers that hold an open
|
|
891
|
+
# session so the score matches the CLI export exactly; when absent we emit
|
|
892
|
+
# the same zero defaults as the investigation entities endpoint so the field
|
|
893
|
+
# is always present on the ``/entities`` surface.
|
|
894
|
+
priority = priority or _EMPTY_PRIORITY
|
|
802
895
|
return {
|
|
803
896
|
"id": str(entity.id),
|
|
804
897
|
"entity_type": entity.entity_type,
|
|
@@ -816,6 +909,11 @@ def _entity_to_dict(entity) -> dict: # type: ignore[type-arg]
|
|
|
816
909
|
"source_count": getattr(entity, "source_count", 1) or 1,
|
|
817
910
|
"investigation_count": getattr(entity, "investigation_count", 1) or 1,
|
|
818
911
|
"corroborating_sources": getattr(entity, "corroborating_sources", None),
|
|
912
|
+
"priority_score": priority.get("priority_score", 0.0),
|
|
913
|
+
"priority_score_components": priority.get("priority_score_components", {}),
|
|
914
|
+
"priority_score_centrality_contribution": priority.get(
|
|
915
|
+
"priority_score_centrality_contribution", 0.0
|
|
916
|
+
),
|
|
819
917
|
}
|
|
820
918
|
|
|
821
919
|
|
|
@@ -16,6 +16,7 @@ POST /export/{investigation_id}/<fmt>/selected — same exports rest
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
18
|
import io
|
|
19
|
+
import json
|
|
19
20
|
import logging
|
|
20
21
|
import os
|
|
21
22
|
import re
|
|
@@ -474,6 +475,21 @@ async def export_package(
|
|
|
474
475
|
investigation_dict["created_at"] = (
|
|
475
476
|
inv.created_at.isoformat() if inv.created_at else None
|
|
476
477
|
)
|
|
478
|
+
# Backfill sources_used from investigation metadata, the
|
|
479
|
+
# same place the CLI export reads it (adapters/sqlite.py
|
|
480
|
+
# ``_investigation_row``). ``metadata_json`` is a dict on
|
|
481
|
+
# Postgres and may be a JSON string on legacy SQLite rows.
|
|
482
|
+
metadata_raw = getattr(inv, "metadata_json", None)
|
|
483
|
+
if isinstance(metadata_raw, str):
|
|
484
|
+
try:
|
|
485
|
+
metadata_parsed = json.loads(metadata_raw) if metadata_raw.strip() else {}
|
|
486
|
+
except (ValueError, TypeError):
|
|
487
|
+
metadata_parsed = {}
|
|
488
|
+
elif isinstance(metadata_raw, dict):
|
|
489
|
+
metadata_parsed = metadata_raw
|
|
490
|
+
else:
|
|
491
|
+
metadata_parsed = {}
|
|
492
|
+
investigation_dict["sources_used"] = metadata_parsed.get("sources_used") or {}
|
|
477
493
|
except Exception as exc:
|
|
478
494
|
logger.warning("export_package: investigation lookup failed: %s", exc)
|
|
479
495
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Bundled reference data shipped inside the installed package.
|
|
2
|
+
|
|
3
|
+
This directory is declared as a package (with this empty ``__init__.py``) so
|
|
4
|
+
that setuptools ships its data files inside the wheel at ``<root>/data/`` —
|
|
5
|
+
the exact location the runtime resolves via
|
|
6
|
+
``os.path.dirname(os.path.dirname(__file__))/data`` from ``extractor/`` and
|
|
7
|
+
``monitor/`` (and ``Path(__file__).parent.parent/data`` from ``monitor/``).
|
|
8
|
+
|
|
9
|
+
Without this, a fresh ``pip install voidaccess`` produces a package with no
|
|
10
|
+
``data/`` directory, and query expansion / shape-checking silently degrade to
|
|
11
|
+
structural-signals-only ("Gazetteer snapshot not found",
|
|
12
|
+
"Common-word list not found"). See pyproject ``[tool.setuptools.package-data]``.
|
|
13
|
+
"""
|