sourcecode 4.8.0__tar.gz → 4.9.1__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 (217) hide show
  1. {sourcecode-4.8.0 → sourcecode-4.9.1}/CHANGELOG.md +40 -0
  2. {sourcecode-4.8.0 → sourcecode-4.9.1}/PKG-INFO +24 -12
  3. {sourcecode-4.8.0 → sourcecode-4.9.1}/README.md +23 -11
  4. {sourcecode-4.8.0 → sourcecode-4.9.1}/pyproject.toml +1 -1
  5. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/__init__.py +1 -1
  6. sourcecode-4.9.1/src/sourcecode/audit_report.py +158 -0
  7. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/cli.py +287 -18
  8. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/environment_resolution.py +88 -6
  9. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/migrate_check.py +307 -1
  10. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/non_coverage.py +12 -10
  11. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/posture.py +2 -1
  12. sourcecode-4.9.1/src/sourcecode/provenance.py +202 -0
  13. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/risk.py +234 -16
  14. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/rule_catalog.py +6 -1
  15. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/sarif.py +12 -0
  16. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/spring_security_audit.py +338 -0
  17. {sourcecode-4.8.0 → sourcecode-4.9.1}/.github/workflows/build-windows.yml +0 -0
  18. {sourcecode-4.8.0 → sourcecode-4.9.1}/.gitignore +0 -0
  19. {sourcecode-4.8.0 → sourcecode-4.9.1}/.ruff.toml +0 -0
  20. {sourcecode-4.8.0 → sourcecode-4.9.1}/CLAUDE.md +0 -0
  21. {sourcecode-4.8.0 → sourcecode-4.9.1}/CONTRIBUTING.md +0 -0
  22. {sourcecode-4.8.0 → sourcecode-4.9.1}/LICENSE +0 -0
  23. {sourcecode-4.8.0 → sourcecode-4.9.1}/SECURITY.md +0 -0
  24. {sourcecode-4.8.0 → sourcecode-4.9.1}/raw +0 -0
  25. {sourcecode-4.8.0 → sourcecode-4.9.1}/scripts/compare_integration_engines.py +0 -0
  26. {sourcecode-4.8.0 → sourcecode-4.9.1}/scripts/customer_smoke_test.sh +0 -0
  27. {sourcecode-4.8.0 → sourcecode-4.9.1}/scripts/generate_jdk_exports.py +0 -0
  28. {sourcecode-4.8.0 → sourcecode-4.9.1}/scripts/perf_harness.py +0 -0
  29. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/adaptive_scanner.py +0 -0
  30. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/archetype.py +0 -0
  31. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/architectural_baseline.py +0 -0
  32. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/architectural_delta.py +0 -0
  33. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/architecture_analyzer.py +0 -0
  34. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/architecture_summary.py +0 -0
  35. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/ast_extractor.py +0 -0
  36. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/baseline_autocapture.py +0 -0
  37. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/cache.py +0 -0
  38. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/cache_model.py +0 -0
  39. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/call_surface.py +0 -0
  40. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/caller_metrics.py +0 -0
  41. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/caller_reach.py +0 -0
  42. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/canonical_ir.py +0 -0
  43. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/chain_rules.py +0 -0
  44. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/change_plan.py +0 -0
  45. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/cir_graphs.py +0 -0
  46. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/classifier.py +0 -0
  47. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/client_calls.py +0 -0
  48. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/code_notes_analyzer.py +0 -0
  49. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/compare.py +0 -0
  50. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/confidence_analyzer.py +0 -0
  51. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/constraint_diff.py +0 -0
  52. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/context_cache.py +0 -0
  53. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/context_graph.py +0 -0
  54. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/context_scorer.py +0 -0
  55. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/context_summarizer.py +0 -0
  56. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/contract_diff.py +0 -0
  57. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/contract_init.py +0 -0
  58. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/contract_model.py +0 -0
  59. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/contract_pipeline.py +0 -0
  60. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/coverage_parser.py +0 -0
  61. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/data_exposure.py +0 -0
  62. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/data_labels.py +0 -0
  63. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/defect_identity.py +0 -0
  64. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/degradation.py +0 -0
  65. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/dependency_analyzer.py +0 -0
  66. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/deployment_prefix.py +0 -0
  67. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/__init__.py +0 -0
  68. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/base.py +0 -0
  69. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/csproj_parser.py +0 -0
  70. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/dart.py +0 -0
  71. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/dotnet.py +0 -0
  72. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/elixir.py +0 -0
  73. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/go.py +0 -0
  74. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/heuristic.py +0 -0
  75. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/hybrid.py +0 -0
  76. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/java.py +0 -0
  77. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/jvm_ext.py +0 -0
  78. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/nodejs.py +0 -0
  79. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/parsers.py +0 -0
  80. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/php.py +0 -0
  81. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/project.py +0 -0
  82. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/python.py +0 -0
  83. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/ruby.py +0 -0
  84. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/rust.py +0 -0
  85. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/systems.py +0 -0
  86. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/terraform.py +0 -0
  87. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/detectors/tooling.py +0 -0
  88. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/doc_analyzer.py +0 -0
  89. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/dynamic_argument_surface.py +0 -0
  90. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/endpoint_literals.py +0 -0
  91. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/endpoint_metrics.py +0 -0
  92. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/entrypoint_classifier.py +0 -0
  93. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/env_analyzer.py +0 -0
  94. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/envelope.py +0 -0
  95. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/error_schema.py +0 -0
  96. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/evidence_provider.py +0 -0
  97. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/explain.py +0 -0
  98. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/facts/__init__.py +0 -0
  99. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/facts/registry.json +0 -0
  100. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/file_chunker.py +0 -0
  101. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/file_classifier.py +0 -0
  102. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/filter_surface.py +0 -0
  103. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/format_contract.py +0 -0
  104. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/fqn_utils.py +0 -0
  105. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/git_analyzer.py +0 -0
  106. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/git_checkout.py +0 -0
  107. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/graph_analyzer.py +0 -0
  108. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/graph_evidence.py +0 -0
  109. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/hibernate_strat.py +0 -0
  110. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/identity_fallback.py +0 -0
  111. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/integration_coordinates.py +0 -0
  112. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/jdk_exports.py +0 -0
  113. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/license.py +0 -0
  114. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/mcp/__init__.py +0 -0
  115. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  116. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  117. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  118. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  119. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  120. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/mcp/orchestrator.py +0 -0
  121. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/mcp/registry.py +0 -0
  122. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/mcp/runner.py +0 -0
  123. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/mcp/server.py +0 -0
  124. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/mcp_nudge.py +0 -0
  125. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/metrics_analyzer.py +0 -0
  126. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/migration_blast.py +0 -0
  127. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/openapi_surface.py +0 -0
  128. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/openrewrite_recipe.py +0 -0
  129. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/output_budget.py +0 -0
  130. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/parse_cache.py +0 -0
  131. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/path_admission.py +0 -0
  132. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/path_filters.py +0 -0
  133. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/perf.py +0 -0
  134. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/pipe_contract.py +0 -0
  135. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/pr_comment_renderer.py +0 -0
  136. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/pr_impact.py +0 -0
  137. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/prepare_context.py +0 -0
  138. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/progress.py +0 -0
  139. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/ranking_engine.py +0 -0
  140. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/readiness_timeline.py +0 -0
  141. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/reconciliation.py +0 -0
  142. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/redactor.py +0 -0
  143. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/reference_facts.py +0 -0
  144. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/release_info.py +0 -0
  145. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/relevance_scorer.py +0 -0
  146. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/remedies.py +0 -0
  147. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/rename_refactor.py +0 -0
  148. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/repo_classifier.py +0 -0
  149. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/repository_ir.py +0 -0
  150. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/__init__.py +0 -0
  151. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/context.py +0 -0
  152. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/errors.py +0 -0
  153. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/executor.py +0 -0
  154. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/planner.py +0 -0
  155. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/query.py +0 -0
  156. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/request.py +0 -0
  157. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/resolution.py +0 -0
  158. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/result.py +0 -0
  159. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/retriever.py +0 -0
  160. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/runtime.py +0 -0
  161. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/steps.py +0 -0
  162. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
  163. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/steps_graph.py +0 -0
  164. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/steps_impact.py +0 -0
  165. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/steps_intf.py +0 -0
  166. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/steps_struct.py +0 -0
  167. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/retrieval/steps_txsec.py +0 -0
  168. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/ris.py +0 -0
  169. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/runtime_classifier.py +0 -0
  170. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/scanner.py +0 -0
  171. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/schema.py +0 -0
  172. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
  173. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/security_config.py +0 -0
  174. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/security_config_scan.py +0 -0
  175. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/security_posture.py +0 -0
  176. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/semantic_analyzer.py +0 -0
  177. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/semantic_impact_engine.py +0 -0
  178. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/semantic_integration_engine.py +0 -0
  179. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/semantic_services.py +0 -0
  180. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/serializer.py +0 -0
  181. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/servlet_surface.py +0 -0
  182. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/source_text.py +0 -0
  183. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/spring_event_topology.py +0 -0
  184. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/spring_findings.py +0 -0
  185. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/spring_impact.py +0 -0
  186. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/spring_model.py +0 -0
  187. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/spring_profiles.py +0 -0
  188. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/spring_properties.py +0 -0
  189. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/spring_semantic.py +0 -0
  190. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/spring_tx_analyzer.py +0 -0
  191. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/summarizer.py +0 -0
  192. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/target_admission.py +0 -0
  193. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/telemetry/__init__.py +0 -0
  194. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/telemetry/config.py +0 -0
  195. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/telemetry/consent.py +0 -0
  196. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/telemetry/events.py +0 -0
  197. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/telemetry/filters.py +0 -0
  198. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/telemetry/transport.py +0 -0
  199. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/test_gap_ranking.py +0 -0
  200. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/test_sources.py +0 -0
  201. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/token_estimate.py +0 -0
  202. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/tree_utils.py +0 -0
  203. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/type_usage_surface.py +0 -0
  204. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/validation_inference.py +0 -0
  205. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/validation_surface.py +0 -0
  206. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/verify_edit.py +0 -0
  207. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/verify_repo.py +0 -0
  208. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/verify_rules.py +0 -0
  209. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/version_check.py +0 -0
  210. {sourcecode-4.8.0 → sourcecode-4.9.1}/src/sourcecode/workspace.py +0 -0
  211. {sourcecode-4.8.0 → sourcecode-4.9.1}/supabase/functions/README.md +0 -0
  212. {sourcecode-4.8.0 → sourcecode-4.9.1}/supabase/functions/get-license/index.ts +0 -0
  213. {sourcecode-4.8.0 → sourcecode-4.9.1}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  214. {sourcecode-4.8.0 → sourcecode-4.9.1}/supabase/functions/telemetry/index.ts +0 -0
  215. {sourcecode-4.8.0 → sourcecode-4.9.1}/supabase/sql/license_event_ordering.sql +0 -0
  216. {sourcecode-4.8.0 → sourcecode-4.9.1}/supabase/sql/licensing_schema.sql +0 -0
  217. {sourcecode-4.8.0 → sourcecode-4.9.1}/supabase/sql/telemetry_events.sql +0 -0
@@ -2,6 +2,46 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [4.9.1] — 2026-08-04
6
+
7
+ ### Added
8
+
9
+ - **Java LTS/licensing inventory in `migrate-check`.** Reports Java 8/11/17/21/25
10
+ evidence from Maven/Gradle, local runtime hints and container files, target-LTS
11
+ blockers via `--target-jdk`, and explicit Oracle JDK licensing-review signals
12
+ without changing migration readiness scoring.
13
+ - **Claim provenance ledger.** `risk`, `enrich`, `migrate-check`, `audit-report`
14
+ and `prepare-context` now emit `evidence_manifest` with stable claim IDs,
15
+ source paths/lines, command inputs, ASK version, git HEAD and freshness metadata.
16
+
17
+ ## [4.9.0] — 2026-08-04
18
+
19
+ ### Added
20
+
21
+ - **Custom AOP security gate audit.** `spring-audit` now emits `GATE-001` through
22
+ `GATE-004` for custom authorization gates detected by the security posture
23
+ authority: Spring AOP proxy bypass, fail-open advice, disabled/tautological
24
+ annotation attributes, and fragile positional/reflection binding.
25
+ - **Deployment evidence for runtime posture.** `posture --resolve-environments`
26
+ accepts `--env-file FILE` and binds explicit deployment profile evidence to
27
+ `decided_case` while keeping repository defaults as lower-priority evidence.
28
+ - **Bounded HTTP-input-to-sink flow in `risk`.** The `query_construction` factor
29
+ now distinguishes a proven bounded path from annotated HTTP input, through
30
+ positional calls in repository Java sources, into known concatenated query
31
+ sinks. General taint remains explicitly outside scope.
32
+ - **SARIF triage table for `enrich`.** `enrich --table` now provides
33
+ auditor-facing filtering by scanner rule, composed band and top-N while
34
+ leaving JSON as the contract.
35
+ - **Signed audit report bundle.** New experimental `audit-report` command packages
36
+ existing `risk` and `posture` evidence into JSON or Markdown, with optional
37
+ HMAC-SHA256 signing over the canonical JSON payload via `--sign-key`.
38
+
39
+ ### Documentation
40
+
41
+ - README, user guide and root `ask --help` now list `audit-report`, the 4.9.0
42
+ version, `posture --env-file`, `enrich --table`, bounded `risk` flow and the
43
+ `GATE-*` rule family.
44
+
5
45
  ## [4.8.0] — 2026-08-04
6
46
 
7
47
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 4.8.0
3
+ Version: 4.9.1
4
4
  Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
5
5
  License-File: LICENSE
6
6
  Keywords: agents,ai,codebase,context,developer-tools,llm
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
42
42
 
43
43
  **Context · Impact · Migration · Architecture · Review — everything from one structural model.**
44
44
 
45
- ![Version](https://img.shields.io/badge/version-4.8.0-blue)
45
+ ![Version](https://img.shields.io/badge/version-4.9.1-blue)
46
46
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
47
47
 
48
48
  > **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
@@ -97,7 +97,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
97
97
  # pip / pipx
98
98
  pipx install sourcecode # or: pip install sourcecode
99
99
 
100
- ask version # ask 4.8.0 — and, on a build that has aged,
100
+ ask version # ask 4.9.1 — and, on a build that has aged,
101
101
  # how many releases have probably shipped since
102
102
  ```
103
103
 
@@ -137,8 +137,9 @@ ask endpoints /path/to/repo
137
137
  # CGLIB no-op), security surface, request-body validation.
138
138
  ask spring-audit /path/to/repo
139
139
 
140
- # Spring Boot 2→3 readiness: located blockers, per-dimension score, effort estimate.
140
+ # Spring Boot 2→3 readiness plus Java LTS/licensing inventory.
141
141
  ask migrate-check /path/to/repo --compact
142
+ # Add --target-jdk 25 to make the LTS route explicit.
142
143
  ```
143
144
 
144
145
  **Then the three that finish the sentence the four above start.** A profile-set answer stays
@@ -260,10 +261,10 @@ figures and the authority behind each — and an axis this build cannot measure
260
261
  weighted 1.0 and named in `blind_axes` rather than silently treated as safe. Measured on a
261
262
  field case: a defect both `spring-audit` and `impact-chain` called *medium* composes to
262
263
  **high (8.06)** once *reachable unauthenticated* and *writes to the database* are in it.
263
- The last two factors describe the input path a query assembled by concatenation, a route
264
- accepting a body with no declared constraint. They are **adjacencies, not dataflow**: no
265
- value is followed from a request to a sink, which is `NC-001` and is published in the
266
- payload's own `non_coverage` block.
264
+ The last two factors describe the input path: a query assembled by concatenation, a bounded
265
+ HTTP-input-to-query-sink path when ASK can prove one, and a route accepting a body with no
266
+ declared constraint. General taint remains `NC-001` and is published in the payload's own
267
+ `non_coverage` block.
267
268
  `ask risk .` · `ask risk . --min-band high` · `ask risk . --limit 10`
268
269
  → [reference](docs/USER_GUIDE.md)
269
270
 
@@ -289,7 +290,7 @@ experimental: both are true, and they are two different facts.
289
290
  |---|---|---|
290
291
  | **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
291
292
  | **supported** | maintained; fields are added, never removed without a major | every command not named in another row |
292
- | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `data-exposure` · `migrate-recipe` · `posture` · `archetype` |
293
+ | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `posture` · `archetype` |
293
294
  | **parked** | kept working, no longer developed | `retrieve` |
294
295
 
295
296
  The same table is printed by `ask --help`, and both are generated from one authority
@@ -307,12 +308,13 @@ from it.
307
308
  |---|---|---|---|
308
309
  | `posture` | experimental | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
309
310
  | `risk` | experimental | what each defect actually costs, once reach, access, write effect and the shape of the input path are in it | `defect_severity × reachability × auth_verdict × write_effect × query_construction × input_constraints`; every factor names its authority; `--table --rule SEC-008 --band high --top-n 20` gives audit triage without `jq` |
310
- | `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`; the same composition as `risk`, with the scanner as the severity authority |
311
+ | `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`; same composition as `risk`, with `--table --rule <id> --band high --top-n 20` for triage |
312
+ | `audit-report` | experimental | human audit bundle over existing `risk` + `posture` evidence, optionally signed | includes `evidence_manifest` claim provenance; `--format markdown`; `--sign-key <file>` signs canonical JSON with HMAC-SHA256 |
311
313
  | `migrate-recipe` | experimental | the migration report as the OpenRewrite recipe that applies it | only recipes a finding named; the manual remainder published beside them; writes nothing without `--write`, and never a runnable command for an empty recipe list |
312
314
  | `data-exposure` | experimental | which routes can carry the data you labelled, and who reaches them | labels declared in `sourcecode.config.json` — never inferred from a name; `signature` and `call_reach` evidence published apart, field-level flow out of scope (NC-008). With nothing declared, `ask data-exposure /path/to/repo` answers `answered: false` and hands back the file, the key and an example to declare — it never reports zero exposed routes |
313
315
  | `endpoints` | core | every REST endpoint, effective path, security policy, confidence | Spring MVC + JAX-RS (~65 % recall on JAX-RS sub-resource locators). `--compact` answers the exposure census without the rows; `--servlets` lists the servlet-mounted surface as its own population; `--client-usage` says which routes the TS/JS client in this repository actually calls |
314
316
  | `spring-audit` | core | transactional anomalies + security surface + validation gaps | `--ci`, `-f github-comment`; `--table --rule SEC-008 --top-n 20` for human-scale review |
315
- | `migrate-check` | core | Boot 2→3 readiness: located blockers, per-dimension score, effort | `--blast-radius` orders the re-test plan; `--table --rule MIG-001 --band critical --top-n 20` for blocker triage |
317
+ | `migrate-check` | core | Boot 2→3 readiness + Java LTS/licensing inventory: located blockers, per-dimension score, effort, detected Java 8/11/17/21/25 evidence and explicit licensing-review signals | `--target-jdk 25` sets the target LTS route; `--blast-radius` orders the re-test plan; `--table --rule MIG-001 --band critical --top-n 20` for blocker triage |
316
318
  | `impact` / `impact-chain` | core | blast radius of a change, to the endpoints it reaches | target the **interface**, not the `Impl` |
317
319
  | `pr-impact` | core | the same, scoped to a PR diff | gating command: `--fail-on`, exit codes |
318
320
  | `verify` | core | does the repo satisfy its declared contracts, **relative to a baseline** | `.ask/contracts.yml`; exit 0/1/2 |
@@ -356,7 +358,7 @@ reading JSON sees the same boundary a buyer reads here.
356
358
 
357
359
  | Not covered | Why | What answers it |
358
360
  |---|---|---|
359
- | **Whether request input reaches a sink no dataflow or taint analysis.** | This engine resolves structure and wiring without compiling. Taint needs value flow through a program, which is a different analysis with a different failure mode: an unsound one produces confident findings that are wrong, and every claim here is meant to be checkable against the line that produced it. | A dataflow scanner (Semgrep, CodeQL). What this product adds on top is reachability: which of that tool's findings sit behind an endpoint that is reachable unauthenticated. |
361
+ | **General request-input-to-sink taint analysis.** | `ask risk` includes a bounded slice for annotated HTTP parameters, positional calls in repository Java sources and known query sinks. Anything broader needs value flow through a program, which is a different analysis with a different failure mode: an unsound one produces confident findings that are wrong, and every claim here is meant to be checkable against the line that produced it. | A dataflow scanner (Semgrep, CodeQL) for complete taint. What this product adds on top is reachability and, for the bounded slice, whether an annotated HTTP input reaches a known concatenated query sink. |
360
362
  | **Secrets outside Java, Spring configuration and the deployment descriptors — a Helm value, a CI variable file, a shell script.** | The file population this analyzer reads is the Java source, the Spring configuration convention and the descriptors it already parses to resolve an environment. A secret elsewhere is not missed by a weak rule; it is outside the set of files anything here opens. Narrowed by CL-10: a credential stored in `web.xml` or a Spring XML context IS reported (SEC-007), because those files were already being read. | A dedicated secret scanner over the whole tree (gitleaks, trufflehog). |
361
363
  | **Filter-chain order and per-filter URL patterns — the presence of a custom filter is structural only.** | Which filter runs first is decided by bean ordering this analyzer does not resolve. Where two active configurations both match a request, the answer published is `undecided` rather than a guess. | `ask posture --profile <set>` states per endpoint what the readable rules decide and what they leave undecided. |
362
364
  | **Known vulnerabilities in dependencies — no CVE database, no version advisory matching.** | Enriching a vulnerability feed is a different product with a different update cadence; a stale embedded database is worse than no database, because it reads as a clean bill of health. | A dependency scanner (Trivy, OWASP Dependency-Check). `impact-chain` then answers which of its findings anything actually reaches. |
@@ -400,6 +402,16 @@ and that gap is the honest description, not a defect to argue with. `migrate-che
400
402
  the OpenRewrite recipe each finding carries so the executor that does apply changes has its
401
403
  input.
402
404
 
405
+ **Java LTS/licensing inventory.** `migrate-check` emits `java_lts_inventory` beside the migration
406
+ scores. It reads Maven/Gradle, local runtime hints and container files for Java 8/11/17/21/25
407
+ evidence, reports target-LTS blockers with `--target-jdk`, and marks explicit Oracle JDK evidence
408
+ as `licensing_review_needed`. This is inventory evidence, not legal advice.
409
+
410
+ **Claim provenance ledger.** JSON outputs from `risk`, `enrich`, `migrate-check`,
411
+ `audit-report` and `prepare-context` include `evidence_manifest`: stable claim IDs mapped to
412
+ source paths/lines, command inputs, ASK version, git HEAD and freshness metadata. The manifest
413
+ indexes claims already in the payload; it does not add analysis or certify compliance.
414
+
403
415
 
404
416
  ---
405
417
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  **Context · Impact · Migration · Architecture · Review — everything from one structural model.**
6
6
 
7
- ![Version](https://img.shields.io/badge/version-4.8.0-blue)
7
+ ![Version](https://img.shields.io/badge/version-4.9.1-blue)
8
8
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
9
9
 
10
10
  > **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
@@ -59,7 +59,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
59
59
  # pip / pipx
60
60
  pipx install sourcecode # or: pip install sourcecode
61
61
 
62
- ask version # ask 4.8.0 — and, on a build that has aged,
62
+ ask version # ask 4.9.1 — and, on a build that has aged,
63
63
  # how many releases have probably shipped since
64
64
  ```
65
65
 
@@ -99,8 +99,9 @@ ask endpoints /path/to/repo
99
99
  # CGLIB no-op), security surface, request-body validation.
100
100
  ask spring-audit /path/to/repo
101
101
 
102
- # Spring Boot 2→3 readiness: located blockers, per-dimension score, effort estimate.
102
+ # Spring Boot 2→3 readiness plus Java LTS/licensing inventory.
103
103
  ask migrate-check /path/to/repo --compact
104
+ # Add --target-jdk 25 to make the LTS route explicit.
104
105
  ```
105
106
 
106
107
  **Then the three that finish the sentence the four above start.** A profile-set answer stays
@@ -222,10 +223,10 @@ figures and the authority behind each — and an axis this build cannot measure
222
223
  weighted 1.0 and named in `blind_axes` rather than silently treated as safe. Measured on a
223
224
  field case: a defect both `spring-audit` and `impact-chain` called *medium* composes to
224
225
  **high (8.06)** once *reachable unauthenticated* and *writes to the database* are in it.
225
- The last two factors describe the input path a query assembled by concatenation, a route
226
- accepting a body with no declared constraint. They are **adjacencies, not dataflow**: no
227
- value is followed from a request to a sink, which is `NC-001` and is published in the
228
- payload's own `non_coverage` block.
226
+ The last two factors describe the input path: a query assembled by concatenation, a bounded
227
+ HTTP-input-to-query-sink path when ASK can prove one, and a route accepting a body with no
228
+ declared constraint. General taint remains `NC-001` and is published in the payload's own
229
+ `non_coverage` block.
229
230
  `ask risk .` · `ask risk . --min-band high` · `ask risk . --limit 10`
230
231
  → [reference](docs/USER_GUIDE.md)
231
232
 
@@ -251,7 +252,7 @@ experimental: both are true, and they are two different facts.
251
252
  |---|---|---|
252
253
  | **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
253
254
  | **supported** | maintained; fields are added, never removed without a major | every command not named in another row |
254
- | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `data-exposure` · `migrate-recipe` · `posture` · `archetype` |
255
+ | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `posture` · `archetype` |
255
256
  | **parked** | kept working, no longer developed | `retrieve` |
256
257
 
257
258
  The same table is printed by `ask --help`, and both are generated from one authority
@@ -269,12 +270,13 @@ from it.
269
270
  |---|---|---|---|
270
271
  | `posture` | experimental | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
271
272
  | `risk` | experimental | what each defect actually costs, once reach, access, write effect and the shape of the input path are in it | `defect_severity × reachability × auth_verdict × write_effect × query_construction × input_constraints`; every factor names its authority; `--table --rule SEC-008 --band high --top-n 20` gives audit triage without `jq` |
272
- | `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`; the same composition as `risk`, with the scanner as the severity authority |
273
+ | `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`; same composition as `risk`, with `--table --rule <id> --band high --top-n 20` for triage |
274
+ | `audit-report` | experimental | human audit bundle over existing `risk` + `posture` evidence, optionally signed | includes `evidence_manifest` claim provenance; `--format markdown`; `--sign-key <file>` signs canonical JSON with HMAC-SHA256 |
273
275
  | `migrate-recipe` | experimental | the migration report as the OpenRewrite recipe that applies it | only recipes a finding named; the manual remainder published beside them; writes nothing without `--write`, and never a runnable command for an empty recipe list |
274
276
  | `data-exposure` | experimental | which routes can carry the data you labelled, and who reaches them | labels declared in `sourcecode.config.json` — never inferred from a name; `signature` and `call_reach` evidence published apart, field-level flow out of scope (NC-008). With nothing declared, `ask data-exposure /path/to/repo` answers `answered: false` and hands back the file, the key and an example to declare — it never reports zero exposed routes |
275
277
  | `endpoints` | core | every REST endpoint, effective path, security policy, confidence | Spring MVC + JAX-RS (~65 % recall on JAX-RS sub-resource locators). `--compact` answers the exposure census without the rows; `--servlets` lists the servlet-mounted surface as its own population; `--client-usage` says which routes the TS/JS client in this repository actually calls |
276
278
  | `spring-audit` | core | transactional anomalies + security surface + validation gaps | `--ci`, `-f github-comment`; `--table --rule SEC-008 --top-n 20` for human-scale review |
277
- | `migrate-check` | core | Boot 2→3 readiness: located blockers, per-dimension score, effort | `--blast-radius` orders the re-test plan; `--table --rule MIG-001 --band critical --top-n 20` for blocker triage |
279
+ | `migrate-check` | core | Boot 2→3 readiness + Java LTS/licensing inventory: located blockers, per-dimension score, effort, detected Java 8/11/17/21/25 evidence and explicit licensing-review signals | `--target-jdk 25` sets the target LTS route; `--blast-radius` orders the re-test plan; `--table --rule MIG-001 --band critical --top-n 20` for blocker triage |
278
280
  | `impact` / `impact-chain` | core | blast radius of a change, to the endpoints it reaches | target the **interface**, not the `Impl` |
279
281
  | `pr-impact` | core | the same, scoped to a PR diff | gating command: `--fail-on`, exit codes |
280
282
  | `verify` | core | does the repo satisfy its declared contracts, **relative to a baseline** | `.ask/contracts.yml`; exit 0/1/2 |
@@ -318,7 +320,7 @@ reading JSON sees the same boundary a buyer reads here.
318
320
 
319
321
  | Not covered | Why | What answers it |
320
322
  |---|---|---|
321
- | **Whether request input reaches a sink no dataflow or taint analysis.** | This engine resolves structure and wiring without compiling. Taint needs value flow through a program, which is a different analysis with a different failure mode: an unsound one produces confident findings that are wrong, and every claim here is meant to be checkable against the line that produced it. | A dataflow scanner (Semgrep, CodeQL). What this product adds on top is reachability: which of that tool's findings sit behind an endpoint that is reachable unauthenticated. |
323
+ | **General request-input-to-sink taint analysis.** | `ask risk` includes a bounded slice for annotated HTTP parameters, positional calls in repository Java sources and known query sinks. Anything broader needs value flow through a program, which is a different analysis with a different failure mode: an unsound one produces confident findings that are wrong, and every claim here is meant to be checkable against the line that produced it. | A dataflow scanner (Semgrep, CodeQL) for complete taint. What this product adds on top is reachability and, for the bounded slice, whether an annotated HTTP input reaches a known concatenated query sink. |
322
324
  | **Secrets outside Java, Spring configuration and the deployment descriptors — a Helm value, a CI variable file, a shell script.** | The file population this analyzer reads is the Java source, the Spring configuration convention and the descriptors it already parses to resolve an environment. A secret elsewhere is not missed by a weak rule; it is outside the set of files anything here opens. Narrowed by CL-10: a credential stored in `web.xml` or a Spring XML context IS reported (SEC-007), because those files were already being read. | A dedicated secret scanner over the whole tree (gitleaks, trufflehog). |
323
325
  | **Filter-chain order and per-filter URL patterns — the presence of a custom filter is structural only.** | Which filter runs first is decided by bean ordering this analyzer does not resolve. Where two active configurations both match a request, the answer published is `undecided` rather than a guess. | `ask posture --profile <set>` states per endpoint what the readable rules decide and what they leave undecided. |
324
326
  | **Known vulnerabilities in dependencies — no CVE database, no version advisory matching.** | Enriching a vulnerability feed is a different product with a different update cadence; a stale embedded database is worse than no database, because it reads as a clean bill of health. | A dependency scanner (Trivy, OWASP Dependency-Check). `impact-chain` then answers which of its findings anything actually reaches. |
@@ -362,6 +364,16 @@ and that gap is the honest description, not a defect to argue with. `migrate-che
362
364
  the OpenRewrite recipe each finding carries so the executor that does apply changes has its
363
365
  input.
364
366
 
367
+ **Java LTS/licensing inventory.** `migrate-check` emits `java_lts_inventory` beside the migration
368
+ scores. It reads Maven/Gradle, local runtime hints and container files for Java 8/11/17/21/25
369
+ evidence, reports target-LTS blockers with `--target-jdk`, and marks explicit Oracle JDK evidence
370
+ as `licensing_review_needed`. This is inventory evidence, not legal advice.
371
+
372
+ **Claim provenance ledger.** JSON outputs from `risk`, `enrich`, `migrate-check`,
373
+ `audit-report` and `prepare-context` include `evidence_manifest`: stable claim IDs mapped to
374
+ source paths/lines, command inputs, ASK version, git HEAD and freshness metadata. The manifest
375
+ indexes claims already in the payload; it does not add analysis or certify compliance.
376
+
365
377
 
366
378
  ---
367
379
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "4.8.0"
7
+ version = "4.9.1"
8
8
  description = "Persistent structural context and ultra-fast repeated analysis for AI coding agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -4,4 +4,4 @@ ASK Engine is the product. ``ask`` is the canonical CLI command; ``sourcecode``
4
4
  the legacy compatibility alias and the Python/PyPI package name. See
5
5
  docs/PRODUCT_IDENTITY.md (normative)."""
6
6
 
7
- __version__ = "4.8.0"
7
+ __version__ = "4.9.1"
@@ -0,0 +1,158 @@
1
+ """Signed audit report over existing ASK evidence.
2
+
3
+ This module packages facts other commands already publish. It does not score ROI,
4
+ choose a fix, or introduce a second judgement layer: the report summary is a
5
+ reader-friendly index over the embedded evidence blocks.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import hmac
12
+ import json
13
+ from datetime import datetime, timezone
14
+ from pathlib import Path
15
+ from typing import Any, Optional
16
+
17
+ from sourcecode import __version__
18
+
19
+ AUDIT_REPORT_SCHEMA = "audit-report-v1"
20
+
21
+
22
+ def _canonical_json(data: dict[str, Any]) -> bytes:
23
+ return json.dumps(data, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
24
+
25
+
26
+ def _sign(payload: dict[str, Any], key: bytes) -> dict[str, str]:
27
+ canonical = _canonical_json(payload)
28
+ return {
29
+ "algorithm": "hmac-sha256",
30
+ "payload_sha256": hashlib.sha256(canonical).hexdigest(),
31
+ "key_id": hashlib.sha256(key).hexdigest()[:12],
32
+ "signature": hmac.new(key, canonical, hashlib.sha256).hexdigest(),
33
+ }
34
+
35
+
36
+ def build_audit_report(
37
+ root: Path,
38
+ *,
39
+ profiles: Optional[set[str]] = None,
40
+ sign_key: Optional[bytes] = None,
41
+ risk_limit: int = 10,
42
+ ) -> dict[str, Any]:
43
+ """Build the buyer-readable audit bundle from existing command payloads."""
44
+ from sourcecode.posture import build_posture
45
+ from sourcecode.risk import build_risk
46
+
47
+ root = Path(root).resolve()
48
+ risk = build_risk(root, limit=risk_limit, min_band="low", profiles=profiles)
49
+ posture = build_posture(root, profiles or set())
50
+ top_risks = risk.get("risks", [])[:risk_limit]
51
+ access = ((posture.get("endpoints") or {}).get("effective_access") or {})
52
+
53
+ unsigned: dict[str, Any] = {
54
+ "schema_version": AUDIT_REPORT_SCHEMA,
55
+ "tool": {"name": "ask", "version": __version__},
56
+ "generated_at": datetime.now(timezone.utc).isoformat(),
57
+ "repository": {"path": str(root)},
58
+ **({"profile_set": sorted(profiles)} if profiles else {}),
59
+ "summary": {
60
+ "risk_model": risk.get("model"),
61
+ "total_defects": risk.get("total_defects"),
62
+ "total_findings": risk.get("total_findings"),
63
+ "risk_bands": risk.get("by_band", {}),
64
+ "top_risks_shown": len(top_risks),
65
+ "endpoint_access": access.get("summary", {}),
66
+ "unresolved_beans": len(posture.get("unresolved") or []),
67
+ },
68
+ "top_risks": top_risks,
69
+ "evidence": {
70
+ "risk": risk,
71
+ "posture": posture,
72
+ },
73
+ "limits": {
74
+ "statement": (
75
+ "This report packages existing ASK evidence. It does not certify "
76
+ "compliance, choose fixes, assign ROI, or replace a human audit decision."
77
+ ),
78
+ "non_coverage": (risk.get("non_coverage") or {}).get("items", []),
79
+ },
80
+ }
81
+ from sourcecode.provenance import build_evidence_manifest
82
+ unsigned["evidence_manifest"] = build_evidence_manifest(
83
+ unsigned,
84
+ command="audit-report",
85
+ root=root,
86
+ inputs={
87
+ "profiles": sorted(profiles) if profiles else None,
88
+ "risk_limit": risk_limit,
89
+ "signed": bool(sign_key),
90
+ },
91
+ )
92
+ # Sign and publish the same JSON-normalized material. Some embedded evidence
93
+ # may contain tuples or other JSON-coercible values; normalizing before signing
94
+ # avoids a signature over an in-memory shape the user never receives.
95
+ normalized = json.loads(_canonical_json(unsigned).decode("utf-8"))
96
+ if sign_key:
97
+ normalized["signature"] = _sign(normalized, sign_key)
98
+ return normalized
99
+
100
+
101
+ def render_markdown(report: dict[str, Any]) -> str:
102
+ """Human report renderer over the JSON contract."""
103
+ summary = report.get("summary") or {}
104
+ repo = (report.get("repository") or {}).get("path", "")
105
+ profile = ", ".join(report.get("profile_set") or []) or "default"
106
+ lines = [
107
+ "# ASK Audit Report",
108
+ "",
109
+ f"- Repository: `{repo}`",
110
+ f"- ASK version: `{(report.get('tool') or {}).get('version', '')}`",
111
+ f"- Profile set: `{profile}`",
112
+ f"- Total defects: `{summary.get('total_defects')}`",
113
+ f"- Risk bands: `{summary.get('risk_bands')}`",
114
+ f"- Endpoint access: `{summary.get('endpoint_access')}`",
115
+ "",
116
+ "## Top Risks",
117
+ "",
118
+ ]
119
+ risks = report.get("top_risks") or []
120
+ if not risks:
121
+ lines.append("No composed risks were reported.")
122
+ else:
123
+ lines.extend([
124
+ "| Band | Score | Rules | File | Line | Title |",
125
+ "|---|---:|---|---|---:|---|",
126
+ ])
127
+ for row in risks:
128
+ rules = ", ".join(str(r) for r in row.get("rule_ids", []))
129
+ lines.append(
130
+ "| "
131
+ + " | ".join([
132
+ str(row.get("band", "")),
133
+ str(row.get("severity_effective", "")),
134
+ rules,
135
+ str(row.get("source_file", "")),
136
+ str(row.get("first_line", "")),
137
+ str(row.get("title", "")).replace("|", "\\|"),
138
+ ])
139
+ + " |"
140
+ )
141
+ lines.extend([
142
+ "",
143
+ "## Limits",
144
+ "",
145
+ str((report.get("limits") or {}).get("statement", "")),
146
+ ])
147
+ signature = report.get("signature")
148
+ if isinstance(signature, dict):
149
+ lines.extend([
150
+ "",
151
+ "## Signature",
152
+ "",
153
+ f"- Algorithm: `{signature.get('algorithm')}`",
154
+ f"- Payload SHA-256: `{signature.get('payload_sha256')}`",
155
+ f"- Key ID: `{signature.get('key_id')}`",
156
+ f"- Signature: `{signature.get('signature')}`",
157
+ ])
158
+ return "\n".join(lines) + "\n"