classifyre-cli 0.4.15__tar.gz → 0.4.16__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.
Files changed (197) hide show
  1. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/.turbo/turbo-build.log +1 -1
  2. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/PKG-INFO +1 -1
  3. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/package.json +1 -1
  4. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/pyproject.toml +2 -1
  5. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/runners/_object_detection.py +1 -0
  6. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/main.py +10 -0
  7. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/outputs/rest.py +49 -0
  8. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/base.py +13 -0
  9. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/email/source.py +23 -0
  10. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/uv.lock +23 -2
  11. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/.gitignore +0 -0
  12. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/.python-version +0 -0
  13. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/README.md +0 -0
  14. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/main.py +0 -0
  15. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/scripts/generate_models.py +0 -0
  16. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/__init__.py +0 -0
  17. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/__init__.py +0 -0
  18. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/base.py +0 -0
  19. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/broken_links/__init__.py +0 -0
  20. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/broken_links/detector.py +0 -0
  21. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/config.py +0 -0
  22. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/content/__init__.py +0 -0
  23. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/__init__.py +0 -0
  24. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/detector.py +0 -0
  25. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/extractor.py +0 -0
  26. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/runners/__init__.py +0 -0
  27. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/runners/_base.py +0 -0
  28. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/runners/_factory.py +0 -0
  29. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/runners/_feature_extraction.py +0 -0
  30. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/runners/_gliner2.py +0 -0
  31. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/runners/_image_classification.py +0 -0
  32. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/runners/_llm.py +0 -0
  33. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/runners/_regex.py +0 -0
  34. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/runners/_text_classification.py +0 -0
  35. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/custom/trainer.py +0 -0
  36. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/dependencies.py +0 -0
  37. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/pii/__init__.py +0 -0
  38. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/pii/detector.py +0 -0
  39. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/secrets/__init__.py +0 -0
  40. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/secrets/detector.py +0 -0
  41. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/threat/__init__.py +0 -0
  42. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/threat/code_security_detector.py +0 -0
  43. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/detectors/threat/yara_detector.py +0 -0
  44. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/models/generated_detectors.py +0 -0
  45. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/models/generated_input.py +0 -0
  46. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/models/generated_single_asset_scan_results.py +0 -0
  47. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/outputs/__init__.py +0 -0
  48. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/outputs/base.py +0 -0
  49. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/outputs/console.py +0 -0
  50. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/outputs/factory.py +0 -0
  51. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/outputs/file.py +0 -0
  52. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/pipeline/__init__.py +0 -0
  53. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/pipeline/content_provider.py +0 -0
  54. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/pipeline/detector_pipeline.py +0 -0
  55. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/pipeline/parsed_content_provider.py +0 -0
  56. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/pipeline/worker_pool.py +0 -0
  57. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sandbox/__init__.py +0 -0
  58. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sandbox/runner.py +0 -0
  59. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/__init__.py +0 -0
  60. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/asset_metadata.py +0 -0
  61. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/atlassian_common.py +0 -0
  62. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/azure_blob_storage/__init__.py +0 -0
  63. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/azure_blob_storage/source.py +0 -0
  64. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/confluence/__init__.py +0 -0
  65. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/confluence/source.py +0 -0
  66. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/databricks/__init__.py +0 -0
  67. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/databricks/source.py +0 -0
  68. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/dependencies.py +0 -0
  69. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/email/__init__.py +0 -0
  70. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/google_cloud_storage/__init__.py +0 -0
  71. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/google_cloud_storage/source.py +0 -0
  72. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/hive/__init__.py +0 -0
  73. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/hive/source.py +0 -0
  74. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/jira/__init__.py +0 -0
  75. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/jira/source.py +0 -0
  76. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/mongodb/__init__.py +0 -0
  77. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/mongodb/source.py +0 -0
  78. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/mssql/__init__.py +0 -0
  79. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/mssql/source.py +0 -0
  80. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/mysql/__init__.py +0 -0
  81. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/mysql/source.py +0 -0
  82. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/neo4j/__init__.py +0 -0
  83. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/neo4j/source.py +0 -0
  84. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/notion/__init__.py +0 -0
  85. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/notion/client.py +0 -0
  86. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/notion/source.py +0 -0
  87. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/object_storage/base.py +0 -0
  88. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/oracle/__init__.py +0 -0
  89. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/oracle/source.py +0 -0
  90. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/postgresql/__init__.py +0 -0
  91. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/postgresql/source.py +0 -0
  92. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/powerbi/__init__.py +0 -0
  93. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/powerbi/source.py +0 -0
  94. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/recipe_normalizer.py +0 -0
  95. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/s3_compatible_storage/README.md +0 -0
  96. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/s3_compatible_storage/__init__.py +0 -0
  97. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/s3_compatible_storage/source.py +0 -0
  98. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/servicedesk/__init__.py +0 -0
  99. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/servicedesk/source.py +0 -0
  100. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/slack/__init__.py +0 -0
  101. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/slack/source.py +0 -0
  102. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/snowflake/__init__.py +0 -0
  103. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/snowflake/source.py +0 -0
  104. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/sqlite/__init__.py +0 -0
  105. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/sqlite/source.py +0 -0
  106. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/tableau/__init__.py +0 -0
  107. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/tableau/source.py +0 -0
  108. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/tabular_base.py +0 -0
  109. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/tabular_utils.py +0 -0
  110. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/wordpress/__init__.py +0 -0
  111. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/sources/wordpress/source.py +0 -0
  112. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/telemetry.py +0 -0
  113. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/utils/__init__.py +0 -0
  114. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/utils/content_extraction.py +0 -0
  115. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/utils/dependency_groups.py +0 -0
  116. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/utils/embedded_images.py +0 -0
  117. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/utils/file_metadata.py +0 -0
  118. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/utils/file_parser.py +0 -0
  119. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/utils/file_to_images.py +0 -0
  120. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/utils/hashing.py +0 -0
  121. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/utils/uv_sync.py +0 -0
  122. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/src/utils/validation.py +0 -0
  123. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/__init__.py +0 -0
  124. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/conftest.py +0 -0
  125. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/__init__.py +0 -0
  126. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/broken_links/test_broken_links_detector.py +0 -0
  127. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/conftest.py +0 -0
  128. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/content/__init__.py +0 -0
  129. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/custom/__init__.py +0 -0
  130. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/custom/conftest.py +0 -0
  131. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/custom/test_invoice_extraction.py +0 -0
  132. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/custom/test_llm_runner.py +0 -0
  133. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/custom/test_pipeline_integration.py +0 -0
  134. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/custom/test_regex_runner.py +0 -0
  135. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/custom/test_transformer_runners.py +0 -0
  136. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/pii/__init__.py +0 -0
  137. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/pii/conftest.py +0 -0
  138. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/pii/sample_invoice.pdf +0 -0
  139. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/pii/test_pii_detector.py +0 -0
  140. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/pii/test_pii_detector_extended.py +0 -0
  141. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/secrets/__init__.py +0 -0
  142. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/secrets/test_secrets_detector.py +0 -0
  143. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/secrets/test_secrets_detector_extended.py +0 -0
  144. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/test_base_detector.py +0 -0
  145. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/test_custom_detector_examples_runtime.py +0 -0
  146. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/test_detector_catalog_commercial.py +0 -0
  147. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/test_detector_pipeline_types.py +0 -0
  148. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/test_detector_schema_examples.py +0 -0
  149. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/test_detector_types.py +0 -0
  150. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/test_phase2_detectors.py +0 -0
  151. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/test_registry.py +0 -0
  152. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/threat/__init__.py +0 -0
  153. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/threat/test_code_security_detector.py +0 -0
  154. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/detectors/threat/test_yara_detector.py +0 -0
  155. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/integration/test_wordpress_broken_links_detector.py +0 -0
  156. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/integration/test_wordpress_links_assets.py +0 -0
  157. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/pipeline/test_detector_pipeline.py +0 -0
  158. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/pipeline/test_worker_pool.py +0 -0
  159. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_assets_metadata_catalog.py +0 -0
  160. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_azure_blob_storage_source.py +0 -0
  161. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_base_source_attachment.py +0 -0
  162. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_base_source_sampling.py +0 -0
  163. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_confluence_source.py +0 -0
  164. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_custom_extractor.py +0 -0
  165. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_databricks_source.py +0 -0
  166. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_dependency_groups.py +0 -0
  167. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_email_source.py +0 -0
  168. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_google_cloud_storage_source.py +0 -0
  169. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_hashing.py +0 -0
  170. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_hive_source.py +0 -0
  171. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_jira_source.py +0 -0
  172. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_mongodb_source.py +0 -0
  173. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_mssql_source.py +0 -0
  174. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_mysql_source.py +0 -0
  175. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_neo4j_source.py +0 -0
  176. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_notion_source.py +0 -0
  177. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_oracle_source.py +0 -0
  178. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_outputs.py +0 -0
  179. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_postgresql_source.py +0 -0
  180. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_powerbi_source.py +0 -0
  181. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_recipe_normalizer.py +0 -0
  182. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_s3_compatible_storage_source.py +0 -0
  183. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_sandbox_runner.py +0 -0
  184. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_servicedesk_source.py +0 -0
  185. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_slack_source.py +0 -0
  186. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_snowflake_source.py +0 -0
  187. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_source_dependency_groups.py +0 -0
  188. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_sqlite_source.py +0 -0
  189. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_tableau_source.py +0 -0
  190. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_tabular_utils.py +0 -0
  191. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_uv_sync.py +0 -0
  192. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/test_wordpress_source.py +0 -0
  193. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/utils/test_content_extraction.py +0 -0
  194. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/utils/test_embedded_images.py +0 -0
  195. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/utils/test_file_metadata.py +0 -0
  196. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/utils/test_file_parser.py +0 -0
  197. {classifyre_cli-0.4.15 → classifyre_cli-0.4.16}/tests/utils/test_file_to_images.py +0 -0
@@ -1,3 +1,3 @@
1
1
  $ uv sync
2
- Resolved 254 packages in 157ms
2
+ Resolved 255 packages in 216ms
3
3
  Checked 50 packages in 1ms
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: classifyre-cli
3
- Version: 0.4.15
3
+ Version: 0.4.16
4
4
  Summary: Classifyre CLI — scan and classify unstructured data sources
5
5
  License: MIT
6
6
  Keywords: data,ingestion,metadata,pii,secrets,unstructured
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classifyre/cli",
3
- "version": "0.4.15",
3
+ "version": "0.4.16",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "build": "uv sync",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "classifyre-cli"
3
- version = "0.4.15"
3
+ version = "0.4.16"
4
4
  description = "Classifyre CLI — scan and classify unstructured data sources"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -94,6 +94,7 @@ custom = [
94
94
  "transformers>=4.50.0,<6.0.0",
95
95
  "torch>=2.12.0",
96
96
  "pillow>=12.2.0",
97
+ "timm>=1.0.27",
97
98
  "setfit>=1.1.3",
98
99
  "datasets>=4.8.5",
99
100
  "scikit-learn>=1.7.2",
@@ -48,6 +48,7 @@ class ObjectDetectionRunner(BaseRunner):
48
48
  raise MissingDependencyError(
49
49
  "object_detection",
50
50
  ["custom", "detectors"],
51
+ ["custom", "detectors"],
51
52
  f"ObjectDetectionRunner requires additional dependencies: {exc}",
52
53
  ) from exc
53
54
 
@@ -372,6 +372,16 @@ async def run_command_async(args: argparse.Namespace, recipe: dict[str, Any]) ->
372
372
  total_assets,
373
373
  output_batch_count,
374
374
  )
375
+
376
+ # Phase 1: emit source-derived relationship edges (best-effort).
377
+ if hasattr(source, "collect_relationships") and hasattr(sink, "emit_edges"):
378
+ try:
379
+ edges = await source.collect_relationships()
380
+ if edges:
381
+ await sink.emit_edges(edges)
382
+ logger.info("Emitted %d source-derived relationship edges", len(edges))
383
+ except Exception as rel_error:
384
+ logger.warning("Relationship emission failed (non-fatal): %s", rel_error)
375
385
  except Exception as extraction_error:
376
386
  if _is_timeout_error(extraction_error):
377
387
  logger.warning(
@@ -97,6 +97,31 @@ class BulkIngestAssetsRequest(BaseModel):
97
97
  skip_findings: bool = Field(False, serialization_alias="skipFindings")
98
98
 
99
99
 
100
+ class IngestEdge(BaseModel):
101
+ """A source-derived relationship edge for the investigation graph.
102
+
103
+ Identify endpoints by UUID (from_id / to_id) or by asset hash
104
+ (from_hash / to_hash — the API resolves hashes to UUIDs).
105
+ """
106
+
107
+ model_config = ConfigDict(populate_by_name=True)
108
+
109
+ from_type: str = Field(serialization_alias="fromType")
110
+ from_id: str | None = Field(None, serialization_alias="fromId")
111
+ from_hash: str | None = Field(None, serialization_alias="fromHash")
112
+ to_type: str = Field(serialization_alias="toType")
113
+ to_id: str | None = Field(None, serialization_alias="toId")
114
+ to_hash: str | None = Field(None, serialization_alias="toHash")
115
+ relation_type: str = Field(serialization_alias="relationType")
116
+ confidence: float = 1.0
117
+
118
+
119
+ class BulkIngestEdgesRequest(BaseModel):
120
+ model_config = ConfigDict(populate_by_name=True)
121
+
122
+ edges: list[IngestEdge]
123
+
124
+
100
125
  class FinalizeIngestRunRequest(BaseModel):
101
126
  model_config = ConfigDict(populate_by_name=True)
102
127
 
@@ -252,6 +277,30 @@ class RestOutputSink:
252
277
  update_error,
253
278
  )
254
279
 
280
+ async def emit_edges(self, edges: list[IngestEdge]) -> None:
281
+ """Bulk-upsert source-derived relationship edges to the investigation graph.
282
+
283
+ Idempotent — safe to call multiple times with overlapping data.
284
+ Silently skips if the list is empty.
285
+ """
286
+ if not edges:
287
+ return
288
+
289
+ _edge_batch = 500
290
+ for i in range(0, len(edges), _edge_batch):
291
+ chunk = edges[i : i + _edge_batch]
292
+ payload = BulkIngestEdgesRequest(edges=chunk)
293
+ try:
294
+ self._request_json(
295
+ "POST",
296
+ "/graph/edges",
297
+ payload.model_dump(mode="json", by_alias=True),
298
+ )
299
+ logger.debug("Emitted %d source-derived edges to graph", len(chunk))
300
+ except Exception as exc:
301
+ # Edge emission is best-effort: log and continue.
302
+ logger.warning("Failed to emit edges to graph: %s", exc)
303
+
255
304
  async def register_discovered_assets(self, hashes: list[str]) -> None:
256
305
  runner_id = self._require_runner_id()
257
306
  for i in range(0, len(hashes), 500):
@@ -4,6 +4,7 @@ from collections.abc import AsyncGenerator, Generator
4
4
  from typing import TYPE_CHECKING, Any
5
5
 
6
6
  from ..models.generated_single_asset_scan_results import DetectionResult, SingleAssetScanResults
7
+ from ..outputs.rest import IngestEdge
7
8
 
8
9
  if TYPE_CHECKING:
9
10
  from ..utils.file_parser import ParsedBytes
@@ -315,3 +316,15 @@ class BaseSource(ABC):
315
316
  this and map those identifiers back to their original URLs.
316
317
  """
317
318
  return normalize_http_url(link)
319
+
320
+
321
+ async def collect_relationships(self) -> list[IngestEdge]:
322
+ """Return source-derived relationship edges for the investigation graph.
323
+
324
+ Connectors override this to emit typed edges (READS, ATTACHED_TO,
325
+ SENT_TO, OWNS, ACCESSED, etc.) discovered during extraction. The caller
326
+ (main.py) will forward these to ``RestOutputSink.emit_edges()``.
327
+
328
+ Default: no relationships (empty list).
329
+ """
330
+ return []
@@ -102,6 +102,8 @@ class EmailSource(BaseSource):
102
102
  self._email_locator_by_hash: dict[str, tuple[str, str]] = {}
103
103
  self._hash_by_url: dict[str, str] = {}
104
104
  self._attachment_name_by_hash = {}
105
+ # Phase 1: tracks (email_hash → [attachment_hash, ...]) for relationship emission.
106
+ self._email_attachment_links: dict[str, list[str]] = {}
105
107
 
106
108
  self._mailbox: Any = None
107
109
 
@@ -303,6 +305,9 @@ class EmailSource(BaseSource):
303
305
  runner_id=self.runner_id,
304
306
  **self.metadata_fields("email", metadata),
305
307
  )
308
+ # Track for Phase 1 relationship emission.
309
+ if attachment_hashes:
310
+ self._email_attachment_links[email_hash] = attachment_hashes
306
311
  return [email_asset, *attachment_assets]
307
312
 
308
313
  def _attachment_to_asset(
@@ -515,6 +520,24 @@ class EmailSource(BaseSource):
515
520
  # ------------------------------------------------------------------
516
521
  # Lifecycle
517
522
  # ------------------------------------------------------------------
523
+ async def collect_relationships(self) -> list[Any]:
524
+ """Emit ATTACHED_TO edges: email → attachment for each extracted message."""
525
+ from ...outputs.rest import IngestEdge
526
+
527
+ edges: list[IngestEdge] = []
528
+ for email_hash, attachment_hashes in self._email_attachment_links.items():
529
+ for att_hash in attachment_hashes:
530
+ edges.append(
531
+ IngestEdge(
532
+ from_type="asset",
533
+ from_hash=email_hash,
534
+ to_type="asset",
535
+ to_hash=att_hash,
536
+ relation_type="ATTACHED_TO",
537
+ )
538
+ )
539
+ return edges
540
+
518
541
  def abort(self) -> None:
519
542
  logger.info("Aborting email extraction...")
520
543
  super().abort()
@@ -606,7 +606,7 @@ wheels = [
606
606
 
607
607
  [[package]]
608
608
  name = "classifyre-cli"
609
- version = "0.4.15"
609
+ version = "0.4.16"
610
610
  source = { editable = "." }
611
611
  dependencies = [
612
612
  { name = "beautifulsoup4" },
@@ -643,6 +643,7 @@ custom = [
643
643
  { name = "scikit-learn" },
644
644
  { name = "sentence-transformers" },
645
645
  { name = "setfit" },
646
+ { name = "timm" },
646
647
  { name = "torch", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform != 'linux'" },
647
648
  { name = "torch", version = "2.12.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "sys_platform == 'linux'" },
648
649
  { name = "transformers" },
@@ -678,6 +679,7 @@ detectors = [
678
679
  { name = "setfit" },
679
680
  { name = "spacy" },
680
681
  { name = "textstat" },
682
+ { name = "timm" },
681
683
  { name = "torch", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform != 'linux'" },
682
684
  { name = "torch", version = "2.12.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "sys_platform == 'linux'" },
683
685
  { name = "transformers" },
@@ -821,6 +823,7 @@ custom = [
821
823
  { name = "scikit-learn", specifier = ">=1.7.2" },
822
824
  { name = "sentence-transformers", specifier = ">=5.5.0" },
823
825
  { name = "setfit", specifier = ">=1.1.3" },
826
+ { name = "timm", specifier = ">=1.0.27" },
824
827
  { name = "torch", marker = "sys_platform != 'linux'", specifier = ">=2.12.0" },
825
828
  { name = "torch", marker = "sys_platform == 'linux'", specifier = ">=2.12.0", index = "https://download.pytorch.org/whl/cpu" },
826
829
  { name = "transformers", specifier = ">=4.50.0,<6.0.0" },
@@ -856,6 +859,7 @@ detectors = [
856
859
  { name = "setfit", specifier = ">=1.1.3" },
857
860
  { name = "spacy", specifier = ">=3.8.14" },
858
861
  { name = "textstat", specifier = ">=0.7.13" },
862
+ { name = "timm", specifier = ">=1.0.27" },
859
863
  { name = "torch", marker = "sys_platform != 'linux'", specifier = ">=2.12.0" },
860
864
  { name = "torch", marker = "sys_platform == 'linux'", specifier = ">=2.12.0", index = "https://download.pytorch.org/whl/cpu" },
861
865
  { name = "transformers", specifier = ">=4.50.0,<6.0.0" },
@@ -942,7 +946,7 @@ threat-ml = [
942
946
 
943
947
  [[package]]
944
948
  name = "classifyre-schemas"
945
- version = "0.4.15"
949
+ version = "0.4.16"
946
950
  source = { editable = "../../packages/schemas" }
947
951
  dependencies = [
948
952
  { name = "fastjsonschema" },
@@ -5349,6 +5353,23 @@ wheels = [
5349
5353
  { url = "https://files.pythonhosted.org/packages/16/5b/f2aa703a4fc5d2dff73460a7d46cc2f3f44aa0f3dd8eeb20d2a0ecf68862/tiktoken-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:85b78cc3a2c3d48723ca751fa981f1fedccd54194ca0471b957364353a898b07", size = 918110, upload-time = "2026-05-15T04:51:17.237Z" },
5350
5354
  ]
5351
5355
 
5356
+ [[package]]
5357
+ name = "timm"
5358
+ version = "1.0.27"
5359
+ source = { registry = "https://pypi.org/simple" }
5360
+ dependencies = [
5361
+ { name = "huggingface-hub" },
5362
+ { name = "pyyaml" },
5363
+ { name = "safetensors" },
5364
+ { name = "torch", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform != 'linux'" },
5365
+ { name = "torch", version = "2.12.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "sys_platform == 'linux'" },
5366
+ { name = "torchvision" },
5367
+ ]
5368
+ sdist = { url = "https://files.pythonhosted.org/packages/08/54/ece85b0eef3700c90db8271a43669b05a0ebbe2edb1962329c34374a297e/timm-1.0.27.tar.gz", hash = "sha256:315dfe63186ca9fb7ff941268941231fd5be259f2b4bb4afa28560ae1015cb9a", size = 2439861, upload-time = "2026-05-08T19:38:36.844Z" }
5369
+ wheels = [
5370
+ { url = "https://files.pythonhosted.org/packages/1f/2e/26bab7686ff4aed48f8f5f6c23e2aa37b7a37ddd9effe3aa61e908fd518f/timm-1.0.27-py3-none-any.whl", hash = "sha256:5ff07c9ddf53cbada88eab1c93ff175c64cab683b5a2fddf863bcee985926f89", size = 2589280, upload-time = "2026-05-08T19:38:35.034Z" },
5371
+ ]
5372
+
5352
5373
  [[package]]
5353
5374
  name = "tldextract"
5354
5375
  version = "5.3.1"
File without changes