sourcecode 4.7.0__tar.gz → 4.9.0__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.
- {sourcecode-4.7.0 → sourcecode-4.9.0}/CHANGELOG.md +68 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/PKG-INFO +15 -14
- {sourcecode-4.7.0 → sourcecode-4.9.0}/README.md +14 -13
- {sourcecode-4.7.0 → sourcecode-4.9.0}/pyproject.toml +1 -1
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/__init__.py +1 -1
- sourcecode-4.9.0/src/sourcecode/audit_report.py +147 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/cli.py +783 -88
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/context_cache.py +48 -1
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/environment_resolution.py +88 -6
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/hibernate_strat.py +28 -6
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/migrate_check.py +20 -3
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/non_coverage.py +12 -10
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/posture.py +2 -1
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/risk.py +382 -22
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/rule_catalog.py +6 -1
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/spring_impact.py +8 -2
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/spring_security_audit.py +338 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/.gitignore +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/.ruff.toml +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/CLAUDE.md +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/CONTRIBUTING.md +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/LICENSE +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/SECURITY.md +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/raw +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/scripts/compare_integration_engines.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/scripts/customer_smoke_test.sh +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/scripts/generate_jdk_exports.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/scripts/perf_harness.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/archetype.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/architectural_baseline.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/architectural_delta.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/baseline_autocapture.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/cache.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/cache_model.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/call_surface.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/caller_metrics.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/caller_reach.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/canonical_ir.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/chain_rules.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/change_plan.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/cir_graphs.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/client_calls.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/compare.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/constraint_diff.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/context_graph.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/contract_diff.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/contract_init.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/data_exposure.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/data_labels.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/defect_identity.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/degradation.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/deployment_prefix.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/endpoint_literals.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/endpoint_metrics.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/envelope.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/error_schema.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/evidence_provider.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/explain.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/facts/__init__.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/facts/registry.json +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/file_chunker.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/filter_surface.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/format_contract.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/fqn_utils.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/git_checkout.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/graph_evidence.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/identity_fallback.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/integration_coordinates.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/jdk_exports.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/license.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/mcp/orchestrator.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/mcp/registry.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/mcp/runner.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/mcp/server.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/mcp_nudge.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/migration_blast.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/openapi_surface.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/openrewrite_recipe.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/output_budget.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/parse_cache.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/path_admission.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/perf.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/pipe_contract.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/pr_impact.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/prepare_context.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/progress.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/readiness_timeline.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/reconciliation.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/reference_facts.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/release_info.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/remedies.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/rename_refactor.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/repository_ir.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/__init__.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/context.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/errors.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/executor.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/planner.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/query.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/request.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/resolution.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/result.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/retriever.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/runtime.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/steps.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/steps_graph.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/steps_impact.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/steps_intf.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/steps_struct.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/retrieval/steps_txsec.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/ris.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/sarif.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/schema.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/security_config.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/security_config_scan.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/security_posture.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/semantic_impact_engine.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/semantic_integration_engine.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/semantic_services.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/serializer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/servlet_surface.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/source_text.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/spring_event_topology.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/spring_findings.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/spring_model.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/spring_profiles.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/spring_properties.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/spring_semantic.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/spring_tx_analyzer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/target_admission.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/test_gap_ranking.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/test_sources.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/token_estimate.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/type_usage_surface.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/validation_inference.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/validation_surface.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/verify_edit.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/verify_repo.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/verify_rules.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/version_check.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/supabase/functions/README.md +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/supabase/functions/get-license/index.ts +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/supabase/functions/telemetry/index.ts +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/supabase/sql/license_event_ordering.sql +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/supabase/sql/licensing_schema.sql +0 -0
- {sourcecode-4.7.0 → sourcecode-4.9.0}/supabase/sql/telemetry_events.sql +0 -0
|
@@ -2,6 +2,74 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [4.9.0] — 2026-08-04
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Custom AOP security gate audit.** `spring-audit` now emits `GATE-001` through
|
|
10
|
+
`GATE-004` for custom authorization gates detected by the security posture
|
|
11
|
+
authority: Spring AOP proxy bypass, fail-open advice, disabled/tautological
|
|
12
|
+
annotation attributes, and fragile positional/reflection binding.
|
|
13
|
+
- **Deployment evidence for runtime posture.** `posture --resolve-environments`
|
|
14
|
+
accepts `--env-file FILE` and binds explicit deployment profile evidence to
|
|
15
|
+
`decided_case` while keeping repository defaults as lower-priority evidence.
|
|
16
|
+
- **Bounded HTTP-input-to-sink flow in `risk`.** The `query_construction` factor
|
|
17
|
+
now distinguishes a proven bounded path from annotated HTTP input, through
|
|
18
|
+
positional calls in repository Java sources, into known concatenated query
|
|
19
|
+
sinks. General taint remains explicitly outside scope.
|
|
20
|
+
- **SARIF triage table for `enrich`.** `enrich --table` now provides
|
|
21
|
+
auditor-facing filtering by scanner rule, composed band and top-N while
|
|
22
|
+
leaving JSON as the contract.
|
|
23
|
+
- **Signed audit report bundle.** New experimental `audit-report` command packages
|
|
24
|
+
existing `risk` and `posture` evidence into JSON or Markdown, with optional
|
|
25
|
+
HMAC-SHA256 signing over the canonical JSON payload via `--sign-key`.
|
|
26
|
+
|
|
27
|
+
### Documentation
|
|
28
|
+
|
|
29
|
+
- README, user guide and root `ask --help` now list `audit-report`, the 4.9.0
|
|
30
|
+
version, `posture --env-file`, `enrich --table`, bounded `risk` flow and the
|
|
31
|
+
`GATE-*` rule family.
|
|
32
|
+
|
|
33
|
+
## [4.8.0] — 2026-08-04
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- **`risk` now gives MyBatis XML findings real reach.** `SEC-008` mapper XML
|
|
38
|
+
binds to the Java mapper interface named by the XML namespace, then walks that
|
|
39
|
+
interface's callers instead of publishing manufactured zero reach.
|
|
40
|
+
- **`risk` now maps deployment descriptor controls to endpoint reach.**
|
|
41
|
+
`DEAD-001` in `web.xml` reads descriptor URL patterns and reports the
|
|
42
|
+
endpoint population they cover, or an explicit unknown reach reason when the
|
|
43
|
+
descriptor scope cannot be parsed.
|
|
44
|
+
- **`migrate-check` no longer scores unresolved transitive Hibernate as ready.**
|
|
45
|
+
`spring-boot-starter-data-jpa` without a resolved Hibernate version now
|
|
46
|
+
degrades to unresolved transitive evidence instead of `hibernate_readiness:
|
|
47
|
+
100`.
|
|
48
|
+
- **`impact-chain` names caller-count units.** List entries, distinct symbols and
|
|
49
|
+
distinct classes are published separately so truncation warnings and metadata
|
|
50
|
+
no longer reuse one ambiguous "direct callers" phrase.
|
|
51
|
+
- **Expensive semantic passes warn about repository contention.** `spring-audit`,
|
|
52
|
+
`risk`, `migrate-check` and `verify` register an advisory analysis scope and
|
|
53
|
+
warn interactive users when another expensive `ask` process is already running
|
|
54
|
+
against the same repository.
|
|
55
|
+
- **Cache context stats publish lookup distributions.** `cache context-stats`
|
|
56
|
+
now includes lookup/build p50/p95 and context-layer payload sizes so cache-hit
|
|
57
|
+
cost can be budgeted instead of inferred.
|
|
58
|
+
- **Cache command grammar is consistent.** `ask cache model [path]` accepts a
|
|
59
|
+
repository path like sibling cache commands.
|
|
60
|
+
|
|
61
|
+
### Added
|
|
62
|
+
|
|
63
|
+
- **Human-scale table triage for large audits.** `spring-audit`, `risk` and
|
|
64
|
+
`migrate-check` now support table renderers with direct filtering:
|
|
65
|
+
`--table`, `--rule`/`--only`, `--band` where applicable, and `--top-n`.
|
|
66
|
+
|
|
67
|
+
### Documentation
|
|
68
|
+
|
|
69
|
+
- README and user guide examples now report `4.8.0`.
|
|
70
|
+
- The development roadmap records the saint-server field-evaluation fixes and
|
|
71
|
+
future feature queue.
|
|
72
|
+
|
|
5
73
|
## [4.7.0] — 2026-08-04
|
|
6
74
|
|
|
7
75
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.9.0
|
|
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
|
-

|
|
46
46
|

|
|
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.
|
|
100
|
+
ask version # ask 4.9.0 — and, on a build that has aged,
|
|
101
101
|
# how many releases have probably shipped since
|
|
102
102
|
```
|
|
103
103
|
|
|
@@ -260,10 +260,10 @@ figures and the authority behind each — and an axis this build cannot measure
|
|
|
260
260
|
weighted 1.0 and named in `blind_axes` rather than silently treated as safe. Measured on a
|
|
261
261
|
field case: a defect both `spring-audit` and `impact-chain` called *medium* composes to
|
|
262
262
|
**high (8.06)** once *reachable unauthenticated* and *writes to the database* are in it.
|
|
263
|
-
The last two factors describe the input path
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
263
|
+
The last two factors describe the input path: a query assembled by concatenation, a bounded
|
|
264
|
+
HTTP-input-to-query-sink path when ASK can prove one, and a route accepting a body with no
|
|
265
|
+
declared constraint. General taint remains `NC-001` and is published in the payload's own
|
|
266
|
+
`non_coverage` block.
|
|
267
267
|
`ask risk .` · `ask risk . --min-band high` · `ask risk . --limit 10`
|
|
268
268
|
→ [reference](docs/USER_GUIDE.md)
|
|
269
269
|
|
|
@@ -289,7 +289,7 @@ experimental: both are true, and they are two different facts.
|
|
|
289
289
|
|---|---|---|
|
|
290
290
|
| **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
|
|
291
291
|
| **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` |
|
|
292
|
+
| **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `posture` · `archetype` |
|
|
293
293
|
| **parked** | kept working, no longer developed | `retrieve` |
|
|
294
294
|
|
|
295
295
|
The same table is printed by `ask --help`, and both are generated from one authority
|
|
@@ -306,13 +306,14 @@ from it.
|
|
|
306
306
|
| Command | Tier | Answers | Note |
|
|
307
307
|
|---|---|---|---|
|
|
308
308
|
| `posture` | experimental | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
|
|
309
|
-
| `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 |
|
|
310
|
-
| `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`;
|
|
309
|
+
| `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>`; same composition as `risk`, with `--table --rule <id> --band high --top-n 20` for triage |
|
|
311
|
+
| `audit-report` | experimental | human audit bundle over existing `risk` + `posture` evidence, optionally signed | `--format markdown`; `--sign-key <file>` signs canonical JSON with HMAC-SHA256 |
|
|
311
312
|
| `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
313
|
| `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
314
|
| `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
|
-
| `spring-audit` | core | transactional anomalies + security surface + validation gaps | `--ci`, `-f github-comment` |
|
|
315
|
-
| `migrate-check` | core | Boot 2→3 readiness: located blockers, per-dimension score, effort | `--blast-radius` orders the re-test plan |
|
|
315
|
+
| `spring-audit` | core | transactional anomalies + security surface + validation gaps | `--ci`, `-f github-comment`; `--table --rule SEC-008 --top-n 20` for human-scale review |
|
|
316
|
+
| `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 |
|
|
316
317
|
| `impact` / `impact-chain` | core | blast radius of a change, to the endpoints it reaches | target the **interface**, not the `Impl` |
|
|
317
318
|
| `pr-impact` | core | the same, scoped to a PR diff | gating command: `--fail-on`, exit codes |
|
|
318
319
|
| `verify` | core | does the repo satisfy its declared contracts, **relative to a baseline** | `.ask/contracts.yml`; exit 0/1/2 |
|
|
@@ -328,7 +329,7 @@ from it.
|
|
|
328
329
|
| `retrieve` | parked | typed knowledge queries over the model | |
|
|
329
330
|
| `archetype` | experimental | evidence-based architectural archetype | |
|
|
330
331
|
| `rename-class` / `chunk-file` | supported | word-boundary Java rename; split a large file for an agent | |
|
|
331
|
-
| `cache status\|warm\|model\|clear` · `auth` · `telemetry` · `mcp` · `config` · `version` | supported | housekeeping | `activate` too |
|
|
332
|
+
| `cache status\|warm\|model\|clear` · `auth` · `telemetry` · `mcp` · `config` · `version` | supported | housekeeping | `cache model [path]` explains what a warm buys per command; `activate` too |
|
|
332
333
|
|
|
333
334
|
---
|
|
334
335
|
|
|
@@ -356,7 +357,7 @@ reading JSON sees the same boundary a buyer reads here.
|
|
|
356
357
|
|
|
357
358
|
| Not covered | Why | What answers it |
|
|
358
359
|
|---|---|---|
|
|
359
|
-
| **
|
|
360
|
+
| **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
361
|
| **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
362
|
| **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
363
|
| **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. |
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**Context · Impact · Migration · Architecture · Review — everything from one structural model.**
|
|
6
6
|
|
|
7
|
-

|
|
8
8
|

|
|
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.
|
|
62
|
+
ask version # ask 4.9.0 — and, on a build that has aged,
|
|
63
63
|
# how many releases have probably shipped since
|
|
64
64
|
```
|
|
65
65
|
|
|
@@ -222,10 +222,10 @@ figures and the authority behind each — and an axis this build cannot measure
|
|
|
222
222
|
weighted 1.0 and named in `blind_axes` rather than silently treated as safe. Measured on a
|
|
223
223
|
field case: a defect both `spring-audit` and `impact-chain` called *medium* composes to
|
|
224
224
|
**high (8.06)** once *reachable unauthenticated* and *writes to the database* are in it.
|
|
225
|
-
The last two factors describe the input path
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
225
|
+
The last two factors describe the input path: a query assembled by concatenation, a bounded
|
|
226
|
+
HTTP-input-to-query-sink path when ASK can prove one, and a route accepting a body with no
|
|
227
|
+
declared constraint. General taint remains `NC-001` and is published in the payload's own
|
|
228
|
+
`non_coverage` block.
|
|
229
229
|
`ask risk .` · `ask risk . --min-band high` · `ask risk . --limit 10`
|
|
230
230
|
→ [reference](docs/USER_GUIDE.md)
|
|
231
231
|
|
|
@@ -251,7 +251,7 @@ experimental: both are true, and they are two different facts.
|
|
|
251
251
|
|---|---|---|
|
|
252
252
|
| **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
|
|
253
253
|
| **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` |
|
|
254
|
+
| **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `posture` · `archetype` |
|
|
255
255
|
| **parked** | kept working, no longer developed | `retrieve` |
|
|
256
256
|
|
|
257
257
|
The same table is printed by `ask --help`, and both are generated from one authority
|
|
@@ -268,13 +268,14 @@ from it.
|
|
|
268
268
|
| Command | Tier | Answers | Note |
|
|
269
269
|
|---|---|---|---|
|
|
270
270
|
| `posture` | experimental | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
|
|
271
|
-
| `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 |
|
|
272
|
-
| `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`;
|
|
271
|
+
| `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>`; same composition as `risk`, with `--table --rule <id> --band high --top-n 20` for triage |
|
|
273
|
+
| `audit-report` | experimental | human audit bundle over existing `risk` + `posture` evidence, optionally signed | `--format markdown`; `--sign-key <file>` signs canonical JSON with HMAC-SHA256 |
|
|
273
274
|
| `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
275
|
| `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
276
|
| `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
|
-
| `spring-audit` | core | transactional anomalies + security surface + validation gaps | `--ci`, `-f github-comment` |
|
|
277
|
-
| `migrate-check` | core | Boot 2→3 readiness: located blockers, per-dimension score, effort | `--blast-radius` orders the re-test plan |
|
|
277
|
+
| `spring-audit` | core | transactional anomalies + security surface + validation gaps | `--ci`, `-f github-comment`; `--table --rule SEC-008 --top-n 20` for human-scale review |
|
|
278
|
+
| `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 |
|
|
278
279
|
| `impact` / `impact-chain` | core | blast radius of a change, to the endpoints it reaches | target the **interface**, not the `Impl` |
|
|
279
280
|
| `pr-impact` | core | the same, scoped to a PR diff | gating command: `--fail-on`, exit codes |
|
|
280
281
|
| `verify` | core | does the repo satisfy its declared contracts, **relative to a baseline** | `.ask/contracts.yml`; exit 0/1/2 |
|
|
@@ -290,7 +291,7 @@ from it.
|
|
|
290
291
|
| `retrieve` | parked | typed knowledge queries over the model | |
|
|
291
292
|
| `archetype` | experimental | evidence-based architectural archetype | |
|
|
292
293
|
| `rename-class` / `chunk-file` | supported | word-boundary Java rename; split a large file for an agent | |
|
|
293
|
-
| `cache status\|warm\|model\|clear` · `auth` · `telemetry` · `mcp` · `config` · `version` | supported | housekeeping | `activate` too |
|
|
294
|
+
| `cache status\|warm\|model\|clear` · `auth` · `telemetry` · `mcp` · `config` · `version` | supported | housekeeping | `cache model [path]` explains what a warm buys per command; `activate` too |
|
|
294
295
|
|
|
295
296
|
---
|
|
296
297
|
|
|
@@ -318,7 +319,7 @@ reading JSON sees the same boundary a buyer reads here.
|
|
|
318
319
|
|
|
319
320
|
| Not covered | Why | What answers it |
|
|
320
321
|
|---|---|---|
|
|
321
|
-
| **
|
|
322
|
+
| **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
323
|
| **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
324
|
| **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
325
|
| **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. |
|
|
@@ -0,0 +1,147 @@
|
|
|
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
|
+
# Sign and publish the same JSON-normalized material. Some embedded evidence
|
|
82
|
+
# may contain tuples or other JSON-coercible values; normalizing before signing
|
|
83
|
+
# avoids a signature over an in-memory shape the user never receives.
|
|
84
|
+
normalized = json.loads(_canonical_json(unsigned).decode("utf-8"))
|
|
85
|
+
if sign_key:
|
|
86
|
+
normalized["signature"] = _sign(normalized, sign_key)
|
|
87
|
+
return normalized
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def render_markdown(report: dict[str, Any]) -> str:
|
|
91
|
+
"""Human report renderer over the JSON contract."""
|
|
92
|
+
summary = report.get("summary") or {}
|
|
93
|
+
repo = (report.get("repository") or {}).get("path", "")
|
|
94
|
+
profile = ", ".join(report.get("profile_set") or []) or "default"
|
|
95
|
+
lines = [
|
|
96
|
+
"# ASK Audit Report",
|
|
97
|
+
"",
|
|
98
|
+
f"- Repository: `{repo}`",
|
|
99
|
+
f"- ASK version: `{(report.get('tool') or {}).get('version', '')}`",
|
|
100
|
+
f"- Profile set: `{profile}`",
|
|
101
|
+
f"- Total defects: `{summary.get('total_defects')}`",
|
|
102
|
+
f"- Risk bands: `{summary.get('risk_bands')}`",
|
|
103
|
+
f"- Endpoint access: `{summary.get('endpoint_access')}`",
|
|
104
|
+
"",
|
|
105
|
+
"## Top Risks",
|
|
106
|
+
"",
|
|
107
|
+
]
|
|
108
|
+
risks = report.get("top_risks") or []
|
|
109
|
+
if not risks:
|
|
110
|
+
lines.append("No composed risks were reported.")
|
|
111
|
+
else:
|
|
112
|
+
lines.extend([
|
|
113
|
+
"| Band | Score | Rules | File | Line | Title |",
|
|
114
|
+
"|---|---:|---|---|---:|---|",
|
|
115
|
+
])
|
|
116
|
+
for row in risks:
|
|
117
|
+
rules = ", ".join(str(r) for r in row.get("rule_ids", []))
|
|
118
|
+
lines.append(
|
|
119
|
+
"| "
|
|
120
|
+
+ " | ".join([
|
|
121
|
+
str(row.get("band", "")),
|
|
122
|
+
str(row.get("severity_effective", "")),
|
|
123
|
+
rules,
|
|
124
|
+
str(row.get("source_file", "")),
|
|
125
|
+
str(row.get("first_line", "")),
|
|
126
|
+
str(row.get("title", "")).replace("|", "\\|"),
|
|
127
|
+
])
|
|
128
|
+
+ " |"
|
|
129
|
+
)
|
|
130
|
+
lines.extend([
|
|
131
|
+
"",
|
|
132
|
+
"## Limits",
|
|
133
|
+
"",
|
|
134
|
+
str((report.get("limits") or {}).get("statement", "")),
|
|
135
|
+
])
|
|
136
|
+
signature = report.get("signature")
|
|
137
|
+
if isinstance(signature, dict):
|
|
138
|
+
lines.extend([
|
|
139
|
+
"",
|
|
140
|
+
"## Signature",
|
|
141
|
+
"",
|
|
142
|
+
f"- Algorithm: `{signature.get('algorithm')}`",
|
|
143
|
+
f"- Payload SHA-256: `{signature.get('payload_sha256')}`",
|
|
144
|
+
f"- Key ID: `{signature.get('key_id')}`",
|
|
145
|
+
f"- Signature: `{signature.get('signature')}`",
|
|
146
|
+
])
|
|
147
|
+
return "\n".join(lines) + "\n"
|