truthound 1.0.8__py3-none-any.whl

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 (877) hide show
  1. truthound/__init__.py +162 -0
  2. truthound/adapters.py +100 -0
  3. truthound/api.py +365 -0
  4. truthound/audit/__init__.py +248 -0
  5. truthound/audit/core.py +967 -0
  6. truthound/audit/filters.py +620 -0
  7. truthound/audit/formatters.py +707 -0
  8. truthound/audit/logger.py +902 -0
  9. truthound/audit/middleware.py +571 -0
  10. truthound/audit/storage.py +1083 -0
  11. truthound/benchmark/__init__.py +123 -0
  12. truthound/benchmark/base.py +757 -0
  13. truthound/benchmark/comparison.py +635 -0
  14. truthound/benchmark/generators.py +706 -0
  15. truthound/benchmark/reporters.py +718 -0
  16. truthound/benchmark/runner.py +635 -0
  17. truthound/benchmark/scenarios.py +712 -0
  18. truthound/cache.py +252 -0
  19. truthound/checkpoint/__init__.py +136 -0
  20. truthound/checkpoint/actions/__init__.py +164 -0
  21. truthound/checkpoint/actions/base.py +324 -0
  22. truthound/checkpoint/actions/custom.py +234 -0
  23. truthound/checkpoint/actions/discord_notify.py +290 -0
  24. truthound/checkpoint/actions/email_notify.py +405 -0
  25. truthound/checkpoint/actions/github_action.py +406 -0
  26. truthound/checkpoint/actions/opsgenie.py +1499 -0
  27. truthound/checkpoint/actions/pagerduty.py +226 -0
  28. truthound/checkpoint/actions/slack_notify.py +233 -0
  29. truthound/checkpoint/actions/store_result.py +249 -0
  30. truthound/checkpoint/actions/teams_notify.py +1570 -0
  31. truthound/checkpoint/actions/telegram_notify.py +419 -0
  32. truthound/checkpoint/actions/update_docs.py +552 -0
  33. truthound/checkpoint/actions/webhook.py +293 -0
  34. truthound/checkpoint/analytics/__init__.py +147 -0
  35. truthound/checkpoint/analytics/aggregations/__init__.py +23 -0
  36. truthound/checkpoint/analytics/aggregations/rollup.py +481 -0
  37. truthound/checkpoint/analytics/aggregations/time_bucket.py +306 -0
  38. truthound/checkpoint/analytics/analyzers/__init__.py +17 -0
  39. truthound/checkpoint/analytics/analyzers/anomaly.py +386 -0
  40. truthound/checkpoint/analytics/analyzers/base.py +270 -0
  41. truthound/checkpoint/analytics/analyzers/forecast.py +421 -0
  42. truthound/checkpoint/analytics/analyzers/trend.py +314 -0
  43. truthound/checkpoint/analytics/models.py +292 -0
  44. truthound/checkpoint/analytics/protocols.py +549 -0
  45. truthound/checkpoint/analytics/service.py +718 -0
  46. truthound/checkpoint/analytics/stores/__init__.py +16 -0
  47. truthound/checkpoint/analytics/stores/base.py +306 -0
  48. truthound/checkpoint/analytics/stores/memory_store.py +353 -0
  49. truthound/checkpoint/analytics/stores/sqlite_store.py +557 -0
  50. truthound/checkpoint/analytics/stores/timescale_store.py +501 -0
  51. truthound/checkpoint/async_actions.py +794 -0
  52. truthound/checkpoint/async_base.py +708 -0
  53. truthound/checkpoint/async_checkpoint.py +617 -0
  54. truthound/checkpoint/async_runner.py +639 -0
  55. truthound/checkpoint/checkpoint.py +527 -0
  56. truthound/checkpoint/ci/__init__.py +61 -0
  57. truthound/checkpoint/ci/detector.py +355 -0
  58. truthound/checkpoint/ci/reporter.py +436 -0
  59. truthound/checkpoint/ci/templates.py +454 -0
  60. truthound/checkpoint/circuitbreaker/__init__.py +133 -0
  61. truthound/checkpoint/circuitbreaker/breaker.py +542 -0
  62. truthound/checkpoint/circuitbreaker/core.py +252 -0
  63. truthound/checkpoint/circuitbreaker/detection.py +459 -0
  64. truthound/checkpoint/circuitbreaker/middleware.py +389 -0
  65. truthound/checkpoint/circuitbreaker/registry.py +357 -0
  66. truthound/checkpoint/distributed/__init__.py +139 -0
  67. truthound/checkpoint/distributed/backends/__init__.py +35 -0
  68. truthound/checkpoint/distributed/backends/celery_backend.py +503 -0
  69. truthound/checkpoint/distributed/backends/kubernetes_backend.py +696 -0
  70. truthound/checkpoint/distributed/backends/local_backend.py +397 -0
  71. truthound/checkpoint/distributed/backends/ray_backend.py +625 -0
  72. truthound/checkpoint/distributed/base.py +774 -0
  73. truthound/checkpoint/distributed/orchestrator.py +765 -0
  74. truthound/checkpoint/distributed/protocols.py +842 -0
  75. truthound/checkpoint/distributed/registry.py +449 -0
  76. truthound/checkpoint/idempotency/__init__.py +120 -0
  77. truthound/checkpoint/idempotency/core.py +295 -0
  78. truthound/checkpoint/idempotency/fingerprint.py +454 -0
  79. truthound/checkpoint/idempotency/locking.py +604 -0
  80. truthound/checkpoint/idempotency/service.py +592 -0
  81. truthound/checkpoint/idempotency/stores.py +653 -0
  82. truthound/checkpoint/monitoring/__init__.py +134 -0
  83. truthound/checkpoint/monitoring/aggregators/__init__.py +15 -0
  84. truthound/checkpoint/monitoring/aggregators/base.py +372 -0
  85. truthound/checkpoint/monitoring/aggregators/realtime.py +300 -0
  86. truthound/checkpoint/monitoring/aggregators/window.py +493 -0
  87. truthound/checkpoint/monitoring/collectors/__init__.py +17 -0
  88. truthound/checkpoint/monitoring/collectors/base.py +257 -0
  89. truthound/checkpoint/monitoring/collectors/memory_collector.py +617 -0
  90. truthound/checkpoint/monitoring/collectors/prometheus_collector.py +451 -0
  91. truthound/checkpoint/monitoring/collectors/redis_collector.py +518 -0
  92. truthound/checkpoint/monitoring/events.py +410 -0
  93. truthound/checkpoint/monitoring/protocols.py +636 -0
  94. truthound/checkpoint/monitoring/service.py +578 -0
  95. truthound/checkpoint/monitoring/views/__init__.py +17 -0
  96. truthound/checkpoint/monitoring/views/base.py +172 -0
  97. truthound/checkpoint/monitoring/views/queue_view.py +220 -0
  98. truthound/checkpoint/monitoring/views/task_view.py +240 -0
  99. truthound/checkpoint/monitoring/views/worker_view.py +263 -0
  100. truthound/checkpoint/registry.py +337 -0
  101. truthound/checkpoint/runner.py +356 -0
  102. truthound/checkpoint/transaction/__init__.py +133 -0
  103. truthound/checkpoint/transaction/base.py +389 -0
  104. truthound/checkpoint/transaction/compensatable.py +537 -0
  105. truthound/checkpoint/transaction/coordinator.py +576 -0
  106. truthound/checkpoint/transaction/executor.py +622 -0
  107. truthound/checkpoint/transaction/idempotency.py +534 -0
  108. truthound/checkpoint/transaction/saga/__init__.py +143 -0
  109. truthound/checkpoint/transaction/saga/builder.py +584 -0
  110. truthound/checkpoint/transaction/saga/definition.py +515 -0
  111. truthound/checkpoint/transaction/saga/event_store.py +542 -0
  112. truthound/checkpoint/transaction/saga/patterns.py +833 -0
  113. truthound/checkpoint/transaction/saga/runner.py +718 -0
  114. truthound/checkpoint/transaction/saga/state_machine.py +793 -0
  115. truthound/checkpoint/transaction/saga/strategies.py +780 -0
  116. truthound/checkpoint/transaction/saga/testing.py +886 -0
  117. truthound/checkpoint/triggers/__init__.py +58 -0
  118. truthound/checkpoint/triggers/base.py +237 -0
  119. truthound/checkpoint/triggers/event.py +385 -0
  120. truthound/checkpoint/triggers/schedule.py +355 -0
  121. truthound/cli.py +2358 -0
  122. truthound/cli_modules/__init__.py +124 -0
  123. truthound/cli_modules/advanced/__init__.py +45 -0
  124. truthound/cli_modules/advanced/benchmark.py +343 -0
  125. truthound/cli_modules/advanced/docs.py +225 -0
  126. truthound/cli_modules/advanced/lineage.py +209 -0
  127. truthound/cli_modules/advanced/ml.py +320 -0
  128. truthound/cli_modules/advanced/realtime.py +196 -0
  129. truthound/cli_modules/checkpoint/__init__.py +46 -0
  130. truthound/cli_modules/checkpoint/init.py +114 -0
  131. truthound/cli_modules/checkpoint/list.py +71 -0
  132. truthound/cli_modules/checkpoint/run.py +159 -0
  133. truthound/cli_modules/checkpoint/validate.py +67 -0
  134. truthound/cli_modules/common/__init__.py +71 -0
  135. truthound/cli_modules/common/errors.py +414 -0
  136. truthound/cli_modules/common/options.py +419 -0
  137. truthound/cli_modules/common/output.py +507 -0
  138. truthound/cli_modules/common/protocol.py +552 -0
  139. truthound/cli_modules/core/__init__.py +48 -0
  140. truthound/cli_modules/core/check.py +123 -0
  141. truthound/cli_modules/core/compare.py +104 -0
  142. truthound/cli_modules/core/learn.py +57 -0
  143. truthound/cli_modules/core/mask.py +77 -0
  144. truthound/cli_modules/core/profile.py +65 -0
  145. truthound/cli_modules/core/scan.py +61 -0
  146. truthound/cli_modules/profiler/__init__.py +51 -0
  147. truthound/cli_modules/profiler/auto_profile.py +175 -0
  148. truthound/cli_modules/profiler/metadata.py +107 -0
  149. truthound/cli_modules/profiler/suite.py +283 -0
  150. truthound/cli_modules/registry.py +431 -0
  151. truthound/cli_modules/scaffolding/__init__.py +89 -0
  152. truthound/cli_modules/scaffolding/base.py +631 -0
  153. truthound/cli_modules/scaffolding/commands.py +545 -0
  154. truthound/cli_modules/scaffolding/plugins.py +1072 -0
  155. truthound/cli_modules/scaffolding/reporters.py +594 -0
  156. truthound/cli_modules/scaffolding/validators.py +1127 -0
  157. truthound/common/__init__.py +18 -0
  158. truthound/common/resilience/__init__.py +130 -0
  159. truthound/common/resilience/bulkhead.py +266 -0
  160. truthound/common/resilience/circuit_breaker.py +516 -0
  161. truthound/common/resilience/composite.py +332 -0
  162. truthound/common/resilience/config.py +292 -0
  163. truthound/common/resilience/protocols.py +217 -0
  164. truthound/common/resilience/rate_limiter.py +404 -0
  165. truthound/common/resilience/retry.py +341 -0
  166. truthound/datadocs/__init__.py +260 -0
  167. truthound/datadocs/base.py +571 -0
  168. truthound/datadocs/builder.py +761 -0
  169. truthound/datadocs/charts.py +764 -0
  170. truthound/datadocs/dashboard/__init__.py +63 -0
  171. truthound/datadocs/dashboard/app.py +576 -0
  172. truthound/datadocs/dashboard/components.py +584 -0
  173. truthound/datadocs/dashboard/state.py +240 -0
  174. truthound/datadocs/engine/__init__.py +46 -0
  175. truthound/datadocs/engine/context.py +376 -0
  176. truthound/datadocs/engine/pipeline.py +618 -0
  177. truthound/datadocs/engine/registry.py +469 -0
  178. truthound/datadocs/exporters/__init__.py +49 -0
  179. truthound/datadocs/exporters/base.py +198 -0
  180. truthound/datadocs/exporters/html.py +178 -0
  181. truthound/datadocs/exporters/json_exporter.py +253 -0
  182. truthound/datadocs/exporters/markdown.py +284 -0
  183. truthound/datadocs/exporters/pdf.py +392 -0
  184. truthound/datadocs/i18n/__init__.py +86 -0
  185. truthound/datadocs/i18n/catalog.py +960 -0
  186. truthound/datadocs/i18n/formatting.py +505 -0
  187. truthound/datadocs/i18n/loader.py +256 -0
  188. truthound/datadocs/i18n/plurals.py +378 -0
  189. truthound/datadocs/renderers/__init__.py +42 -0
  190. truthound/datadocs/renderers/base.py +401 -0
  191. truthound/datadocs/renderers/custom.py +342 -0
  192. truthound/datadocs/renderers/jinja.py +697 -0
  193. truthound/datadocs/sections.py +736 -0
  194. truthound/datadocs/styles.py +931 -0
  195. truthound/datadocs/themes/__init__.py +101 -0
  196. truthound/datadocs/themes/base.py +336 -0
  197. truthound/datadocs/themes/default.py +417 -0
  198. truthound/datadocs/themes/enterprise.py +419 -0
  199. truthound/datadocs/themes/loader.py +336 -0
  200. truthound/datadocs/themes.py +301 -0
  201. truthound/datadocs/transformers/__init__.py +57 -0
  202. truthound/datadocs/transformers/base.py +268 -0
  203. truthound/datadocs/transformers/enrichers.py +544 -0
  204. truthound/datadocs/transformers/filters.py +447 -0
  205. truthound/datadocs/transformers/i18n.py +468 -0
  206. truthound/datadocs/versioning/__init__.py +62 -0
  207. truthound/datadocs/versioning/diff.py +639 -0
  208. truthound/datadocs/versioning/storage.py +497 -0
  209. truthound/datadocs/versioning/version.py +358 -0
  210. truthound/datasources/__init__.py +223 -0
  211. truthound/datasources/_async_protocols.py +222 -0
  212. truthound/datasources/_protocols.py +159 -0
  213. truthound/datasources/adapters.py +428 -0
  214. truthound/datasources/async_base.py +599 -0
  215. truthound/datasources/async_factory.py +511 -0
  216. truthound/datasources/base.py +516 -0
  217. truthound/datasources/factory.py +433 -0
  218. truthound/datasources/nosql/__init__.py +47 -0
  219. truthound/datasources/nosql/base.py +487 -0
  220. truthound/datasources/nosql/elasticsearch.py +801 -0
  221. truthound/datasources/nosql/mongodb.py +636 -0
  222. truthound/datasources/pandas_optimized.py +582 -0
  223. truthound/datasources/pandas_source.py +216 -0
  224. truthound/datasources/polars_source.py +395 -0
  225. truthound/datasources/spark_source.py +479 -0
  226. truthound/datasources/sql/__init__.py +154 -0
  227. truthound/datasources/sql/base.py +710 -0
  228. truthound/datasources/sql/bigquery.py +410 -0
  229. truthound/datasources/sql/cloud_base.py +199 -0
  230. truthound/datasources/sql/databricks.py +471 -0
  231. truthound/datasources/sql/mysql.py +316 -0
  232. truthound/datasources/sql/oracle.py +427 -0
  233. truthound/datasources/sql/postgresql.py +321 -0
  234. truthound/datasources/sql/redshift.py +479 -0
  235. truthound/datasources/sql/snowflake.py +439 -0
  236. truthound/datasources/sql/sqlite.py +286 -0
  237. truthound/datasources/sql/sqlserver.py +437 -0
  238. truthound/datasources/streaming/__init__.py +47 -0
  239. truthound/datasources/streaming/base.py +350 -0
  240. truthound/datasources/streaming/kafka.py +670 -0
  241. truthound/decorators.py +98 -0
  242. truthound/docs/__init__.py +69 -0
  243. truthound/docs/extractor.py +971 -0
  244. truthound/docs/generator.py +601 -0
  245. truthound/docs/parser.py +1037 -0
  246. truthound/docs/renderer.py +999 -0
  247. truthound/drift/__init__.py +22 -0
  248. truthound/drift/compare.py +189 -0
  249. truthound/drift/detectors.py +464 -0
  250. truthound/drift/report.py +160 -0
  251. truthound/execution/__init__.py +65 -0
  252. truthound/execution/_protocols.py +324 -0
  253. truthound/execution/base.py +576 -0
  254. truthound/execution/distributed/__init__.py +179 -0
  255. truthound/execution/distributed/aggregations.py +731 -0
  256. truthound/execution/distributed/arrow_bridge.py +817 -0
  257. truthound/execution/distributed/base.py +550 -0
  258. truthound/execution/distributed/dask_engine.py +976 -0
  259. truthound/execution/distributed/mixins.py +766 -0
  260. truthound/execution/distributed/protocols.py +756 -0
  261. truthound/execution/distributed/ray_engine.py +1127 -0
  262. truthound/execution/distributed/registry.py +446 -0
  263. truthound/execution/distributed/spark_engine.py +1011 -0
  264. truthound/execution/distributed/validator_adapter.py +682 -0
  265. truthound/execution/pandas_engine.py +401 -0
  266. truthound/execution/polars_engine.py +497 -0
  267. truthound/execution/pushdown/__init__.py +230 -0
  268. truthound/execution/pushdown/ast.py +1550 -0
  269. truthound/execution/pushdown/builder.py +1550 -0
  270. truthound/execution/pushdown/dialects.py +1072 -0
  271. truthound/execution/pushdown/executor.py +829 -0
  272. truthound/execution/pushdown/optimizer.py +1041 -0
  273. truthound/execution/sql_engine.py +518 -0
  274. truthound/infrastructure/__init__.py +189 -0
  275. truthound/infrastructure/audit.py +1515 -0
  276. truthound/infrastructure/config.py +1133 -0
  277. truthound/infrastructure/encryption.py +1132 -0
  278. truthound/infrastructure/logging.py +1503 -0
  279. truthound/infrastructure/metrics.py +1220 -0
  280. truthound/lineage/__init__.py +89 -0
  281. truthound/lineage/base.py +746 -0
  282. truthound/lineage/impact_analysis.py +474 -0
  283. truthound/lineage/integrations/__init__.py +22 -0
  284. truthound/lineage/integrations/openlineage.py +548 -0
  285. truthound/lineage/tracker.py +512 -0
  286. truthound/lineage/visualization/__init__.py +33 -0
  287. truthound/lineage/visualization/protocols.py +145 -0
  288. truthound/lineage/visualization/renderers/__init__.py +20 -0
  289. truthound/lineage/visualization/renderers/cytoscape.py +329 -0
  290. truthound/lineage/visualization/renderers/d3.py +331 -0
  291. truthound/lineage/visualization/renderers/graphviz.py +276 -0
  292. truthound/lineage/visualization/renderers/mermaid.py +308 -0
  293. truthound/maskers.py +113 -0
  294. truthound/ml/__init__.py +124 -0
  295. truthound/ml/anomaly_models/__init__.py +31 -0
  296. truthound/ml/anomaly_models/ensemble.py +362 -0
  297. truthound/ml/anomaly_models/isolation_forest.py +444 -0
  298. truthound/ml/anomaly_models/statistical.py +392 -0
  299. truthound/ml/base.py +1178 -0
  300. truthound/ml/drift_detection/__init__.py +26 -0
  301. truthound/ml/drift_detection/concept.py +381 -0
  302. truthound/ml/drift_detection/distribution.py +361 -0
  303. truthound/ml/drift_detection/feature.py +442 -0
  304. truthound/ml/drift_detection/multivariate.py +495 -0
  305. truthound/ml/monitoring/__init__.py +88 -0
  306. truthound/ml/monitoring/alerting/__init__.py +33 -0
  307. truthound/ml/monitoring/alerting/handlers.py +427 -0
  308. truthound/ml/monitoring/alerting/rules.py +508 -0
  309. truthound/ml/monitoring/collectors/__init__.py +19 -0
  310. truthound/ml/monitoring/collectors/composite.py +105 -0
  311. truthound/ml/monitoring/collectors/drift.py +324 -0
  312. truthound/ml/monitoring/collectors/performance.py +179 -0
  313. truthound/ml/monitoring/collectors/quality.py +369 -0
  314. truthound/ml/monitoring/monitor.py +536 -0
  315. truthound/ml/monitoring/protocols.py +451 -0
  316. truthound/ml/monitoring/stores/__init__.py +15 -0
  317. truthound/ml/monitoring/stores/memory.py +201 -0
  318. truthound/ml/monitoring/stores/prometheus.py +296 -0
  319. truthound/ml/rule_learning/__init__.py +25 -0
  320. truthound/ml/rule_learning/constraint_miner.py +443 -0
  321. truthound/ml/rule_learning/pattern_learner.py +499 -0
  322. truthound/ml/rule_learning/profile_learner.py +462 -0
  323. truthound/multitenancy/__init__.py +326 -0
  324. truthound/multitenancy/core.py +852 -0
  325. truthound/multitenancy/integration.py +597 -0
  326. truthound/multitenancy/isolation.py +630 -0
  327. truthound/multitenancy/manager.py +770 -0
  328. truthound/multitenancy/middleware.py +765 -0
  329. truthound/multitenancy/quota.py +537 -0
  330. truthound/multitenancy/resolvers.py +603 -0
  331. truthound/multitenancy/storage.py +703 -0
  332. truthound/observability/__init__.py +307 -0
  333. truthound/observability/context.py +531 -0
  334. truthound/observability/instrumentation.py +611 -0
  335. truthound/observability/logging.py +887 -0
  336. truthound/observability/metrics.py +1157 -0
  337. truthound/observability/tracing/__init__.py +178 -0
  338. truthound/observability/tracing/baggage.py +310 -0
  339. truthound/observability/tracing/config.py +426 -0
  340. truthound/observability/tracing/exporter.py +787 -0
  341. truthound/observability/tracing/integration.py +1018 -0
  342. truthound/observability/tracing/otel/__init__.py +146 -0
  343. truthound/observability/tracing/otel/adapter.py +982 -0
  344. truthound/observability/tracing/otel/bridge.py +1177 -0
  345. truthound/observability/tracing/otel/compat.py +681 -0
  346. truthound/observability/tracing/otel/config.py +691 -0
  347. truthound/observability/tracing/otel/detection.py +327 -0
  348. truthound/observability/tracing/otel/protocols.py +426 -0
  349. truthound/observability/tracing/processor.py +561 -0
  350. truthound/observability/tracing/propagator.py +757 -0
  351. truthound/observability/tracing/provider.py +569 -0
  352. truthound/observability/tracing/resource.py +515 -0
  353. truthound/observability/tracing/sampler.py +487 -0
  354. truthound/observability/tracing/span.py +676 -0
  355. truthound/plugins/__init__.py +198 -0
  356. truthound/plugins/base.py +599 -0
  357. truthound/plugins/cli.py +680 -0
  358. truthound/plugins/dependencies/__init__.py +42 -0
  359. truthound/plugins/dependencies/graph.py +422 -0
  360. truthound/plugins/dependencies/resolver.py +417 -0
  361. truthound/plugins/discovery.py +379 -0
  362. truthound/plugins/docs/__init__.py +46 -0
  363. truthound/plugins/docs/extractor.py +444 -0
  364. truthound/plugins/docs/renderer.py +499 -0
  365. truthound/plugins/enterprise_manager.py +877 -0
  366. truthound/plugins/examples/__init__.py +19 -0
  367. truthound/plugins/examples/custom_validators.py +317 -0
  368. truthound/plugins/examples/slack_notifier.py +312 -0
  369. truthound/plugins/examples/xml_reporter.py +254 -0
  370. truthound/plugins/hooks.py +558 -0
  371. truthound/plugins/lifecycle/__init__.py +43 -0
  372. truthound/plugins/lifecycle/hot_reload.py +402 -0
  373. truthound/plugins/lifecycle/manager.py +371 -0
  374. truthound/plugins/manager.py +736 -0
  375. truthound/plugins/registry.py +338 -0
  376. truthound/plugins/security/__init__.py +93 -0
  377. truthound/plugins/security/exceptions.py +332 -0
  378. truthound/plugins/security/policies.py +348 -0
  379. truthound/plugins/security/protocols.py +643 -0
  380. truthound/plugins/security/sandbox/__init__.py +45 -0
  381. truthound/plugins/security/sandbox/context.py +158 -0
  382. truthound/plugins/security/sandbox/engines/__init__.py +19 -0
  383. truthound/plugins/security/sandbox/engines/container.py +379 -0
  384. truthound/plugins/security/sandbox/engines/noop.py +144 -0
  385. truthound/plugins/security/sandbox/engines/process.py +336 -0
  386. truthound/plugins/security/sandbox/factory.py +211 -0
  387. truthound/plugins/security/signing/__init__.py +57 -0
  388. truthound/plugins/security/signing/service.py +330 -0
  389. truthound/plugins/security/signing/trust_store.py +368 -0
  390. truthound/plugins/security/signing/verifier.py +459 -0
  391. truthound/plugins/versioning/__init__.py +41 -0
  392. truthound/plugins/versioning/constraints.py +297 -0
  393. truthound/plugins/versioning/resolver.py +329 -0
  394. truthound/profiler/__init__.py +1729 -0
  395. truthound/profiler/_lazy.py +452 -0
  396. truthound/profiler/ab_testing/__init__.py +80 -0
  397. truthound/profiler/ab_testing/analysis.py +449 -0
  398. truthound/profiler/ab_testing/base.py +257 -0
  399. truthound/profiler/ab_testing/experiment.py +395 -0
  400. truthound/profiler/ab_testing/tracking.py +368 -0
  401. truthound/profiler/auto_threshold.py +1170 -0
  402. truthound/profiler/base.py +579 -0
  403. truthound/profiler/cache_patterns.py +911 -0
  404. truthound/profiler/caching.py +1303 -0
  405. truthound/profiler/column_profiler.py +712 -0
  406. truthound/profiler/comparison.py +1007 -0
  407. truthound/profiler/custom_patterns.py +1170 -0
  408. truthound/profiler/dashboard/__init__.py +50 -0
  409. truthound/profiler/dashboard/app.py +476 -0
  410. truthound/profiler/dashboard/components.py +457 -0
  411. truthound/profiler/dashboard/config.py +72 -0
  412. truthound/profiler/distributed/__init__.py +83 -0
  413. truthound/profiler/distributed/base.py +281 -0
  414. truthound/profiler/distributed/dask_backend.py +498 -0
  415. truthound/profiler/distributed/local_backend.py +293 -0
  416. truthound/profiler/distributed/profiler.py +304 -0
  417. truthound/profiler/distributed/ray_backend.py +374 -0
  418. truthound/profiler/distributed/spark_backend.py +375 -0
  419. truthound/profiler/distributed.py +1366 -0
  420. truthound/profiler/enterprise_sampling.py +1065 -0
  421. truthound/profiler/errors.py +488 -0
  422. truthound/profiler/evolution/__init__.py +91 -0
  423. truthound/profiler/evolution/alerts.py +426 -0
  424. truthound/profiler/evolution/changes.py +206 -0
  425. truthound/profiler/evolution/compatibility.py +365 -0
  426. truthound/profiler/evolution/detector.py +372 -0
  427. truthound/profiler/evolution/protocols.py +121 -0
  428. truthound/profiler/generators/__init__.py +48 -0
  429. truthound/profiler/generators/base.py +384 -0
  430. truthound/profiler/generators/ml_rules.py +375 -0
  431. truthound/profiler/generators/pattern_rules.py +384 -0
  432. truthound/profiler/generators/schema_rules.py +267 -0
  433. truthound/profiler/generators/stats_rules.py +324 -0
  434. truthound/profiler/generators/suite_generator.py +857 -0
  435. truthound/profiler/i18n.py +1542 -0
  436. truthound/profiler/incremental.py +554 -0
  437. truthound/profiler/incremental_validation.py +1710 -0
  438. truthound/profiler/integration/__init__.py +73 -0
  439. truthound/profiler/integration/adapters.py +345 -0
  440. truthound/profiler/integration/context.py +371 -0
  441. truthound/profiler/integration/executor.py +527 -0
  442. truthound/profiler/integration/naming.py +75 -0
  443. truthound/profiler/integration/protocols.py +243 -0
  444. truthound/profiler/memory.py +1185 -0
  445. truthound/profiler/migration/__init__.py +60 -0
  446. truthound/profiler/migration/base.py +345 -0
  447. truthound/profiler/migration/manager.py +444 -0
  448. truthound/profiler/migration/v1_0_to_v1_1.py +484 -0
  449. truthound/profiler/ml/__init__.py +73 -0
  450. truthound/profiler/ml/base.py +244 -0
  451. truthound/profiler/ml/classifier.py +507 -0
  452. truthound/profiler/ml/feature_extraction.py +604 -0
  453. truthound/profiler/ml/pretrained.py +448 -0
  454. truthound/profiler/ml_inference.py +1276 -0
  455. truthound/profiler/native_patterns.py +815 -0
  456. truthound/profiler/observability.py +1184 -0
  457. truthound/profiler/process_timeout.py +1566 -0
  458. truthound/profiler/progress.py +568 -0
  459. truthound/profiler/progress_callbacks.py +1734 -0
  460. truthound/profiler/quality.py +1345 -0
  461. truthound/profiler/resilience.py +1180 -0
  462. truthound/profiler/sampled_matcher.py +794 -0
  463. truthound/profiler/sampling.py +1288 -0
  464. truthound/profiler/scheduling/__init__.py +82 -0
  465. truthound/profiler/scheduling/protocols.py +214 -0
  466. truthound/profiler/scheduling/scheduler.py +474 -0
  467. truthound/profiler/scheduling/storage.py +457 -0
  468. truthound/profiler/scheduling/triggers.py +449 -0
  469. truthound/profiler/schema.py +603 -0
  470. truthound/profiler/streaming.py +685 -0
  471. truthound/profiler/streaming_patterns.py +1354 -0
  472. truthound/profiler/suite_cli.py +625 -0
  473. truthound/profiler/suite_config.py +789 -0
  474. truthound/profiler/suite_export.py +1268 -0
  475. truthound/profiler/table_profiler.py +547 -0
  476. truthound/profiler/timeout.py +565 -0
  477. truthound/profiler/validation.py +1532 -0
  478. truthound/profiler/visualization/__init__.py +118 -0
  479. truthound/profiler/visualization/base.py +346 -0
  480. truthound/profiler/visualization/generator.py +1259 -0
  481. truthound/profiler/visualization/plotly_renderer.py +811 -0
  482. truthound/profiler/visualization/renderers.py +669 -0
  483. truthound/profiler/visualization/sections.py +540 -0
  484. truthound/profiler/visualization.py +2122 -0
  485. truthound/profiler/yaml_validation.py +1151 -0
  486. truthound/py.typed +0 -0
  487. truthound/ratelimit/__init__.py +248 -0
  488. truthound/ratelimit/algorithms.py +1108 -0
  489. truthound/ratelimit/core.py +573 -0
  490. truthound/ratelimit/integration.py +532 -0
  491. truthound/ratelimit/limiter.py +663 -0
  492. truthound/ratelimit/middleware.py +700 -0
  493. truthound/ratelimit/policy.py +792 -0
  494. truthound/ratelimit/storage.py +763 -0
  495. truthound/rbac/__init__.py +340 -0
  496. truthound/rbac/core.py +976 -0
  497. truthound/rbac/integration.py +760 -0
  498. truthound/rbac/manager.py +1052 -0
  499. truthound/rbac/middleware.py +842 -0
  500. truthound/rbac/policy.py +954 -0
  501. truthound/rbac/storage.py +878 -0
  502. truthound/realtime/__init__.py +141 -0
  503. truthound/realtime/adapters/__init__.py +43 -0
  504. truthound/realtime/adapters/base.py +533 -0
  505. truthound/realtime/adapters/kafka.py +487 -0
  506. truthound/realtime/adapters/kinesis.py +479 -0
  507. truthound/realtime/adapters/mock.py +243 -0
  508. truthound/realtime/base.py +553 -0
  509. truthound/realtime/factory.py +382 -0
  510. truthound/realtime/incremental.py +660 -0
  511. truthound/realtime/processing/__init__.py +67 -0
  512. truthound/realtime/processing/exactly_once.py +575 -0
  513. truthound/realtime/processing/state.py +547 -0
  514. truthound/realtime/processing/windows.py +647 -0
  515. truthound/realtime/protocols.py +569 -0
  516. truthound/realtime/streaming.py +605 -0
  517. truthound/realtime/testing/__init__.py +32 -0
  518. truthound/realtime/testing/containers.py +615 -0
  519. truthound/realtime/testing/fixtures.py +484 -0
  520. truthound/report.py +280 -0
  521. truthound/reporters/__init__.py +46 -0
  522. truthound/reporters/_protocols.py +30 -0
  523. truthound/reporters/base.py +324 -0
  524. truthound/reporters/ci/__init__.py +66 -0
  525. truthound/reporters/ci/azure.py +436 -0
  526. truthound/reporters/ci/base.py +509 -0
  527. truthound/reporters/ci/bitbucket.py +567 -0
  528. truthound/reporters/ci/circleci.py +547 -0
  529. truthound/reporters/ci/detection.py +364 -0
  530. truthound/reporters/ci/factory.py +182 -0
  531. truthound/reporters/ci/github.py +388 -0
  532. truthound/reporters/ci/gitlab.py +471 -0
  533. truthound/reporters/ci/jenkins.py +525 -0
  534. truthound/reporters/console_reporter.py +299 -0
  535. truthound/reporters/factory.py +211 -0
  536. truthound/reporters/html_reporter.py +524 -0
  537. truthound/reporters/json_reporter.py +256 -0
  538. truthound/reporters/markdown_reporter.py +280 -0
  539. truthound/reporters/sdk/__init__.py +174 -0
  540. truthound/reporters/sdk/builder.py +558 -0
  541. truthound/reporters/sdk/mixins.py +1150 -0
  542. truthound/reporters/sdk/schema.py +1493 -0
  543. truthound/reporters/sdk/templates.py +666 -0
  544. truthound/reporters/sdk/testing.py +968 -0
  545. truthound/scanners.py +170 -0
  546. truthound/scheduling/__init__.py +122 -0
  547. truthound/scheduling/cron.py +1136 -0
  548. truthound/scheduling/presets.py +212 -0
  549. truthound/schema.py +275 -0
  550. truthound/secrets/__init__.py +173 -0
  551. truthound/secrets/base.py +618 -0
  552. truthound/secrets/cloud.py +682 -0
  553. truthound/secrets/integration.py +507 -0
  554. truthound/secrets/manager.py +633 -0
  555. truthound/secrets/oidc/__init__.py +172 -0
  556. truthound/secrets/oidc/base.py +902 -0
  557. truthound/secrets/oidc/credential_provider.py +623 -0
  558. truthound/secrets/oidc/exchangers.py +1001 -0
  559. truthound/secrets/oidc/github/__init__.py +110 -0
  560. truthound/secrets/oidc/github/claims.py +718 -0
  561. truthound/secrets/oidc/github/enhanced_provider.py +693 -0
  562. truthound/secrets/oidc/github/trust_policy.py +742 -0
  563. truthound/secrets/oidc/github/verification.py +723 -0
  564. truthound/secrets/oidc/github/workflow.py +691 -0
  565. truthound/secrets/oidc/providers.py +825 -0
  566. truthound/secrets/providers.py +506 -0
  567. truthound/secrets/resolver.py +495 -0
  568. truthound/stores/__init__.py +177 -0
  569. truthound/stores/backends/__init__.py +18 -0
  570. truthound/stores/backends/_protocols.py +340 -0
  571. truthound/stores/backends/azure_blob.py +530 -0
  572. truthound/stores/backends/concurrent_filesystem.py +915 -0
  573. truthound/stores/backends/connection_pool.py +1365 -0
  574. truthound/stores/backends/database.py +743 -0
  575. truthound/stores/backends/filesystem.py +538 -0
  576. truthound/stores/backends/gcs.py +399 -0
  577. truthound/stores/backends/memory.py +354 -0
  578. truthound/stores/backends/s3.py +434 -0
  579. truthound/stores/backpressure/__init__.py +84 -0
  580. truthound/stores/backpressure/base.py +375 -0
  581. truthound/stores/backpressure/circuit_breaker.py +434 -0
  582. truthound/stores/backpressure/monitor.py +376 -0
  583. truthound/stores/backpressure/strategies.py +677 -0
  584. truthound/stores/base.py +551 -0
  585. truthound/stores/batching/__init__.py +65 -0
  586. truthound/stores/batching/base.py +305 -0
  587. truthound/stores/batching/buffer.py +370 -0
  588. truthound/stores/batching/store.py +248 -0
  589. truthound/stores/batching/writer.py +521 -0
  590. truthound/stores/caching/__init__.py +60 -0
  591. truthound/stores/caching/backends.py +684 -0
  592. truthound/stores/caching/base.py +356 -0
  593. truthound/stores/caching/store.py +305 -0
  594. truthound/stores/compression/__init__.py +193 -0
  595. truthound/stores/compression/adaptive.py +694 -0
  596. truthound/stores/compression/base.py +514 -0
  597. truthound/stores/compression/pipeline.py +868 -0
  598. truthound/stores/compression/providers.py +672 -0
  599. truthound/stores/compression/streaming.py +832 -0
  600. truthound/stores/concurrency/__init__.py +81 -0
  601. truthound/stores/concurrency/atomic.py +556 -0
  602. truthound/stores/concurrency/index.py +775 -0
  603. truthound/stores/concurrency/locks.py +576 -0
  604. truthound/stores/concurrency/manager.py +482 -0
  605. truthound/stores/encryption/__init__.py +297 -0
  606. truthound/stores/encryption/base.py +952 -0
  607. truthound/stores/encryption/keys.py +1191 -0
  608. truthound/stores/encryption/pipeline.py +903 -0
  609. truthound/stores/encryption/providers.py +953 -0
  610. truthound/stores/encryption/streaming.py +950 -0
  611. truthound/stores/expectations.py +227 -0
  612. truthound/stores/factory.py +246 -0
  613. truthound/stores/migration/__init__.py +75 -0
  614. truthound/stores/migration/base.py +480 -0
  615. truthound/stores/migration/manager.py +347 -0
  616. truthound/stores/migration/registry.py +382 -0
  617. truthound/stores/migration/store.py +559 -0
  618. truthound/stores/observability/__init__.py +106 -0
  619. truthound/stores/observability/audit.py +718 -0
  620. truthound/stores/observability/config.py +270 -0
  621. truthound/stores/observability/factory.py +208 -0
  622. truthound/stores/observability/metrics.py +636 -0
  623. truthound/stores/observability/protocols.py +410 -0
  624. truthound/stores/observability/store.py +570 -0
  625. truthound/stores/observability/tracing.py +784 -0
  626. truthound/stores/replication/__init__.py +76 -0
  627. truthound/stores/replication/base.py +260 -0
  628. truthound/stores/replication/monitor.py +269 -0
  629. truthound/stores/replication/store.py +439 -0
  630. truthound/stores/replication/syncer.py +391 -0
  631. truthound/stores/results.py +359 -0
  632. truthound/stores/retention/__init__.py +77 -0
  633. truthound/stores/retention/base.py +378 -0
  634. truthound/stores/retention/policies.py +621 -0
  635. truthound/stores/retention/scheduler.py +279 -0
  636. truthound/stores/retention/store.py +526 -0
  637. truthound/stores/streaming/__init__.py +138 -0
  638. truthound/stores/streaming/base.py +801 -0
  639. truthound/stores/streaming/database.py +984 -0
  640. truthound/stores/streaming/filesystem.py +719 -0
  641. truthound/stores/streaming/reader.py +629 -0
  642. truthound/stores/streaming/s3.py +843 -0
  643. truthound/stores/streaming/writer.py +790 -0
  644. truthound/stores/tiering/__init__.py +108 -0
  645. truthound/stores/tiering/base.py +462 -0
  646. truthound/stores/tiering/manager.py +249 -0
  647. truthound/stores/tiering/policies.py +692 -0
  648. truthound/stores/tiering/store.py +526 -0
  649. truthound/stores/versioning/__init__.py +56 -0
  650. truthound/stores/versioning/base.py +376 -0
  651. truthound/stores/versioning/store.py +660 -0
  652. truthound/stores/versioning/strategies.py +353 -0
  653. truthound/types.py +56 -0
  654. truthound/validators/__init__.py +774 -0
  655. truthound/validators/aggregate/__init__.py +27 -0
  656. truthound/validators/aggregate/central.py +116 -0
  657. truthound/validators/aggregate/extremes.py +116 -0
  658. truthound/validators/aggregate/spread.py +118 -0
  659. truthound/validators/aggregate/sum.py +64 -0
  660. truthound/validators/aggregate/type.py +78 -0
  661. truthound/validators/anomaly/__init__.py +93 -0
  662. truthound/validators/anomaly/base.py +431 -0
  663. truthound/validators/anomaly/ml_based.py +1190 -0
  664. truthound/validators/anomaly/multivariate.py +647 -0
  665. truthound/validators/anomaly/statistical.py +599 -0
  666. truthound/validators/base.py +1089 -0
  667. truthound/validators/business_rule/__init__.py +46 -0
  668. truthound/validators/business_rule/base.py +147 -0
  669. truthound/validators/business_rule/checksum.py +509 -0
  670. truthound/validators/business_rule/financial.py +526 -0
  671. truthound/validators/cache.py +733 -0
  672. truthound/validators/completeness/__init__.py +39 -0
  673. truthound/validators/completeness/conditional.py +73 -0
  674. truthound/validators/completeness/default.py +98 -0
  675. truthound/validators/completeness/empty.py +103 -0
  676. truthound/validators/completeness/nan.py +337 -0
  677. truthound/validators/completeness/null.py +152 -0
  678. truthound/validators/cross_table/__init__.py +17 -0
  679. truthound/validators/cross_table/aggregate.py +333 -0
  680. truthound/validators/cross_table/row_count.py +122 -0
  681. truthound/validators/datetime/__init__.py +29 -0
  682. truthound/validators/datetime/format.py +78 -0
  683. truthound/validators/datetime/freshness.py +269 -0
  684. truthound/validators/datetime/order.py +73 -0
  685. truthound/validators/datetime/parseable.py +185 -0
  686. truthound/validators/datetime/range.py +202 -0
  687. truthound/validators/datetime/timezone.py +69 -0
  688. truthound/validators/distribution/__init__.py +49 -0
  689. truthound/validators/distribution/distribution.py +128 -0
  690. truthound/validators/distribution/monotonic.py +119 -0
  691. truthound/validators/distribution/outlier.py +178 -0
  692. truthound/validators/distribution/quantile.py +80 -0
  693. truthound/validators/distribution/range.py +254 -0
  694. truthound/validators/distribution/set.py +125 -0
  695. truthound/validators/distribution/statistical.py +459 -0
  696. truthound/validators/drift/__init__.py +79 -0
  697. truthound/validators/drift/base.py +427 -0
  698. truthound/validators/drift/multi_feature.py +401 -0
  699. truthound/validators/drift/numeric.py +395 -0
  700. truthound/validators/drift/psi.py +446 -0
  701. truthound/validators/drift/statistical.py +510 -0
  702. truthound/validators/enterprise.py +1658 -0
  703. truthound/validators/geospatial/__init__.py +80 -0
  704. truthound/validators/geospatial/base.py +97 -0
  705. truthound/validators/geospatial/boundary.py +238 -0
  706. truthound/validators/geospatial/coordinate.py +351 -0
  707. truthound/validators/geospatial/distance.py +399 -0
  708. truthound/validators/geospatial/polygon.py +665 -0
  709. truthound/validators/i18n/__init__.py +308 -0
  710. truthound/validators/i18n/bidi.py +571 -0
  711. truthound/validators/i18n/catalogs.py +570 -0
  712. truthound/validators/i18n/dialects.py +763 -0
  713. truthound/validators/i18n/extended_catalogs.py +549 -0
  714. truthound/validators/i18n/formatting.py +1434 -0
  715. truthound/validators/i18n/loader.py +1020 -0
  716. truthound/validators/i18n/messages.py +521 -0
  717. truthound/validators/i18n/plural.py +683 -0
  718. truthound/validators/i18n/protocols.py +855 -0
  719. truthound/validators/i18n/tms.py +1162 -0
  720. truthound/validators/localization/__init__.py +53 -0
  721. truthound/validators/localization/base.py +122 -0
  722. truthound/validators/localization/chinese.py +362 -0
  723. truthound/validators/localization/japanese.py +275 -0
  724. truthound/validators/localization/korean.py +524 -0
  725. truthound/validators/memory/__init__.py +94 -0
  726. truthound/validators/memory/approximate_knn.py +506 -0
  727. truthound/validators/memory/base.py +547 -0
  728. truthound/validators/memory/sgd_online.py +719 -0
  729. truthound/validators/memory/streaming_ecdf.py +753 -0
  730. truthound/validators/ml_feature/__init__.py +54 -0
  731. truthound/validators/ml_feature/base.py +249 -0
  732. truthound/validators/ml_feature/correlation.py +299 -0
  733. truthound/validators/ml_feature/leakage.py +344 -0
  734. truthound/validators/ml_feature/null_impact.py +270 -0
  735. truthound/validators/ml_feature/scale.py +264 -0
  736. truthound/validators/multi_column/__init__.py +89 -0
  737. truthound/validators/multi_column/arithmetic.py +284 -0
  738. truthound/validators/multi_column/base.py +231 -0
  739. truthound/validators/multi_column/comparison.py +273 -0
  740. truthound/validators/multi_column/consistency.py +312 -0
  741. truthound/validators/multi_column/statistical.py +299 -0
  742. truthound/validators/optimization/__init__.py +164 -0
  743. truthound/validators/optimization/aggregation.py +563 -0
  744. truthound/validators/optimization/covariance.py +556 -0
  745. truthound/validators/optimization/geo.py +626 -0
  746. truthound/validators/optimization/graph.py +587 -0
  747. truthound/validators/optimization/orchestrator.py +970 -0
  748. truthound/validators/optimization/profiling.py +1312 -0
  749. truthound/validators/privacy/__init__.py +223 -0
  750. truthound/validators/privacy/base.py +635 -0
  751. truthound/validators/privacy/ccpa.py +670 -0
  752. truthound/validators/privacy/gdpr.py +728 -0
  753. truthound/validators/privacy/global_patterns.py +604 -0
  754. truthound/validators/privacy/plugins.py +867 -0
  755. truthound/validators/profiling/__init__.py +52 -0
  756. truthound/validators/profiling/base.py +175 -0
  757. truthound/validators/profiling/cardinality.py +312 -0
  758. truthound/validators/profiling/entropy.py +391 -0
  759. truthound/validators/profiling/frequency.py +455 -0
  760. truthound/validators/pushdown_support.py +660 -0
  761. truthound/validators/query/__init__.py +91 -0
  762. truthound/validators/query/aggregate.py +346 -0
  763. truthound/validators/query/base.py +246 -0
  764. truthound/validators/query/column.py +249 -0
  765. truthound/validators/query/expression.py +274 -0
  766. truthound/validators/query/result.py +323 -0
  767. truthound/validators/query/row_count.py +264 -0
  768. truthound/validators/referential/__init__.py +80 -0
  769. truthound/validators/referential/base.py +395 -0
  770. truthound/validators/referential/cascade.py +391 -0
  771. truthound/validators/referential/circular.py +563 -0
  772. truthound/validators/referential/foreign_key.py +624 -0
  773. truthound/validators/referential/orphan.py +485 -0
  774. truthound/validators/registry.py +112 -0
  775. truthound/validators/schema/__init__.py +41 -0
  776. truthound/validators/schema/column_count.py +142 -0
  777. truthound/validators/schema/column_exists.py +80 -0
  778. truthound/validators/schema/column_order.py +82 -0
  779. truthound/validators/schema/column_pair.py +85 -0
  780. truthound/validators/schema/column_pair_set.py +195 -0
  781. truthound/validators/schema/column_type.py +94 -0
  782. truthound/validators/schema/multi_column.py +53 -0
  783. truthound/validators/schema/multi_column_aggregate.py +175 -0
  784. truthound/validators/schema/referential.py +274 -0
  785. truthound/validators/schema/table_schema.py +91 -0
  786. truthound/validators/schema_validator.py +219 -0
  787. truthound/validators/sdk/__init__.py +250 -0
  788. truthound/validators/sdk/builder.py +680 -0
  789. truthound/validators/sdk/decorators.py +474 -0
  790. truthound/validators/sdk/enterprise/__init__.py +211 -0
  791. truthound/validators/sdk/enterprise/docs.py +725 -0
  792. truthound/validators/sdk/enterprise/fuzzing.py +659 -0
  793. truthound/validators/sdk/enterprise/licensing.py +709 -0
  794. truthound/validators/sdk/enterprise/manager.py +543 -0
  795. truthound/validators/sdk/enterprise/resources.py +628 -0
  796. truthound/validators/sdk/enterprise/sandbox.py +766 -0
  797. truthound/validators/sdk/enterprise/signing.py +603 -0
  798. truthound/validators/sdk/enterprise/templates.py +865 -0
  799. truthound/validators/sdk/enterprise/versioning.py +659 -0
  800. truthound/validators/sdk/templates.py +757 -0
  801. truthound/validators/sdk/testing.py +807 -0
  802. truthound/validators/security/__init__.py +181 -0
  803. truthound/validators/security/redos/__init__.py +182 -0
  804. truthound/validators/security/redos/core.py +861 -0
  805. truthound/validators/security/redos/cpu_monitor.py +593 -0
  806. truthound/validators/security/redos/cve_database.py +791 -0
  807. truthound/validators/security/redos/ml/__init__.py +155 -0
  808. truthound/validators/security/redos/ml/base.py +785 -0
  809. truthound/validators/security/redos/ml/datasets.py +618 -0
  810. truthound/validators/security/redos/ml/features.py +359 -0
  811. truthound/validators/security/redos/ml/models.py +1000 -0
  812. truthound/validators/security/redos/ml/predictor.py +507 -0
  813. truthound/validators/security/redos/ml/storage.py +632 -0
  814. truthound/validators/security/redos/ml/training.py +571 -0
  815. truthound/validators/security/redos/ml_analyzer.py +937 -0
  816. truthound/validators/security/redos/optimizer.py +674 -0
  817. truthound/validators/security/redos/profiler.py +682 -0
  818. truthound/validators/security/redos/re2_engine.py +709 -0
  819. truthound/validators/security/redos.py +886 -0
  820. truthound/validators/security/sql_security.py +1247 -0
  821. truthound/validators/streaming/__init__.py +126 -0
  822. truthound/validators/streaming/base.py +292 -0
  823. truthound/validators/streaming/completeness.py +210 -0
  824. truthound/validators/streaming/mixin.py +575 -0
  825. truthound/validators/streaming/range.py +308 -0
  826. truthound/validators/streaming/sources.py +846 -0
  827. truthound/validators/string/__init__.py +57 -0
  828. truthound/validators/string/casing.py +158 -0
  829. truthound/validators/string/charset.py +96 -0
  830. truthound/validators/string/format.py +501 -0
  831. truthound/validators/string/json.py +77 -0
  832. truthound/validators/string/json_schema.py +184 -0
  833. truthound/validators/string/length.py +104 -0
  834. truthound/validators/string/like_pattern.py +237 -0
  835. truthound/validators/string/regex.py +202 -0
  836. truthound/validators/string/regex_extended.py +435 -0
  837. truthound/validators/table/__init__.py +88 -0
  838. truthound/validators/table/base.py +78 -0
  839. truthound/validators/table/column_count.py +198 -0
  840. truthound/validators/table/freshness.py +362 -0
  841. truthound/validators/table/row_count.py +251 -0
  842. truthound/validators/table/schema.py +333 -0
  843. truthound/validators/table/size.py +285 -0
  844. truthound/validators/timeout/__init__.py +102 -0
  845. truthound/validators/timeout/advanced/__init__.py +247 -0
  846. truthound/validators/timeout/advanced/circuit_breaker.py +675 -0
  847. truthound/validators/timeout/advanced/prediction.py +773 -0
  848. truthound/validators/timeout/advanced/priority.py +618 -0
  849. truthound/validators/timeout/advanced/redis_backend.py +770 -0
  850. truthound/validators/timeout/advanced/retry.py +721 -0
  851. truthound/validators/timeout/advanced/sampling.py +788 -0
  852. truthound/validators/timeout/advanced/sla.py +661 -0
  853. truthound/validators/timeout/advanced/telemetry.py +804 -0
  854. truthound/validators/timeout/cascade.py +477 -0
  855. truthound/validators/timeout/deadline.py +657 -0
  856. truthound/validators/timeout/degradation.py +525 -0
  857. truthound/validators/timeout/distributed.py +597 -0
  858. truthound/validators/timeseries/__init__.py +89 -0
  859. truthound/validators/timeseries/base.py +326 -0
  860. truthound/validators/timeseries/completeness.py +617 -0
  861. truthound/validators/timeseries/gap.py +485 -0
  862. truthound/validators/timeseries/monotonic.py +310 -0
  863. truthound/validators/timeseries/seasonality.py +422 -0
  864. truthound/validators/timeseries/trend.py +510 -0
  865. truthound/validators/uniqueness/__init__.py +59 -0
  866. truthound/validators/uniqueness/approximate.py +475 -0
  867. truthound/validators/uniqueness/distinct_values.py +253 -0
  868. truthound/validators/uniqueness/duplicate.py +118 -0
  869. truthound/validators/uniqueness/primary_key.py +140 -0
  870. truthound/validators/uniqueness/unique.py +191 -0
  871. truthound/validators/uniqueness/within_record.py +599 -0
  872. truthound/validators/utils.py +756 -0
  873. truthound-1.0.8.dist-info/METADATA +474 -0
  874. truthound-1.0.8.dist-info/RECORD +877 -0
  875. truthound-1.0.8.dist-info/WHEEL +4 -0
  876. truthound-1.0.8.dist-info/entry_points.txt +2 -0
  877. truthound-1.0.8.dist-info/licenses/LICENSE +190 -0
@@ -0,0 +1,718 @@
1
+ """GitHub Actions OIDC Claims Parsing and Validation.
2
+
3
+ This module provides comprehensive parsing and validation of GitHub Actions
4
+ OIDC token claims, including all standard and GitHub-specific claims.
5
+
6
+ GitHub Actions OIDC Token Claims Reference:
7
+ https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect
8
+
9
+ Standard Claims:
10
+ - iss: Token issuer (https://token.actions.githubusercontent.com)
11
+ - sub: Subject identifier (repo:owner/repo:ref:refs/heads/main)
12
+ - aud: Token audience (configured by user)
13
+ - exp: Expiration time
14
+ - iat: Issued at time
15
+ - nbf: Not before time
16
+ - jti: JWT ID (unique identifier)
17
+
18
+ GitHub-Specific Claims:
19
+ - repository: Full repository name (owner/repo)
20
+ - repository_owner: Repository owner (user or org)
21
+ - repository_owner_id: Owner's numeric ID
22
+ - repository_id: Repository's numeric ID
23
+ - repository_visibility: public, private, or internal
24
+ - actor: User who triggered the workflow
25
+ - actor_id: Actor's numeric ID
26
+ - workflow: Workflow name
27
+ - workflow_ref: Full workflow reference
28
+ - workflow_sha: Workflow file's commit SHA
29
+ - head_ref: Source branch for pull requests
30
+ - base_ref: Target branch for pull requests
31
+ - event_name: Triggering event (push, pull_request, etc.)
32
+ - ref: Git ref (refs/heads/main, refs/tags/v1.0)
33
+ - ref_type: branch or tag
34
+ - sha: Commit SHA
35
+ - run_id: Workflow run ID
36
+ - run_number: Workflow run number
37
+ - run_attempt: Workflow run attempt
38
+ - job_workflow_ref: Reusable workflow reference
39
+ - job_workflow_sha: Reusable workflow SHA
40
+ - runner_environment: github-hosted or self-hosted
41
+ - environment: Deployment environment name
42
+ - environment_node_id: Environment's node ID
43
+ """
44
+
45
+ from __future__ import annotations
46
+
47
+ import re
48
+ from dataclasses import dataclass, field
49
+ from datetime import datetime
50
+ from enum import Enum
51
+ from typing import Any
52
+
53
+
54
+ class EventType(str, Enum):
55
+ """GitHub Actions event types."""
56
+
57
+ PUSH = "push"
58
+ PULL_REQUEST = "pull_request"
59
+ PULL_REQUEST_TARGET = "pull_request_target"
60
+ WORKFLOW_DISPATCH = "workflow_dispatch"
61
+ WORKFLOW_CALL = "workflow_call"
62
+ SCHEDULE = "schedule"
63
+ RELEASE = "release"
64
+ DEPLOYMENT = "deployment"
65
+ DEPLOYMENT_STATUS = "deployment_status"
66
+ CREATE = "create"
67
+ DELETE = "delete"
68
+ FORK = "fork"
69
+ ISSUE_COMMENT = "issue_comment"
70
+ ISSUES = "issues"
71
+ MERGE_GROUP = "merge_group"
72
+ PAGE_BUILD = "page_build"
73
+ REGISTRY_PACKAGE = "registry_package"
74
+ REPOSITORY_DISPATCH = "repository_dispatch"
75
+ STATUS = "status"
76
+ WATCH = "watch"
77
+ UNKNOWN = "unknown"
78
+
79
+
80
+ class RefType(str, Enum):
81
+ """Git reference types."""
82
+
83
+ BRANCH = "branch"
84
+ TAG = "tag"
85
+ UNKNOWN = "unknown"
86
+
87
+
88
+ class RepositoryVisibility(str, Enum):
89
+ """Repository visibility levels."""
90
+
91
+ PUBLIC = "public"
92
+ PRIVATE = "private"
93
+ INTERNAL = "internal"
94
+ UNKNOWN = "unknown"
95
+
96
+
97
+ class RunnerEnvironment(str, Enum):
98
+ """Runner environment types."""
99
+
100
+ GITHUB_HOSTED = "github-hosted"
101
+ SELF_HOSTED = "self-hosted"
102
+ UNKNOWN = "unknown"
103
+
104
+
105
+ @dataclass(frozen=True)
106
+ class GitHubActionsClaims:
107
+ """Parsed GitHub Actions OIDC token claims.
108
+
109
+ This dataclass provides a strongly-typed representation of all claims
110
+ available in a GitHub Actions OIDC token.
111
+
112
+ Attributes:
113
+ # Standard OIDC Claims
114
+ issuer: Token issuer URL.
115
+ subject: Subject identifier.
116
+ audience: Token audience(s).
117
+ expiration: Token expiration time.
118
+ issued_at: Token issue time.
119
+ not_before: Token not-before time.
120
+ jwt_id: Unique JWT identifier.
121
+
122
+ # Repository Claims
123
+ repository: Full repository name (owner/repo).
124
+ repository_owner: Repository owner.
125
+ repository_owner_id: Owner's numeric ID.
126
+ repository_id: Repository's numeric ID.
127
+ repository_visibility: Repository visibility.
128
+
129
+ # Actor Claims
130
+ actor: User who triggered the workflow.
131
+ actor_id: Actor's numeric ID.
132
+
133
+ # Workflow Claims
134
+ workflow: Workflow name.
135
+ workflow_ref: Full workflow reference.
136
+ workflow_sha: Workflow file's commit SHA.
137
+ job_workflow_ref: Reusable workflow reference.
138
+ job_workflow_sha: Reusable workflow SHA.
139
+
140
+ # Git Reference Claims
141
+ ref: Git reference.
142
+ ref_type: Reference type (branch/tag).
143
+ sha: Commit SHA.
144
+ head_ref: Source branch for PRs.
145
+ base_ref: Target branch for PRs.
146
+
147
+ # Run Claims
148
+ run_id: Workflow run ID.
149
+ run_number: Workflow run number.
150
+ run_attempt: Workflow run attempt.
151
+ event_name: Triggering event type.
152
+
153
+ # Environment Claims
154
+ environment: Deployment environment name.
155
+ environment_node_id: Environment's node ID.
156
+ runner_environment: Runner type.
157
+
158
+ # Extra Claims
159
+ extra: Additional claims not covered above.
160
+ """
161
+
162
+ # Standard OIDC Claims
163
+ issuer: str
164
+ subject: str
165
+ audience: str | list[str]
166
+ expiration: datetime
167
+ issued_at: datetime
168
+ not_before: datetime | None = None
169
+ jwt_id: str | None = None
170
+
171
+ # Repository Claims
172
+ repository: str = ""
173
+ repository_owner: str = ""
174
+ repository_owner_id: str = ""
175
+ repository_id: str = ""
176
+ repository_visibility: RepositoryVisibility = RepositoryVisibility.UNKNOWN
177
+
178
+ # Actor Claims
179
+ actor: str = ""
180
+ actor_id: str = ""
181
+
182
+ # Workflow Claims
183
+ workflow: str = ""
184
+ workflow_ref: str = ""
185
+ workflow_sha: str = ""
186
+ job_workflow_ref: str | None = None
187
+ job_workflow_sha: str | None = None
188
+
189
+ # Git Reference Claims
190
+ ref: str = ""
191
+ ref_type: RefType = RefType.UNKNOWN
192
+ sha: str = ""
193
+ head_ref: str | None = None
194
+ base_ref: str | None = None
195
+
196
+ # Run Claims
197
+ run_id: str = ""
198
+ run_number: str = ""
199
+ run_attempt: str = ""
200
+ event_name: EventType = EventType.UNKNOWN
201
+
202
+ # Environment Claims
203
+ environment: str | None = None
204
+ environment_node_id: str | None = None
205
+ runner_environment: RunnerEnvironment = RunnerEnvironment.UNKNOWN
206
+
207
+ # Extra Claims
208
+ extra: dict[str, Any] = field(default_factory=dict)
209
+
210
+ @property
211
+ def is_expired(self) -> bool:
212
+ """Check if token is expired."""
213
+ return datetime.now() >= self.expiration
214
+
215
+ @property
216
+ def is_pull_request(self) -> bool:
217
+ """Check if triggered by a pull request."""
218
+ return self.event_name in (
219
+ EventType.PULL_REQUEST,
220
+ EventType.PULL_REQUEST_TARGET,
221
+ )
222
+
223
+ @property
224
+ def is_main_branch(self) -> bool:
225
+ """Check if running on main/master branch."""
226
+ return self.ref in (
227
+ "refs/heads/main",
228
+ "refs/heads/master",
229
+ )
230
+
231
+ @property
232
+ def is_tag(self) -> bool:
233
+ """Check if triggered by a tag."""
234
+ return self.ref_type == RefType.TAG or self.ref.startswith("refs/tags/")
235
+
236
+ @property
237
+ def is_release(self) -> bool:
238
+ """Check if triggered by a release event."""
239
+ return self.event_name == EventType.RELEASE
240
+
241
+ @property
242
+ def is_scheduled(self) -> bool:
243
+ """Check if triggered by schedule."""
244
+ return self.event_name == EventType.SCHEDULE
245
+
246
+ @property
247
+ def is_workflow_dispatch(self) -> bool:
248
+ """Check if manually triggered."""
249
+ return self.event_name == EventType.WORKFLOW_DISPATCH
250
+
251
+ @property
252
+ def is_reusable_workflow(self) -> bool:
253
+ """Check if running as a reusable workflow."""
254
+ return self.job_workflow_ref is not None
255
+
256
+ @property
257
+ def has_environment(self) -> bool:
258
+ """Check if running in a deployment environment."""
259
+ return self.environment is not None
260
+
261
+ @property
262
+ def is_github_hosted(self) -> bool:
263
+ """Check if running on GitHub-hosted runner."""
264
+ return self.runner_environment == RunnerEnvironment.GITHUB_HOSTED
265
+
266
+ @property
267
+ def branch_name(self) -> str | None:
268
+ """Extract branch name from ref."""
269
+ if self.ref.startswith("refs/heads/"):
270
+ return self.ref[len("refs/heads/"):]
271
+ return None
272
+
273
+ @property
274
+ def tag_name(self) -> str | None:
275
+ """Extract tag name from ref."""
276
+ if self.ref.startswith("refs/tags/"):
277
+ return self.ref[len("refs/tags/"):]
278
+ return None
279
+
280
+ @property
281
+ def short_sha(self) -> str:
282
+ """Get short commit SHA (7 characters)."""
283
+ return self.sha[:7] if self.sha else ""
284
+
285
+ def matches_repository(self, pattern: str) -> bool:
286
+ """Check if repository matches a pattern.
287
+
288
+ Args:
289
+ pattern: Repository pattern (supports wildcards).
290
+ Examples: "owner/repo", "owner/*", "*/repo"
291
+
292
+ Returns:
293
+ True if repository matches the pattern.
294
+ """
295
+ if not self.repository:
296
+ return False
297
+
298
+ # Convert pattern to regex
299
+ regex_pattern = pattern.replace("*", ".*")
300
+ return bool(re.match(f"^{regex_pattern}$", self.repository))
301
+
302
+ def matches_ref(self, pattern: str) -> bool:
303
+ """Check if ref matches a pattern.
304
+
305
+ Args:
306
+ pattern: Ref pattern (supports wildcards).
307
+ Examples: "refs/heads/main", "refs/heads/*", "refs/tags/v*"
308
+
309
+ Returns:
310
+ True if ref matches the pattern.
311
+ """
312
+ if not self.ref:
313
+ return False
314
+
315
+ regex_pattern = pattern.replace("*", ".*")
316
+ return bool(re.match(f"^{regex_pattern}$", self.ref))
317
+
318
+ def to_dict(self) -> dict[str, Any]:
319
+ """Convert claims to dictionary."""
320
+ return {
321
+ "iss": self.issuer,
322
+ "sub": self.subject,
323
+ "aud": self.audience,
324
+ "exp": int(self.expiration.timestamp()),
325
+ "iat": int(self.issued_at.timestamp()),
326
+ "nbf": int(self.not_before.timestamp()) if self.not_before else None,
327
+ "jti": self.jwt_id,
328
+ "repository": self.repository,
329
+ "repository_owner": self.repository_owner,
330
+ "repository_owner_id": self.repository_owner_id,
331
+ "repository_id": self.repository_id,
332
+ "repository_visibility": self.repository_visibility.value,
333
+ "actor": self.actor,
334
+ "actor_id": self.actor_id,
335
+ "workflow": self.workflow,
336
+ "workflow_ref": self.workflow_ref,
337
+ "workflow_sha": self.workflow_sha,
338
+ "job_workflow_ref": self.job_workflow_ref,
339
+ "job_workflow_sha": self.job_workflow_sha,
340
+ "ref": self.ref,
341
+ "ref_type": self.ref_type.value,
342
+ "sha": self.sha,
343
+ "head_ref": self.head_ref,
344
+ "base_ref": self.base_ref,
345
+ "run_id": self.run_id,
346
+ "run_number": self.run_number,
347
+ "run_attempt": self.run_attempt,
348
+ "event_name": self.event_name.value,
349
+ "environment": self.environment,
350
+ "environment_node_id": self.environment_node_id,
351
+ "runner_environment": self.runner_environment.value,
352
+ **self.extra,
353
+ }
354
+
355
+
356
+ @dataclass
357
+ class GitHubActionsContext:
358
+ """GitHub Actions workflow context from environment variables.
359
+
360
+ This provides access to GitHub Actions context information that
361
+ is available through environment variables rather than the OIDC token.
362
+
363
+ Attributes:
364
+ github_token: GITHUB_TOKEN for API access.
365
+ github_api_url: GitHub API URL.
366
+ github_graphql_url: GitHub GraphQL API URL.
367
+ github_server_url: GitHub server URL.
368
+ github_workspace: Workspace directory path.
369
+ github_output: Output file path.
370
+ github_env: Environment file path.
371
+ github_step_summary: Step summary file path.
372
+ github_path: Path file.
373
+ github_action: Current action name.
374
+ github_action_path: Action's directory.
375
+ github_action_repository: Action's repository.
376
+ github_action_ref: Action's ref.
377
+ github_retention_days: Artifact retention days.
378
+ runner_name: Runner name.
379
+ runner_os: Runner OS (Linux, Windows, macOS).
380
+ runner_arch: Runner architecture.
381
+ runner_temp: Temp directory path.
382
+ runner_tool_cache: Tool cache path.
383
+ """
384
+
385
+ # GitHub Environment
386
+ github_token: str = ""
387
+ github_api_url: str = ""
388
+ github_graphql_url: str = ""
389
+ github_server_url: str = ""
390
+ github_workspace: str = ""
391
+ github_output: str = ""
392
+ github_env: str = ""
393
+ github_step_summary: str = ""
394
+ github_path: str = ""
395
+
396
+ # Action Context
397
+ github_action: str = ""
398
+ github_action_path: str = ""
399
+ github_action_repository: str = ""
400
+ github_action_ref: str = ""
401
+ github_retention_days: int = 0
402
+
403
+ # Runner Context
404
+ runner_name: str = ""
405
+ runner_os: str = ""
406
+ runner_arch: str = ""
407
+ runner_temp: str = ""
408
+ runner_tool_cache: str = ""
409
+
410
+ @classmethod
411
+ def from_environment(cls) -> "GitHubActionsContext":
412
+ """Create context from current environment variables."""
413
+ import os
414
+
415
+ retention_days = os.environ.get("GITHUB_RETENTION_DAYS", "0")
416
+ try:
417
+ retention_days_int = int(retention_days)
418
+ except ValueError:
419
+ retention_days_int = 0
420
+
421
+ return cls(
422
+ github_token=os.environ.get("GITHUB_TOKEN", ""),
423
+ github_api_url=os.environ.get("GITHUB_API_URL", "https://api.github.com"),
424
+ github_graphql_url=os.environ.get(
425
+ "GITHUB_GRAPHQL_URL", "https://api.github.com/graphql"
426
+ ),
427
+ github_server_url=os.environ.get("GITHUB_SERVER_URL", "https://github.com"),
428
+ github_workspace=os.environ.get("GITHUB_WORKSPACE", ""),
429
+ github_output=os.environ.get("GITHUB_OUTPUT", ""),
430
+ github_env=os.environ.get("GITHUB_ENV", ""),
431
+ github_step_summary=os.environ.get("GITHUB_STEP_SUMMARY", ""),
432
+ github_path=os.environ.get("GITHUB_PATH", ""),
433
+ github_action=os.environ.get("GITHUB_ACTION", ""),
434
+ github_action_path=os.environ.get("GITHUB_ACTION_PATH", ""),
435
+ github_action_repository=os.environ.get("GITHUB_ACTION_REPOSITORY", ""),
436
+ github_action_ref=os.environ.get("GITHUB_ACTION_REF", ""),
437
+ github_retention_days=retention_days_int,
438
+ runner_name=os.environ.get("RUNNER_NAME", ""),
439
+ runner_os=os.environ.get("RUNNER_OS", ""),
440
+ runner_arch=os.environ.get("RUNNER_ARCH", ""),
441
+ runner_temp=os.environ.get("RUNNER_TEMP", ""),
442
+ runner_tool_cache=os.environ.get("RUNNER_TOOL_CACHE", ""),
443
+ )
444
+
445
+
446
+ def parse_github_claims(payload: dict[str, Any]) -> GitHubActionsClaims:
447
+ """Parse GitHub Actions OIDC token claims.
448
+
449
+ Args:
450
+ payload: Decoded JWT payload.
451
+
452
+ Returns:
453
+ GitHubActionsClaims instance.
454
+ """
455
+ # Standard claims
456
+ issuer = payload.get("iss", "")
457
+ subject = payload.get("sub", "")
458
+ audience = payload.get("aud", "")
459
+
460
+ # Time claims
461
+ exp = payload.get("exp", 0)
462
+ iat = payload.get("iat", 0)
463
+ nbf = payload.get("nbf")
464
+
465
+ expiration = datetime.fromtimestamp(exp) if exp else datetime.now()
466
+ issued_at = datetime.fromtimestamp(iat) if iat else datetime.now()
467
+ not_before = datetime.fromtimestamp(nbf) if nbf else None
468
+
469
+ # Parse repository visibility
470
+ visibility_str = payload.get("repository_visibility", "unknown")
471
+ try:
472
+ visibility = RepositoryVisibility(visibility_str)
473
+ except ValueError:
474
+ visibility = RepositoryVisibility.UNKNOWN
475
+
476
+ # Parse ref type
477
+ ref_type_str = payload.get("ref_type", "unknown")
478
+ try:
479
+ ref_type = RefType(ref_type_str)
480
+ except ValueError:
481
+ ref_type = RefType.UNKNOWN
482
+
483
+ # Parse event name
484
+ event_str = payload.get("event_name", "unknown")
485
+ try:
486
+ event_name = EventType(event_str)
487
+ except ValueError:
488
+ event_name = EventType.UNKNOWN
489
+
490
+ # Parse runner environment
491
+ runner_str = payload.get("runner_environment", "unknown")
492
+ try:
493
+ runner_env = RunnerEnvironment(runner_str)
494
+ except ValueError:
495
+ runner_env = RunnerEnvironment.UNKNOWN
496
+
497
+ # Known claim names
498
+ known_claims = {
499
+ "iss", "sub", "aud", "exp", "iat", "nbf", "jti",
500
+ "repository", "repository_owner", "repository_owner_id",
501
+ "repository_id", "repository_visibility",
502
+ "actor", "actor_id",
503
+ "workflow", "workflow_ref", "workflow_sha",
504
+ "job_workflow_ref", "job_workflow_sha",
505
+ "ref", "ref_type", "sha", "head_ref", "base_ref",
506
+ "run_id", "run_number", "run_attempt", "event_name",
507
+ "environment", "environment_node_id", "runner_environment",
508
+ }
509
+
510
+ # Collect extra claims
511
+ extra = {k: v for k, v in payload.items() if k not in known_claims}
512
+
513
+ return GitHubActionsClaims(
514
+ issuer=issuer,
515
+ subject=subject,
516
+ audience=audience,
517
+ expiration=expiration,
518
+ issued_at=issued_at,
519
+ not_before=not_before,
520
+ jwt_id=payload.get("jti"),
521
+ repository=payload.get("repository", ""),
522
+ repository_owner=payload.get("repository_owner", ""),
523
+ repository_owner_id=str(payload.get("repository_owner_id", "")),
524
+ repository_id=str(payload.get("repository_id", "")),
525
+ repository_visibility=visibility,
526
+ actor=payload.get("actor", ""),
527
+ actor_id=str(payload.get("actor_id", "")),
528
+ workflow=payload.get("workflow", ""),
529
+ workflow_ref=payload.get("workflow_ref", ""),
530
+ workflow_sha=payload.get("workflow_sha", ""),
531
+ job_workflow_ref=payload.get("job_workflow_ref"),
532
+ job_workflow_sha=payload.get("job_workflow_sha"),
533
+ ref=payload.get("ref", ""),
534
+ ref_type=ref_type,
535
+ sha=payload.get("sha", ""),
536
+ head_ref=payload.get("head_ref"),
537
+ base_ref=payload.get("base_ref"),
538
+ run_id=str(payload.get("run_id", "")),
539
+ run_number=str(payload.get("run_number", "")),
540
+ run_attempt=str(payload.get("run_attempt", "")),
541
+ event_name=event_name,
542
+ environment=payload.get("environment"),
543
+ environment_node_id=payload.get("environment_node_id"),
544
+ runner_environment=runner_env,
545
+ extra=extra,
546
+ )
547
+
548
+
549
+ @dataclass
550
+ class ClaimsValidationResult:
551
+ """Result of claims validation."""
552
+
553
+ is_valid: bool
554
+ errors: list[str] = field(default_factory=list)
555
+ warnings: list[str] = field(default_factory=list)
556
+
557
+ def __bool__(self) -> bool:
558
+ return self.is_valid
559
+
560
+
561
+ @dataclass
562
+ class ClaimsValidationPolicy:
563
+ """Policy for validating GitHub Actions claims.
564
+
565
+ Attributes:
566
+ allowed_repositories: List of allowed repository patterns.
567
+ allowed_branches: List of allowed branch patterns.
568
+ allowed_tags: List of allowed tag patterns.
569
+ allowed_actors: List of allowed actors.
570
+ allowed_events: List of allowed event types.
571
+ allowed_environments: List of allowed environment names.
572
+ require_environment: Require a deployment environment.
573
+ allow_pull_requests: Allow pull request events.
574
+ allow_forks: Allow forked repositories.
575
+ require_github_hosted: Require GitHub-hosted runners.
576
+ allowed_workflows: List of allowed workflow patterns.
577
+ """
578
+
579
+ allowed_repositories: list[str] | None = None
580
+ allowed_branches: list[str] | None = None
581
+ allowed_tags: list[str] | None = None
582
+ allowed_actors: list[str] | None = None
583
+ allowed_events: list[EventType] | None = None
584
+ allowed_environments: list[str] | None = None
585
+ require_environment: bool = False
586
+ allow_pull_requests: bool = True
587
+ allow_forks: bool = False
588
+ require_github_hosted: bool = False
589
+ allowed_workflows: list[str] | None = None
590
+
591
+
592
+ def validate_claims(
593
+ claims: GitHubActionsClaims,
594
+ policy: ClaimsValidationPolicy | None = None,
595
+ ) -> ClaimsValidationResult:
596
+ """Validate GitHub Actions claims against a policy.
597
+
598
+ Args:
599
+ claims: Parsed claims to validate.
600
+ policy: Validation policy (uses defaults if None).
601
+
602
+ Returns:
603
+ ClaimsValidationResult with errors and warnings.
604
+ """
605
+ if policy is None:
606
+ policy = ClaimsValidationPolicy()
607
+
608
+ errors: list[str] = []
609
+ warnings: list[str] = []
610
+
611
+ # Check expiration
612
+ if claims.is_expired:
613
+ errors.append("Token is expired")
614
+
615
+ # Check issuer
616
+ if claims.issuer != "https://token.actions.githubusercontent.com":
617
+ errors.append(f"Invalid issuer: {claims.issuer}")
618
+
619
+ # Check repository
620
+ if policy.allowed_repositories:
621
+ if not any(
622
+ claims.matches_repository(pattern)
623
+ for pattern in policy.allowed_repositories
624
+ ):
625
+ errors.append(
626
+ f"Repository '{claims.repository}' not in allowed list: "
627
+ f"{policy.allowed_repositories}"
628
+ )
629
+
630
+ # Check branches
631
+ if policy.allowed_branches and claims.branch_name:
632
+ branch_patterns = [f"refs/heads/{b}" for b in policy.allowed_branches]
633
+ if not any(claims.matches_ref(pattern) for pattern in branch_patterns):
634
+ errors.append(
635
+ f"Branch '{claims.branch_name}' not in allowed list: "
636
+ f"{policy.allowed_branches}"
637
+ )
638
+
639
+ # Check tags
640
+ if policy.allowed_tags and claims.tag_name:
641
+ tag_patterns = [f"refs/tags/{t}" for t in policy.allowed_tags]
642
+ if not any(claims.matches_ref(pattern) for pattern in tag_patterns):
643
+ errors.append(
644
+ f"Tag '{claims.tag_name}' not in allowed list: "
645
+ f"{policy.allowed_tags}"
646
+ )
647
+
648
+ # Check actors
649
+ if policy.allowed_actors:
650
+ if claims.actor and claims.actor not in policy.allowed_actors:
651
+ errors.append(
652
+ f"Actor '{claims.actor}' not in allowed list: "
653
+ f"{policy.allowed_actors}"
654
+ )
655
+
656
+ # Check events
657
+ if policy.allowed_events:
658
+ if claims.event_name not in policy.allowed_events:
659
+ errors.append(
660
+ f"Event '{claims.event_name.value}' not in allowed list: "
661
+ f"{[e.value for e in policy.allowed_events]}"
662
+ )
663
+
664
+ # Check environments
665
+ if policy.require_environment and not claims.environment:
666
+ errors.append("Deployment environment is required but not present")
667
+
668
+ if policy.allowed_environments and claims.environment:
669
+ if claims.environment not in policy.allowed_environments:
670
+ errors.append(
671
+ f"Environment '{claims.environment}' not in allowed list: "
672
+ f"{policy.allowed_environments}"
673
+ )
674
+
675
+ # Check pull requests
676
+ if not policy.allow_pull_requests and claims.is_pull_request:
677
+ errors.append("Pull request events are not allowed")
678
+
679
+ # Check forks
680
+ if not policy.allow_forks:
681
+ if claims.repository_visibility == RepositoryVisibility.PUBLIC:
682
+ # For public repos, check if head_ref suggests a fork
683
+ if claims.head_ref and ":" in claims.head_ref:
684
+ errors.append("Forked repository events are not allowed")
685
+
686
+ # Check runner environment
687
+ if policy.require_github_hosted and not claims.is_github_hosted:
688
+ errors.append("GitHub-hosted runners are required")
689
+
690
+ # Check workflows
691
+ if policy.allowed_workflows:
692
+ workflow_match = False
693
+ for pattern in policy.allowed_workflows:
694
+ if claims.workflow_ref:
695
+ regex_pattern = pattern.replace("*", ".*")
696
+ if re.match(f"^{regex_pattern}$", claims.workflow_ref):
697
+ workflow_match = True
698
+ break
699
+ if not workflow_match:
700
+ errors.append(
701
+ f"Workflow '{claims.workflow_ref}' not in allowed list: "
702
+ f"{policy.allowed_workflows}"
703
+ )
704
+
705
+ # Add warnings
706
+ if claims.is_pull_request:
707
+ warnings.append("Token was issued for a pull request event")
708
+
709
+ if claims.is_reusable_workflow:
710
+ warnings.append(
711
+ f"Token was issued for a reusable workflow: {claims.job_workflow_ref}"
712
+ )
713
+
714
+ return ClaimsValidationResult(
715
+ is_valid=len(errors) == 0,
716
+ errors=errors,
717
+ warnings=warnings,
718
+ )