refactor(backend/api): extract EvidenceService (Step 4 — file 9 of 18)
compliance/api/evidence_routes.py (641 LOC) -> 240 LOC thin routes + 460-line
EvidenceService. Manages evidence CRUD, file upload, CI/CD evidence
collection (SAST/dependency/SBOM/container scans), and CI status dashboard.
Service injection pattern: EvidenceService takes the EvidenceRepository,
ControlRepository, and AutoRiskUpdater classes as constructor parameters.
The route's get_evidence_service factory reads these class references from
its own module namespace so tests that
``patch("compliance.api.evidence_routes.EvidenceRepository", ...)`` still
take effect through the factory.
The `_store_evidence` and `_update_risks` helpers stay as module-level
callables in evidence_service and are re-exported from the route module.
The collect_ci_evidence handler remains inline (not delegated to a service
method) so tests can patch
`compliance.api.evidence_routes._store_evidence` and have the patch take
effect at the handler's call site.
Legacy re-exports via __all__: SOURCE_CONTROL_MAP, EvidenceRepository,
ControlRepository, AutoRiskUpdater, _parse_ci_evidence,
_extract_findings_detail, _store_evidence, _update_risks.
Verified:
- 208/208 pytest (core + 35 evidence tests) pass
- OpenAPI 360/484 unchanged
- mypy compliance/ -> Success on 135 source files
- evidence_routes.py 641 -> 240 LOC
- Hard-cap violations: 10 -> 9
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -29108,7 +29108,7 @@
|
||||
},
|
||||
"/api/compliance/evidence/ci-status": {
|
||||
"get": {
|
||||
"description": "Get CI/CD evidence collection status.\n\nReturns overview of recent evidence collected from CI/CD pipelines,\nuseful for dashboards and monitoring.",
|
||||
"description": "Get CI/CD evidence collection status overview.",
|
||||
"operationId": "get_ci_evidence_status_api_compliance_evidence_ci_status_get",
|
||||
"parameters": [
|
||||
{
|
||||
@@ -29117,9 +29117,16 @@
|
||||
"name": "control_id",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Filter by control ID",
|
||||
"title": "Control Id",
|
||||
"type": "string"
|
||||
"title": "Control Id"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -29139,7 +29146,11 @@
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
"schema": {
|
||||
"additionalProperties": true,
|
||||
"title": "Response Get Ci Evidence Status Api Compliance Evidence Ci Status Get",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Successful Response"
|
||||
@@ -29164,7 +29175,7 @@
|
||||
},
|
||||
"/api/compliance/evidence/collect": {
|
||||
"post": {
|
||||
"description": "Collect evidence from CI/CD pipeline.\n\nThis endpoint is designed to be called from CI/CD workflows (GitHub Actions,\nGitLab CI, Jenkins, etc.) to automatically collect compliance evidence.\n\nSupported sources:\n- sast: Static Application Security Testing (Semgrep, SonarQube, etc.)\n- dependency_scan: Dependency vulnerability scanning (Trivy, Grype, Snyk)\n- sbom: Software Bill of Materials (CycloneDX, SPDX)\n- container_scan: Container image scanning (Trivy, Grype)\n- test_results: Test coverage and results\n- secret_scan: Secret detection (Gitleaks, TruffleHog)\n- code_review: Code review metrics",
|
||||
"description": "Collect evidence from CI/CD pipeline.\n\nHandler stays inline so tests can patch\n``compliance.api.evidence_routes._store_evidence`` /\n``compliance.api.evidence_routes._update_risks`` directly.",
|
||||
"operationId": "collect_ci_evidence_api_compliance_evidence_collect_post",
|
||||
"parameters": [
|
||||
{
|
||||
@@ -29184,9 +29195,16 @@
|
||||
"name": "ci_job_id",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "CI/CD Job ID for traceability",
|
||||
"title": "Ci Job Id",
|
||||
"type": "string"
|
||||
"title": "Ci Job Id"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -29195,9 +29213,16 @@
|
||||
"name": "ci_job_url",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "URL to CI/CD job",
|
||||
"title": "Ci Job Url",
|
||||
"type": "string"
|
||||
"title": "Ci Job Url"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -29205,9 +29230,16 @@
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"additionalProperties": true,
|
||||
"title": "Report Data",
|
||||
"type": "object"
|
||||
"anyOf": [
|
||||
{
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Report Data"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29216,7 +29248,11 @@
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
"schema": {
|
||||
"additionalProperties": true,
|
||||
"title": "Response Collect Ci Evidence Api Compliance Evidence Collect Post",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Successful Response"
|
||||
@@ -29302,7 +29338,9 @@
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/EvidenceResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Successful Response"
|
||||
@@ -29344,7 +29382,11 @@
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
"schema": {
|
||||
"additionalProperties": true,
|
||||
"title": "Response Delete Evidence Api Compliance Evidence Evidence Id Delete",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Successful Response"
|
||||
|
||||
Reference in New Issue
Block a user