Skip to main content

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

GET /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_idstringUnique scan identifier (UUID)
repo_urlstringThe repository URL that was scanned
scan_typestringshallow or deep
statusstringcomplete, failed, or pending
created_atstring (ISO 8601)When the scan was created
completed_atstring (ISO 8601)When the scan completed
summaryobjectFinding counts grouped by severity
findingsarrayList of finding objects
gatekeepobject or nullGate 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_idstringYesYesDeterministic ID derived from category, file_path, and title
categorystringYesYesOne of the nine gate categories
severitystringYesYescritical, high, medium, low, or info
titlestringYesYesShort description of the issue
descriptionstringYesYesExplanation of the finding and its risk
remediationstringYesYesRecommended fix or mitigation
file_pathstring or nullSometimesYesRepository-relative path of the affected file. null for repository-level findings
line_numberinteger or nullNoSometimesLine number of the issue within the file. Present when the layer can determine it precisely
analysis_layerstring or nullNoYesName of the deep scan layer that produced the finding (e.g. SecretDetector)
confidencefloat or nullNoYesConfidence 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
verdictstringpassed, passed_with_warnings, failed, not_evaluated, or error
gates_evaluatedintegerNumber of gates in the Contract
gates_firedintegerNumber of gates that exceeded their threshold
gatesarrayPer-gate result objects

Gate result object

Field Type Description
categorystringGate category
severitystringGate minimum severity
thresholdintegerMaximum tolerated findings
blockingbooleanWhether the gate is blocking
finding_countintegerFindings that matched category and severity
firedbooleantrue if finding_count > threshold
descriptionstring or nullThe 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.

Next steps