classifyre-cli 0.6.3__tar.gz → 0.6.5__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 (374) hide show
  1. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/.turbo/turbo-build.log +1 -1
  2. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/PKG-INFO +1 -1
  3. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/package.json +1 -1
  4. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/pyproject.toml +1 -1
  5. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/scripts/generate_models.py +12 -0
  6. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/scripts/generate_sdk_completions.py +12 -0
  7. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/sdk.py +34 -0
  8. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/session.py +24 -162
  9. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/__init__.py +2 -0
  10. classifyre_cli-0.6.5/src/detectors/custom/runners/_custom_detector.py +72 -0
  11. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_factory.py +6 -0
  12. classifyre_cli-0.6.5/src/detectors/custom_detector/__init__.py +9 -0
  13. classifyre_cli-0.6.5/src/detectors/custom_detector/contract.py +45 -0
  14. classifyre_cli-0.6.5/src/detectors/custom_detector/files.py +102 -0
  15. classifyre_cli-0.6.5/src/detectors/custom_detector/preview.py +283 -0
  16. classifyre_cli-0.6.5/src/detectors/custom_detector/results.py +266 -0
  17. classifyre_cli-0.6.5/src/detectors/custom_detector/runner.py +258 -0
  18. classifyre_cli-0.6.5/src/detectors/custom_detector/sdk.py +334 -0
  19. classifyre_cli-0.6.5/src/detectors/custom_detector/session.py +443 -0
  20. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/engine_version.py +41 -1
  21. classifyre_cli-0.6.5/src/file_evaluation/asset_fixture.py +142 -0
  22. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/file_evaluation/runner.py +110 -6
  23. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/graph/__init__.py +2 -0
  24. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/graph/edges.py +51 -2
  25. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/main.py +26 -0
  26. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/models/generated_detectors.py +250 -0
  27. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/models/generated_single_asset_scan_results.py +6 -1
  28. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/child.py +5 -1
  29. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/cli.py +54 -4
  30. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/protocol.py +24 -0
  31. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/sdk.py +129 -1
  32. classifyre_cli-0.6.5/src/pipeline/asset_payload_server.py +242 -0
  33. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/detector_pipeline.py +121 -0
  34. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/scan_cache.py +66 -15
  35. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/redaction.py +22 -0
  36. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/urn.py +28 -1
  37. classifyre_cli-0.6.5/tests/detectors/test_custom_detector_session.py +303 -0
  38. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_sdk.py +1 -0
  39. classifyre_cli-0.6.5/tests/test_custom_detector_end_to_end.py +152 -0
  40. classifyre_cli-0.6.5/tests/test_custom_detector_evaluation.py +75 -0
  41. classifyre_cli-0.6.5/tests/test_custom_detector_notebook.py +136 -0
  42. classifyre_cli-0.6.5/tests/test_custom_detector_templates.py +86 -0
  43. classifyre_cli-0.6.5/tests/test_notebook_asset_entity.py +82 -0
  44. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_scan_cache.py +46 -0
  45. classifyre_cli-0.6.5/tests/test_semantic_declarations.py +96 -0
  46. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/uv.lock +722 -681
  47. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/.gitignore +0 -0
  48. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/.python-version +0 -0
  49. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/README.md +0 -0
  50. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/main.py +0 -0
  51. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/scripts/generate_runtime_packages.py +0 -0
  52. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/__init__.py +0 -0
  53. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/__init__.py +0 -0
  54. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/contract.py +0 -0
  55. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/preview.py +0 -0
  56. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/runner.py +0 -0
  57. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/config.py +0 -0
  58. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/__init__.py +0 -0
  59. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/base.py +0 -0
  60. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/broken_links/__init__.py +0 -0
  61. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/broken_links/detector.py +0 -0
  62. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/config.py +0 -0
  63. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/content/__init__.py +0 -0
  64. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/__init__.py +0 -0
  65. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/detector.py +0 -0
  66. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/extractor.py +0 -0
  67. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_base.py +0 -0
  68. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_gliner2.py +0 -0
  69. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_image_classification.py +0 -0
  70. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_llm.py +0 -0
  71. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_object_detection.py +0 -0
  72. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_regex.py +0 -0
  73. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_tag.py +0 -0
  74. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_text_classification.py +0 -0
  75. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/trainer.py +0 -0
  76. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/dependencies.py +0 -0
  77. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/errors.py +0 -0
  78. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/pii/__init__.py +0 -0
  79. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/pii/detector.py +0 -0
  80. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/secrets/__init__.py +0 -0
  81. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/secrets/detector.py +0 -0
  82. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/threat/__init__.py +0 -0
  83. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/threat/code_security_detector.py +0 -0
  84. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/threat/yara_detector.py +0 -0
  85. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/file_evaluation/__init__.py +0 -0
  86. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/models/generated_input.py +0 -0
  87. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/__init__.py +0 -0
  88. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/cohort.py +0 -0
  89. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/contract.py +0 -0
  90. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/execute.py +0 -0
  91. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/files.py +0 -0
  92. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/groups.py +0 -0
  93. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/outputs.py +0 -0
  94. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/packages.py +0 -0
  95. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/redact.py +0 -0
  96. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/scaffold.py +0 -0
  97. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/serialize.py +0 -0
  98. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/__init__.py +0 -0
  99. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/base.py +0 -0
  100. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/console.py +0 -0
  101. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/factory.py +0 -0
  102. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/file.py +0 -0
  103. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/rest.py +0 -0
  104. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/__init__.py +0 -0
  105. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/content_provider.py +0 -0
  106. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/detector_breaker.py +0 -0
  107. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/parsed_content_provider.py +0 -0
  108. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/payload_window.py +0 -0
  109. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/text_artifact.py +0 -0
  110. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/worker_pool.py +0 -0
  111. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/__init__.py +0 -0
  112. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/asset_metadata.py +0 -0
  113. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/atlassian_common.py +0 -0
  114. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/azure_blob_storage/__init__.py +0 -0
  115. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/azure_blob_storage/source.py +0 -0
  116. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/base.py +0 -0
  117. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/confluence/__init__.py +0 -0
  118. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/confluence/source.py +0 -0
  119. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/custom/__init__.py +0 -0
  120. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/custom/env.py +0 -0
  121. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/custom/runner.py +0 -0
  122. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/custom/source.py +0 -0
  123. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/databricks/__init__.py +0 -0
  124. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/databricks/source.py +0 -0
  125. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/delta_lake/__init__.py +0 -0
  126. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/delta_lake/source.py +0 -0
  127. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/dependencies.py +0 -0
  128. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/dropbox/__init__.py +0 -0
  129. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/dropbox/auth.py +0 -0
  130. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/dropbox/source.py +0 -0
  131. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/elasticsearch/__init__.py +0 -0
  132. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/elasticsearch/source.py +0 -0
  133. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/email/__init__.py +0 -0
  134. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/email/source.py +0 -0
  135. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/git/__init__.py +0 -0
  136. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/git/source.py +0 -0
  137. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/google_cloud_storage/__init__.py +0 -0
  138. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/google_cloud_storage/source.py +0 -0
  139. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/google_workspace/__init__.py +0 -0
  140. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/google_workspace/source.py +0 -0
  141. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/hive/__init__.py +0 -0
  142. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/hive/source.py +0 -0
  143. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/hugging_face/__init__.py +0 -0
  144. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/hugging_face/source.py +0 -0
  145. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/iceberg/__init__.py +0 -0
  146. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/iceberg/source.py +0 -0
  147. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/jira/__init__.py +0 -0
  148. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/jira/source.py +0 -0
  149. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/kafka/__init__.py +0 -0
  150. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/kafka/rest.py +0 -0
  151. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/kafka/source.py +0 -0
  152. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/lakehouse_base.py +0 -0
  153. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/local_folder/__init__.py +0 -0
  154. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/local_folder/source.py +0 -0
  155. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/meilisearch/__init__.py +0 -0
  156. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/meilisearch/source.py +0 -0
  157. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/microsoft_365/__init__.py +0 -0
  158. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/microsoft_365/source.py +0 -0
  159. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mongodb/__init__.py +0 -0
  160. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mongodb/source.py +0 -0
  161. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mssql/__init__.py +0 -0
  162. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mssql/source.py +0 -0
  163. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mysql/__init__.py +0 -0
  164. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mysql/source.py +0 -0
  165. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/neo4j/__init__.py +0 -0
  166. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/neo4j/source.py +0 -0
  167. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/notion/__init__.py +0 -0
  168. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/notion/client.py +0 -0
  169. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/notion/source.py +0 -0
  170. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/object_storage/base.py +0 -0
  171. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/opensearch/__init__.py +0 -0
  172. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/opensearch/source.py +0 -0
  173. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/oracle/__init__.py +0 -0
  174. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/oracle/source.py +0 -0
  175. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/postgresql/__init__.py +0 -0
  176. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/postgresql/source.py +0 -0
  177. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/powerbi/__init__.py +0 -0
  178. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/powerbi/source.py +0 -0
  179. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/recipe_normalizer.py +0 -0
  180. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/reddit/__init__.py +0 -0
  181. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/reddit/source.py +0 -0
  182. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/s3_client.py +0 -0
  183. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/s3_compatible_storage/README.md +0 -0
  184. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/s3_compatible_storage/__init__.py +0 -0
  185. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/s3_compatible_storage/source.py +0 -0
  186. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/sandbox/__init__.py +0 -0
  187. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/sandbox/source.py +0 -0
  188. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/search_engine_base.py +0 -0
  189. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/servicedesk/__init__.py +0 -0
  190. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/servicedesk/source.py +0 -0
  191. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/slack/__init__.py +0 -0
  192. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/slack/source.py +0 -0
  193. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/snowflake/__init__.py +0 -0
  194. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/snowflake/source.py +0 -0
  195. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/sqlite/__init__.py +0 -0
  196. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/sqlite/source.py +0 -0
  197. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/tableau/__init__.py +0 -0
  198. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/tableau/source.py +0 -0
  199. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/tabular_base.py +0 -0
  200. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/tabular_utils.py +0 -0
  201. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/wordpress/__init__.py +0 -0
  202. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/wordpress/source.py +0 -0
  203. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/youtube/__init__.py +0 -0
  204. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/youtube/source.py +0 -0
  205. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/telemetry.py +0 -0
  206. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/__init__.py +0 -0
  207. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/archive_extraction.py +0 -0
  208. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/content_extraction.py +0 -0
  209. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/dependency_groups.py +0 -0
  210. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/embedded_files.py +0 -0
  211. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/external_video.py +0 -0
  212. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/file_metadata.py +0 -0
  213. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/file_parser.py +0 -0
  214. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/file_to_images.py +0 -0
  215. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/hashing.py +0 -0
  216. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/legacy_office.py +0 -0
  217. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/payload.py +0 -0
  218. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/range_reader.py +0 -0
  219. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/resources.py +0 -0
  220. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/source_files.py +0 -0
  221. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/sql_lineage.py +0 -0
  222. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/torch_runtime.py +0 -0
  223. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/transcription.py +0 -0
  224. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/uv_sync.py +0 -0
  225. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/validation.py +0 -0
  226. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/video_processing.py +0 -0
  227. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/__init__.py +0 -0
  228. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/_lakehouse_fakes.py +0 -0
  229. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/conftest.py +0 -0
  230. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/__init__.py +0 -0
  231. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/broken_links/test_broken_links_detector.py +0 -0
  232. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/conftest.py +0 -0
  233. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/content/__init__.py +0 -0
  234. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/__init__.py +0 -0
  235. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/conftest.py +0 -0
  236. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_gliner2_classification.py +0 -0
  237. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_invoice_extraction.py +0 -0
  238. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_llm_runner.py +0 -0
  239. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_pipeline_integration.py +0 -0
  240. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_regex_runner.py +0 -0
  241. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_runner_hardening.py +0 -0
  242. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_transformer_runners.py +0 -0
  243. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/__init__.py +0 -0
  244. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/conftest.py +0 -0
  245. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/sample_invoice.pdf +0 -0
  246. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/test_pii_chunking.py +0 -0
  247. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/test_pii_detector.py +0 -0
  248. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/test_pii_detector_extended.py +0 -0
  249. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/test_pii_regional_entities.py +0 -0
  250. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/test_pii_severity.py +0 -0
  251. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/secrets/__init__.py +0 -0
  252. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/secrets/test_secrets_detector.py +0 -0
  253. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/secrets/test_secrets_detector_extended.py +0 -0
  254. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_base_detector.py +0 -0
  255. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_custom_detector_examples_runtime.py +0 -0
  256. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_detector_catalog_commercial.py +0 -0
  257. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_detector_pipeline_types.py +0 -0
  258. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_detector_schema_examples.py +0 -0
  259. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_detector_types.py +0 -0
  260. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_phase2_detectors.py +0 -0
  261. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_registry.py +0 -0
  262. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_tag_runner.py +0 -0
  263. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/threat/__init__.py +0 -0
  264. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/threat/test_code_security_detector.py +0 -0
  265. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/threat/test_yara_detector.py +0 -0
  266. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/integration/test_wordpress_broken_links_detector.py +0 -0
  267. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/integration/test_wordpress_links_assets.py +0 -0
  268. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/pipeline/test_detector_breaker.py +0 -0
  269. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/pipeline/test_detector_outcomes.py +0 -0
  270. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/pipeline/test_detector_pipeline.py +0 -0
  271. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/pipeline/test_worker_pool.py +0 -0
  272. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_arrow_ipc_payloads.py +0 -0
  273. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_assets_metadata_catalog.py +0 -0
  274. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_contract.py +0 -0
  275. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_edges.py +0 -0
  276. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_patch.py +0 -0
  277. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_scan_cache.py +0 -0
  278. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_session.py +0 -0
  279. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_tags_end_to_end.py +0 -0
  280. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_azure_blob_storage_source.py +0 -0
  281. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_base_source_attachment.py +0 -0
  282. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_base_source_sampling.py +0 -0
  283. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_byte_valued_fields.py +0 -0
  284. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_config.py +0 -0
  285. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_confluence_source.py +0 -0
  286. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_custom_extractor.py +0 -0
  287. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_custom_source.py +0 -0
  288. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_custom_source_relationships.py +0 -0
  289. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_custom_source_tags_end_to_end.py +0 -0
  290. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_databricks_source.py +0 -0
  291. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_delta_lake_source.py +0 -0
  292. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_dependency_groups.py +0 -0
  293. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_detector_scope.py +0 -0
  294. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_dropbox_auth_command.py +0 -0
  295. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_dropbox_source.py +0 -0
  296. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_elasticsearch_source.py +0 -0
  297. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_email_source.py +0 -0
  298. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_file_evaluation_runner.py +0 -0
  299. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_git_source.py +0 -0
  300. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_google_cloud_storage_source.py +0 -0
  301. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_google_workspace_source.py +0 -0
  302. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_graph_edges.py +0 -0
  303. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_hashing.py +0 -0
  304. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_hive_source.py +0 -0
  305. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_hugging_face_source.py +0 -0
  306. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_iceberg_source.py +0 -0
  307. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_jira_source.py +0 -0
  308. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_kafka_source.py +0 -0
  309. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_lineage_loss_reporting.py +0 -0
  310. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_local_folder_source.py +0 -0
  311. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_main.py +0 -0
  312. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_meilisearch_source.py +0 -0
  313. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_microsoft_365_source.py +0 -0
  314. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_mongodb_source.py +0 -0
  315. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_mssql_source.py +0 -0
  316. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_mysql_source.py +0 -0
  317. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_neo4j_source.py +0 -0
  318. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_asset_extract.py +0 -0
  319. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_asset_tags.py +0 -0
  320. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_cohort.py +0 -0
  321. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_execute.py +0 -0
  322. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_files.py +0 -0
  323. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_groups.py +0 -0
  324. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_log_levels.py +0 -0
  325. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_packages.py +0 -0
  326. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_query_assets.py +0 -0
  327. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_sdk_exports.py +0 -0
  328. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_serialize.py +0 -0
  329. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_templates.py +0 -0
  330. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notion_source.py +0 -0
  331. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_object_storage_download_efficiency.py +0 -0
  332. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_opensearch_source.py +0 -0
  333. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_oracle_source.py +0 -0
  334. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_outputs.py +0 -0
  335. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_payload_window.py +0 -0
  336. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_payload_window_parquet.py +0 -0
  337. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_postgresql_source.py +0 -0
  338. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_powerbi_source.py +0 -0
  339. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_range_reading.py +0 -0
  340. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_recipe_normalizer.py +0 -0
  341. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_reddit_source.py +0 -0
  342. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_rest_backpressure.py +0 -0
  343. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_runtime_packages.py +0 -0
  344. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_s3_compatible_storage_source.py +0 -0
  345. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_sampling_automatic.py +0 -0
  346. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_sandbox_source.py +0 -0
  347. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_sdk_completions.py +0 -0
  348. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_secret_redaction.py +0 -0
  349. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_servicedesk_source.py +0 -0
  350. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_slack_source.py +0 -0
  351. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_snowflake_source.py +0 -0
  352. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_source_dependency_groups.py +0 -0
  353. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_source_strategy_conformance.py +0 -0
  354. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_sqlite_source.py +0 -0
  355. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_tableau_source.py +0 -0
  356. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_tabular_automatic_sampling.py +0 -0
  357. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_tabular_lineage.py +0 -0
  358. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_tabular_utils.py +0 -0
  359. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_torch_runtime.py +0 -0
  360. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_urn.py +0 -0
  361. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_uv_sync.py +0 -0
  362. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_wordpress_source.py +0 -0
  363. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_youtube_source.py +0 -0
  364. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_youtube_source_integration.py +0 -0
  365. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_archive_extraction.py +0 -0
  366. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_content_extraction.py +0 -0
  367. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_embedded_files.py +0 -0
  368. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_file_metadata.py +0 -0
  369. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_file_parser.py +0 -0
  370. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_file_to_images.py +0 -0
  371. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_legacy_office.py +0 -0
  372. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_payload.py +0 -0
  373. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_transcription.py +0 -0
  374. {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_video_processing.py +0 -0
@@ -1,3 +1,3 @@
1
1
  $ uv sync
2
- Resolved 325 packages in 183ms
2
+ Resolved 325 packages in 219ms
3
3
  Checked 51 packages in 1ms
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: classifyre-cli
3
- Version: 0.6.3
3
+ Version: 0.6.5
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.6.3",
3
+ "version": "0.6.5",
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.6.3"
3
+ version = "0.6.5"
4
4
  description = "Classifyre CLI — scan and classify unstructured data sources"
5
5
  readme = "README.md"
6
6
  # Upper bound is load-bearing: onnxruntime publishes no cp315 wheels (notably
@@ -15,6 +15,7 @@ _PIPELINE_TYPE_DEFAULTS: dict[str, str] = {
15
15
  "RegexPipelineSchema": "REGEX",
16
16
  "LLMPipelineSchema": "LLM",
17
17
  "TagPipelineSchema": "TAG",
18
+ "CodeDetectorPipelineSchema": "CODE_DETECTOR",
18
19
  }
19
20
 
20
21
  # Pipeline schema classes whose `severity` field has a string default from JSON schema
@@ -27,6 +28,7 @@ _SEVERITY_ENUM_DEFAULT_CLASSES = {
27
28
  "LLMPipelineSchema": "info",
28
29
  "TextClassificationPipelineSchema": "info",
29
30
  "TagPipelineSchema": "medium",
31
+ "CodeDetectorPipelineSchema": "medium",
30
32
  }
31
33
 
32
34
 
@@ -60,6 +62,15 @@ def _patch_severity_enum_defaults(source: str) -> str:
60
62
  return source
61
63
 
62
64
 
65
+ def _patch_category_enum_defaults(source: str) -> str:
66
+ """Same fix as the severity one, for the code detector's ``category`` default."""
67
+ pattern = (
68
+ r"(class CodeDetectorPipelineSchema\(.*?category: DetectorCategory \| None = Field\(\n\s+)"
69
+ r"'QUALITY'(\s*,)"
70
+ )
71
+ return re.sub(pattern, r"\1DetectorCategory.QUALITY\2", source, flags=re.DOTALL)
72
+
73
+
63
74
  def run_codegen(input_file):
64
75
  """Generate Pydantic models from a single JSON schema file."""
65
76
  cmd = [
@@ -107,6 +118,7 @@ def main():
107
118
  content = run_codegen(detector_schema)
108
119
  content = _patch_pipeline_type_defaults(content)
109
120
  content = _patch_severity_enum_defaults(content)
121
+ content = _patch_category_enum_defaults(content)
110
122
  (MODEL_DIR / "generated_detectors.py").write_text(content)
111
123
  print("Wrote src/models/generated_detectors.py")
112
124
 
@@ -35,6 +35,7 @@ from src.notebook.contract import ( # noqa: E402
35
35
  from src.notebook.sdk import ( # noqa: E402
36
36
  Asset,
37
37
  Context,
38
+ Entity,
38
39
  FieldMapping,
39
40
  FlowType,
40
41
  NotebookFile,
@@ -259,6 +260,13 @@ def build() -> dict[str, Any]:
259
260
  "documentation": _summary(Tag),
260
261
  "insertText": "Tag",
261
262
  },
263
+ {
264
+ "label": "Entity",
265
+ "kind": "class",
266
+ "detail": 'Entity(name, type="ORGANIZATION", identifiers={...})',
267
+ "documentation": _summary(Entity),
268
+ "insertText": "Entity",
269
+ },
262
270
  {
263
271
  "label": "Ref",
264
272
  "kind": "class",
@@ -304,6 +312,10 @@ def build() -> dict[str, Any]:
304
312
  "documentation": _summary(Tag),
305
313
  "fields": _fields(Tag),
306
314
  },
315
+ "Entity": {
316
+ "documentation": _summary(Entity),
317
+ "fields": _fields(Entity),
318
+ },
307
319
  "AugmentedAsset": {
308
320
  "documentation": _summary(augmentation_sdk.AugmentedAsset),
309
321
  "members": _members(augmentation_sdk.AugmentedAsset),
@@ -44,11 +44,13 @@ from ..graph.edges import (
44
44
  FlowType,
45
45
  Ref,
46
46
  contains,
47
+ edge_to_payload,
47
48
  flow,
48
49
  references,
49
50
  same_as,
50
51
  uses,
51
52
  )
53
+ from ..graph.edges import means as means_edge
52
54
  from ..notebook.files import ParsedContent, pages, parse
53
55
  from ..notebook.sdk import (
54
56
  MODULE_NAME,
@@ -141,6 +143,7 @@ class AugmentedAsset:
141
143
  self._added_metadata: dict[str, Any] = {}
142
144
  self._tags: dict[str, str] = {}
143
145
  self._links: list[str] = []
146
+ self._means: list[dict[str, Any]] = []
144
147
  self._new_urn: str | None = None
145
148
  self.warnings: list[str] = []
146
149
 
@@ -313,6 +316,33 @@ class AugmentedAsset:
313
316
  if target not in self._links:
314
317
  self._links.append(target)
315
318
 
319
+ def means(
320
+ self,
321
+ key: str,
322
+ *,
323
+ evidence: Mapping[str, Any] | None = None,
324
+ confidence: float | None = None,
325
+ ) -> None:
326
+ """Declare that this asset is about a glossary concept or entity, by key.
327
+
328
+ Additive, like ``tag()`` and ``link()``: a DECLARED semantic link. The
329
+ term need not exist yet; the declaration links once it is defined. An
330
+ invalid key is skipped with a warning.
331
+ """
332
+ try:
333
+ edge = means_edge(
334
+ Ref.asset(self._hash),
335
+ Ref.term(str(key or "")),
336
+ evidence=dict(evidence or {}),
337
+ confidence=confidence,
338
+ )
339
+ except ValueError as exc:
340
+ self.warnings.append(f"Ignoring asset.means({key!r}): {exc}")
341
+ return
342
+ payload = edge_to_payload(edge)
343
+ if payload not in self._means:
344
+ self._means.append(payload)
345
+
316
346
  def set_urn(self, urn: str) -> None:
317
347
  """Set the asset's cross-system identity, only if the connector left it empty.
318
348
 
@@ -337,6 +367,7 @@ class AugmentedAsset:
337
367
  "metadata": dict(self._added_metadata),
338
368
  "tags": dict(self._tags),
339
369
  "links": list(self._links),
370
+ "means": list(self._means),
340
371
  "urn": self._new_urn,
341
372
  "warnings": list(self.warnings),
342
373
  }
@@ -418,6 +449,7 @@ def build_augmentation_module(context: AugmentContext) -> types.ModuleType:
418
449
  module.flow = flow # type: ignore[attr-defined]
419
450
  module.contains = contains # type: ignore[attr-defined]
420
451
  module.references = references # type: ignore[attr-defined]
452
+ module.means = means_edge # type: ignore[attr-defined]
421
453
  module.same_as = same_as # type: ignore[attr-defined]
422
454
  module.uses = uses # type: ignore[attr-defined]
423
455
  module.urn_for = urn_for # type: ignore[attr-defined]
@@ -439,6 +471,7 @@ def build_augmentation_module(context: AugmentContext) -> types.ModuleType:
439
471
  "contains",
440
472
  "ctx",
441
473
  "flow",
474
+ "means",
442
475
  "pages",
443
476
  "parse",
444
477
  "references",
@@ -470,6 +503,7 @@ def augmentation_namespace(context: AugmentContext) -> dict[str, Any]:
470
503
  "flow": flow,
471
504
  "contains": contains,
472
505
  "references": references,
506
+ "means": means_edge,
473
507
  "same_as": same_as,
474
508
  "uses": uses,
475
509
  "urn_for": urn_for,
@@ -18,7 +18,6 @@ silently-degraded run visible.
18
18
  from __future__ import annotations
19
19
 
20
20
  import asyncio
21
- import base64
22
21
  import json
23
22
  import logging
24
23
  from collections.abc import Mapping
@@ -29,6 +28,7 @@ from ..graph.edges import edge_from_payload
29
28
  from ..notebook.child import ChildProcessError, NotebookChildProcess
30
29
  from ..notebook.groups import warm_declared_groups
31
30
  from ..notebook.packages import install as install_packages
31
+ from ..pipeline.asset_payload_server import AssetPayloadServer
32
32
  from ..utils.hashing import unhash_id
33
33
  from ..utils.urn import normalize_urn_or_none
34
34
  from .contract import validate_augmentation_notebook
@@ -143,10 +143,6 @@ class AugmentationSession:
143
143
  self._warnings: list[str] = []
144
144
  self._warning_set: set[str] = set()
145
145
  self.stats = AugmentationStats()
146
- # Run-scoped memo of fetched payloads, keyed by fetch candidate id.
147
- # Bounded: one in-flight asset's worth per entry, each capped at
148
- # max_payload_bytes, dropped by evict_asset_cache().
149
- self._memo: dict[str, dict[str, Any]] = {}
150
146
 
151
147
  # -- construction ----------------------------------------------------------
152
148
 
@@ -295,7 +291,6 @@ class AugmentationSession:
295
291
  slot.child.terminate()
296
292
  except Exception:
297
293
  pass
298
- self._memo.clear()
299
294
 
300
295
  # -- per asset -----------------------------------------------------------------
301
296
 
@@ -314,163 +309,34 @@ class AugmentationSession:
314
309
  "mime_type": None,
315
310
  }
316
311
 
317
- def _candidates(self, asset: Any) -> list[str]:
318
- seen: list[str] = []
319
- for candidate in (getattr(asset, "external_url", ""), getattr(asset, "hash", "")):
320
- value = str(candidate or "").strip()
321
- if value and value not in seen:
322
- seen.append(value)
323
- return seen
312
+ @property
313
+ def _payloads(self) -> AssetPayloadServer:
314
+ """The source's shared payload server.
315
+
316
+ Shared with the code detectors that run on the same asset later in the
317
+ scan, so a payload augmentation fetched is not fetched again (G1 R20).
318
+ """
319
+ return AssetPayloadServer.shared(
320
+ self._source, max_payload_bytes=self._limits["max_payload_bytes"]
321
+ )
324
322
 
325
323
  async def _serve_need(self, asset: Any, memo_key: str, frame: dict[str, Any]) -> Any:
326
- op = str(frame.get("op") or "")
327
- if op == "payload":
328
- fetched = await self._fetch_payload(asset)
329
- if fetched is None:
330
- return {"bytes_b64": None, "mime": None}
331
- raw, mime = fetched
332
- return {"bytes_b64": base64.b64encode(raw).decode("ascii"), "mime": mime}
333
- if op == "raw_pages":
334
- pages = await self._fetch_raw_pages(asset)
335
- return {"pages": pages}
336
- if op == "text":
337
- pages = await self._fetch_text_pages(asset)
338
- whole = "".join(pages)
339
- return {"text": whole, "pages": pages}
340
- raise ChildProcessError(f"Unknown payload op {op!r}")
324
+ try:
325
+ return await self._payloads.serve(asset, frame)
326
+ except ValueError as exc:
327
+ raise ChildProcessError(str(exc)) from exc
341
328
 
342
329
  async def _fetch_payload(self, asset: Any) -> tuple[bytes, str] | None:
343
330
  """Raw bytes for file-shaped sources; None for row-shaped ones."""
344
- memo = self._memo_for(asset)
345
- if "payload" in memo:
346
- cached = memo["payload"]
347
- return cached if cached is None else (bytes(cached[0]), str(cached[1]))
348
- fetch = getattr(self._source, "fetch_content_bytes", None)
349
- result: tuple[bytes, str] | None = None
350
- if callable(fetch):
351
- for candidate in self._candidates(asset):
352
- try:
353
- result = await fetch(candidate)
354
- except Exception as exc:
355
- logger.debug("Augmentation payload fetch failed for %s: %s", candidate, exc)
356
- continue
357
- if result is not None:
358
- break
359
- if result is not None:
360
- raw, mime = result
361
- cap = self._limits["max_payload_bytes"]
362
- if len(raw) > cap:
363
- logger.debug("Augmentation payload for %s truncated to %d bytes", candidate, cap)
364
- raw = raw[:cap]
365
- result = (raw, mime)
366
- self._remember_bytes(asset, raw, mime)
367
- memo["payload"] = result
368
- return result
331
+ return await self._payloads.payload(asset)
369
332
 
370
333
  async def _fetch_raw_pages(self, asset: Any) -> list[str]:
371
334
  """The connector's own raw representation, page by page (capped)."""
372
- memo = self._memo_for(asset)
373
- if "raw_pages" in memo:
374
- return [str(page) for page in memo["raw_pages"]]
375
- pages: list[str] = []
376
- fetch = getattr(self._source, "fetch_content_pages", None)
377
- cap = self._limits["max_payload_bytes"]
378
- used = 0
379
- if callable(fetch):
380
- for candidate in self._candidates(asset):
381
- try:
382
- async for raw, _text in fetch(candidate):
383
- if not raw:
384
- continue
385
- chunk = str(raw)
386
- if used + len(chunk) > cap:
387
- chunk = chunk[: max(0, cap - used)]
388
- if chunk:
389
- pages.append(chunk)
390
- used += len(chunk)
391
- if used >= cap or len(pages) >= 50:
392
- break
393
- if pages:
394
- break
395
- except Exception as exc:
396
- logger.debug("Augmentation raw fetch failed for %s: %s", candidate, exc)
397
- continue
398
- memo["raw_pages"] = pages
399
- return pages
335
+ return await self._payloads.raw_pages(asset)
400
336
 
401
337
  async def _fetch_text_pages(self, asset: Any) -> list[str]:
402
338
  """Extracted text, page by page (capped)."""
403
- memo = self._memo_for(asset)
404
- if "text_pages" in memo:
405
- return [str(page) for page in memo["text_pages"]]
406
- pages: list[str] = []
407
- fetch = getattr(self._source, "fetch_content_pages", None)
408
- cap = self._limits["max_payload_bytes"]
409
- used = 0
410
- if callable(fetch):
411
- for candidate in self._candidates(asset):
412
- try:
413
- async for _raw, text in fetch(candidate):
414
- if not text:
415
- continue
416
- chunk = str(text)
417
- if used + len(chunk) > cap:
418
- chunk = chunk[: max(0, cap - used)]
419
- if chunk:
420
- pages.append(chunk)
421
- used += len(chunk)
422
- if used >= cap or len(pages) >= 50:
423
- break
424
- if pages:
425
- break
426
- except Exception as exc:
427
- logger.debug("Augmentation text fetch failed for %s: %s", candidate, exc)
428
- continue
429
- if not pages:
430
- provider = getattr(self._source, "fetch_content_bytes", None)
431
- if callable(provider):
432
- fetched = await self._fetch_payload(asset)
433
- if fetched is not None:
434
- raw, mime = fetched
435
- try:
436
- text_pages = await asyncio.to_thread(
437
- list, self._source.iter_asset_pages(raw, mime)
438
- )
439
- for page in text_pages[:50]:
440
- chunk = str(page)
441
- if used + len(chunk) > cap:
442
- chunk = chunk[: max(0, cap - used)]
443
- if chunk:
444
- pages.append(chunk)
445
- used += len(chunk)
446
- if used >= cap:
447
- break
448
- except Exception as exc:
449
- logger.debug("Augmentation text fallback failed: %s", exc)
450
- memo["text_pages"] = pages
451
- return pages
452
-
453
- def _memo_for(self, asset: Any) -> dict[str, Any]:
454
- key = str(getattr(asset, "hash", "") or "")
455
- return self._memo.setdefault(key, {})
456
-
457
- def _remember_bytes(self, asset: Any, raw: bytes, mime: str) -> None:
458
- """Mirror fetched bytes onto the source so the pipeline reuses them.
459
-
460
- ``ParsedContentProvider.fetch_bytes`` consults this memo first instead
461
- of re-downloading — the fetch augmentation already paid for is not
462
- paid twice. Registered under every candidate id the pipeline tries
463
- (external URL, then hash), and dropped by ``evict`` at the end of the
464
- asset.
465
- """
466
- remember = getattr(self._source, "remember_augmentation_bytes", None)
467
- if not callable(remember):
468
- return
469
- for candidate in self._candidates(asset):
470
- try:
471
- remember(candidate, raw, mime)
472
- except Exception:
473
- pass
339
+ return await self._payloads.text_pages(asset)
474
340
 
475
341
  async def augment(self, asset: Any) -> Any:
476
342
  """Enrich one asset. Never raises: failure degrades to a warning."""
@@ -597,6 +463,11 @@ class AugmentationSession:
597
463
 
598
464
  self._ingest_edges(patch, asset_hash=asset_hash or None)
599
465
 
466
+ # asset.means(): declarations, already built as MEANS edges by the SDK.
467
+ declared = patch.get("means")
468
+ if isinstance(declared, list) and declared:
469
+ self._ingest_edges({"edges": declared}, asset_hash=asset_hash or None)
470
+
600
471
  for message in patch.get("warnings") or []:
601
472
  self._warn(f"Augmentation on {getattr(asset, 'name', asset_hash)}: {message}")
602
473
 
@@ -718,13 +589,4 @@ class AugmentationSession:
718
589
 
719
590
  def evict(self, asset: Any) -> None:
720
591
  """Drop one asset's payload memo. Called alongside evict_asset_cache."""
721
- self._memo.pop(str(getattr(asset, "hash", "") or ""), None)
722
- forget = getattr(self._source, "forget_augmentation_bytes", None)
723
- if not callable(forget):
724
- return
725
- # The bytes were mirrored under every candidate id; drop them all.
726
- for candidate in self._candidates(asset):
727
- try:
728
- forget(candidate)
729
- except Exception:
730
- pass
592
+ self._payloads.evict(asset)
@@ -13,6 +13,7 @@ from ._base import (
13
13
  BaseRunner,
14
14
  _resolve_pipeline_severity,
15
15
  )
16
+ from ._custom_detector import CustomDetectorRunner
16
17
  from ._factory import create_runner
17
18
  from ._gliner2 import (
18
19
  GLiNER2Runner,
@@ -35,6 +36,7 @@ __all__ = [
35
36
  "_IMAGE_CONTENT_TYPES",
36
37
  "_TEXT_CONTENT_TYPES",
37
38
  "BaseRunner",
39
+ "CustomDetectorRunner",
38
40
  "GLiNER2Runner",
39
41
  "ImageClassificationRunner",
40
42
  "LLMRunner",
@@ -0,0 +1,72 @@
1
+ """Runner for the ``CODE_DETECTOR`` pipeline type: a code detector.
2
+
3
+ Like ``TAG`` it never runs over a page of text: ``detect()`` returns nothing and
4
+ no content type is advertised, so the text, binary and link passes never
5
+ schedule it and the worker pool never receives it. The detector pipeline
6
+ recognises it by this class and calls it once per asset, after every other
7
+ detector, through the :class:`CustomDetectorSession` it owns.
8
+
9
+ The session is created lazily on first use and bound to the scan's source,
10
+ because it needs the source to serve payload and holds child processes that
11
+ must not exist in the worker pool's processes.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from typing import Any
17
+
18
+ from ....models.generated_detectors import CodeDetectorPipelineSchema, PipelineResult
19
+ from ....models.generated_single_asset_scan_results import DetectionResult
20
+ from ._base import BaseRunner
21
+
22
+
23
+ class CustomDetectorRunner(BaseRunner):
24
+ """Asset-scoped runner: judged per asset by a notebook, never per page."""
25
+
26
+ asset_scoped = True
27
+
28
+ def __init__(
29
+ self,
30
+ schema: CodeDetectorPipelineSchema,
31
+ detector_key: str = "",
32
+ detector_name: str = "",
33
+ ) -> None:
34
+ self.schema = schema
35
+ self._detector_key = detector_key
36
+ self._detector_name = detector_name
37
+ self._session: Any = None
38
+
39
+ def run(self, text: str) -> PipelineResult:
40
+ return PipelineResult(metadata={"runner": "CODE_DETECTOR"})
41
+
42
+ def detect(self, content: str | bytes, content_type: str) -> list[DetectionResult]:
43
+ """Never called per page. The pipeline calls ``session().detect(asset)``."""
44
+ return []
45
+
46
+ def get_supported_content_types(self) -> list[str]:
47
+ return []
48
+
49
+ @property
50
+ def deterministic(self) -> bool:
51
+ return self.schema.deterministic is not False
52
+
53
+ @property
54
+ def needs_findings(self) -> bool:
55
+ return bool(self.schema.needs_findings)
56
+
57
+ def session(self, source: Any) -> Any:
58
+ """The run's session, created on first use."""
59
+ if self._session is None:
60
+ from ...custom_detector.session import CustomDetectorSession
61
+
62
+ self._session = CustomDetectorSession(
63
+ key=self._detector_key,
64
+ name=self._detector_name,
65
+ schema=self.schema,
66
+ source=source,
67
+ )
68
+ return self._session
69
+
70
+ def close(self) -> None:
71
+ if self._session is not None:
72
+ self._session.close()
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from ....models.generated_detectors import (
6
+ CodeDetectorPipelineSchema,
6
7
  GLiNER2PipelineSchema,
7
8
  ImageClassificationPipelineSchema,
8
9
  LLMPipelineSchema,
@@ -12,6 +13,7 @@ from ....models.generated_detectors import (
12
13
  TextClassificationPipelineSchema,
13
14
  )
14
15
  from ._base import BaseRunner
16
+ from ._custom_detector import CustomDetectorRunner
15
17
  from ._gliner2 import GLiNER2Runner
16
18
  from ._image_classification import ImageClassificationRunner
17
19
  from ._llm import LLMRunner
@@ -30,6 +32,7 @@ def create_runner(
30
32
  | ImageClassificationPipelineSchema
31
33
  | ObjectDetectionPipelineSchema
32
34
  | TagPipelineSchema
35
+ | CodeDetectorPipelineSchema
33
36
  ),
34
37
  detector_key: str = "",
35
38
  detector_name: str = "",
@@ -50,5 +53,8 @@ def create_runner(
50
53
  # detector that is not supposed to run anything at all.
51
54
  if isinstance(schema, TagPipelineSchema):
52
55
  return TagRunner(schema, detector_key, detector_name)
56
+ # Same reason as TAG: a code detector must never fall through to GLiNER2.
57
+ if isinstance(schema, CodeDetectorPipelineSchema):
58
+ return CustomDetectorRunner(schema, detector_key, detector_name)
53
59
  # GLiNER2PipelineSchema is the default / backward-compat path
54
60
  return GLiNER2Runner(schema, detector_key, detector_name)
@@ -0,0 +1,9 @@
1
+ """Code detectors: the ``CODE_DETECTOR`` pipeline type.
2
+
3
+ A notebook that defines ``detect(asset, ctx)`` and yields ``Finding`` objects,
4
+ run in an isolated child process once per asset, after every other detector.
5
+ """
6
+
7
+ from .session import CustomDetectorSession, DetectOutcome
8
+
9
+ __all__ = ["CustomDetectorSession", "DetectOutcome"]
@@ -0,0 +1,45 @@
1
+ """The interface a code detector's notebook must cover.
2
+
3
+ A code detector answers one question -- "what is wrong with this asset?" -- so
4
+ ``detect(asset, ctx)`` is required and ``setup(ctx)`` optional. Checked at the
5
+ three moments the connector contract is: on save (the API's cheap check),
6
+ before a preview, and before every scan, because the recipe travels to a job
7
+ that has to defend itself.
8
+
9
+ Only the shape is checked, through the shared ``validate_module`` /
10
+ ``validate_notebook``. Isolation is the child process and its scrubbed
11
+ environment, not anything an AST can decide.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from collections.abc import Iterable, Mapping
17
+
18
+ from ...notebook.contract import ContractReport, validate_module, validate_notebook
19
+ from ...notebook.serialize import ModuleSource
20
+
21
+ REQUIRED_FUNCTIONS = ("detect",)
22
+
23
+ #: ``setup(ctx)`` runs once per worker before the first asset: load a list,
24
+ #: a model, a lookup table into ``ctx.state``.
25
+ OPTIONAL_FUNCTIONS = ("setup",)
26
+
27
+
28
+ def validate_detector_module(module: ModuleSource) -> ContractReport:
29
+ """Parse the assembled module and check ``detect()`` exists."""
30
+ return validate_module(module, required=REQUIRED_FUNCTIONS)
31
+
32
+
33
+ def validate_detector_notebook(
34
+ cells: Iterable[Mapping[str, object] | object],
35
+ ) -> ContractReport:
36
+ """Validate a code detector's cells."""
37
+ return validate_notebook(cells, required=REQUIRED_FUNCTIONS)
38
+
39
+
40
+ __all__ = [
41
+ "OPTIONAL_FUNCTIONS",
42
+ "REQUIRED_FUNCTIONS",
43
+ "validate_detector_module",
44
+ "validate_detector_notebook",
45
+ ]