Evidence JSON
The scan report JSON is the authoritative record of what was found. It is stored in S3 and returned by GET /api/scan/{id}/report. This page documents the complete report structure and all finding fields.
Retrieving the report
/api/scan/{id}/report
Returns the full report JSON. No authentication required for public repository scans. The report is available once scan status is complete.
Report structure
The top-level report object:
| Field | Type | Description |
|---|---|---|
scan_id | string | Unique scan identifier (UUID) |
repo_url | string | The repository URL that was scanned |
scan_type | string | shallow or deep |
status | string | complete, failed, or pending |
created_at | string (ISO 8601) | When the scan was created |
completed_at | string (ISO 8601) | When the scan completed |
summary | object | Finding counts grouped by severity |
findings | array | List of finding objects |
gatekeep | object or null | Gate evaluation results. null if no devcontract.json present |
Summary object
{
"summary": {
"critical": 1,
"high": 3,
"medium": 7,
"low": 4,
"info": 2,
"total": 17
}
}
Finding object
Each item in the findings array:
| Field | Type | Shallow | Deep | Description |
|---|---|---|---|---|
finding_id | string | Yes | Yes | Deterministic ID derived from category, file_path, and title |
category | string | Yes | Yes | One of the nine gate categories |
severity | string | Yes | Yes | critical, high, medium, low, or info |
title | string | Yes | Yes | Short description of the issue |
description | string | Yes | Yes | Explanation of the finding and its risk |
remediation | string | Yes | Yes | Recommended fix or mitigation |
file_path | string or null | Sometimes | Yes | Repository-relative path of the affected file. null for repository-level findings |
line_number | integer or null | No | Sometimes | Line number of the issue within the file. Present when the layer can determine it precisely |
analysis_layer | string or null | No | Yes | Name of the deep scan layer that produced the finding (e.g. SecretDetector) |
confidence | float or null | No | Yes | Confidence score 0.0-1.0. Adjusted by the learning loop based on feedback. null if no learning data available |
Example finding (shallow)
{
"finding_id": "a1b2c3d4",
"category": "governance",
"severity": "medium",
"title": "No README found",
"description": "The repository has no README file at the root or in a docs/ directory.",
"remediation": "Add a README.md explaining the service purpose, setup, and usage.",
"file_path": null,
"line_number": null,
"analysis_layer": null,
"confidence": null
}
Example finding (deep, secret detection)
{
"finding_id": "e5f6a7b8",
"category": "secret",
"severity": "critical",
"title": "AWS access key detected",
"description": "A string matching the AWS access key pattern (AKIA...) was found in a source file. The value has been redacted.",
"remediation": "Remove the key from source, rotate it immediately in the AWS console, and use IAM roles or environment variables instead.",
"file_path": "src/config.py",
"line_number": 42,
"analysis_layer": "SecretDetector",
"confidence": 0.95
}
Example finding (deep, dependency CVE)
{
"finding_id": "c9d0e1f2",
"category": "dependency",
"severity": "high",
"title": "CVE-2023-12345 in requests 2.26.0",
"description": "The requests library version 2.26.0 has a known vulnerability (GHSA-...).",
"remediation": "Upgrade requests to 2.31.0 or later.",
"file_path": "requirements.txt",
"line_number": null,
"analysis_layer": "DependencyAnalyzer",
"confidence": 1.0
}
Gatekeep object
Present in the report when a devcontract.json was found in the repository:
| Field | Type | Description |
|---|---|---|
verdict | string | passed, passed_with_warnings, failed, not_evaluated, or error |
gates_evaluated | integer | Number of gates in the Contract |
gates_fired | integer | Number of gates that exceeded their threshold |
gates | array | Per-gate result objects |
Gate result object
| Field | Type | Description |
|---|---|---|
category | string | Gate category |
severity | string | Gate minimum severity |
threshold | integer | Maximum tolerated findings |
blocking | boolean | Whether the gate is blocking |
finding_count | integer | Findings that matched category and severity |
fired | boolean | true if finding_count > threshold |
description | string or null | The gate's description field from the Contract, if present |
Full gatekeep example
{
"gatekeep": {
"verdict": "failed",
"gates_evaluated": 3,
"gates_fired": 1,
"gates": [
{
"category": "secret",
"severity": "critical",
"threshold": 0,
"blocking": true,
"finding_count": 1,
"fired": true,
"description": "No hardcoded secrets"
},
{
"category": "dependency",
"severity": "high",
"threshold": 0,
"blocking": true,
"finding_count": 0,
"fired": false,
"description": "No high CVEs"
},
{
"category": "governance",
"severity": "medium",
"threshold": 0,
"blocking": false,
"finding_count": 0,
"fired": false,
"description": "Governance informational"
}
]
}
}
S3 storage path
Reports are stored in the ticketyboo-reports-579378699130 S3 bucket at the key reports/{scan_id}/report.json. The bucket is not publicly accessible; reports are served through the API.
Report TTL
DynamoDB finding records have a 90-day TTL. After 90 days, the scan status record and individual findings are eligible for deletion. The S3 report object has a separate lifecycle policy. For long-term audit trails, download and store the report JSON externally.