Skip to main content

How Gatekeep works

Gatekeep runs after a scan completes. It reads your devcontract.json, evaluates each gate against the scan findings, and returns a structured verdict. This page traces the full evaluation flow.

Scan lifecycle

Understanding Gatekeep requires understanding how a scan runs. When you submit a repository URL via POST /api/scan:

  1. Request validation — the API validates the URL, checks rate limits (1 scan per IP per 24h window for shallow; 3 deep scans per IP per 7-day rolling window), deducts a credit, and creates a scan record in DynamoDB with status pending.
  2. Async invocation — the handler self-invokes the Lambda asynchronously to run the scan without blocking the HTTP response. The API response returns immediately with a scan_id and status pending.
  3. Scan execution — the async handler clones the repository, runs the relevant layers (shallow or deep), deduplicates findings, applies confidence adjustments from the learning loop, and writes findings to DynamoDB.
  4. Report storage — the full scan report is serialised to JSON and stored in S3 at reports/{scan_id}/report.json.
  5. Status update — the scan record in DynamoDB is updated to complete.

Gatekeep evaluation happens at step 4 when the report is assembled: the scanner reads devcontract.json from the cloned repository and adds gate results to the report.

Gate evaluation logic

For each gate defined in the Contract:

  1. All findings from the scan are filtered to the gate's category.
  2. Findings are further filtered to those whose severity is equal to or higher than the gate's specified severity. The severity order is: info < low < medium < high < critical.
  3. The count of qualifying findings is compared to the gate's threshold.
  4. If count > threshold, the gate fires.
  5. If the gate fires and "blocking": true, it contributes to a failed verdict.
  6. If the gate fires and "blocking": false, it contributes to a passed_with_warnings verdict (unless a blocking gate also fires, in which case the overall verdict is failed).

Overall verdict

The overall Gatekeep verdict is determined as follows:

Conditions Verdict
No gates fired passed
One or more non-blocking gates fired; no blocking gates fired passed_with_warnings
One or more blocking gates fired failed
No devcontract.json present in repository not_evaluated
Contract file present but invalid JSON or unrecognised fields error

Where the verdict appears

Scan status endpoint

The GET /api/scan/{id} response includes a top-level gatekeep field when evaluation ran:

{
  "scan_id": "abc123",
  "status": "complete",
  "gatekeep": {
    "verdict": "failed",
    "gates_evaluated": 5,
    "gates_fired": 1
  }
}

Full report

The GET /api/scan/{id}/report response contains the complete gate-by-gate breakdown:

{
  "scan_id": "abc123",
  "gatekeep": {
    "verdict": "failed",
    "gates": [
      {
        "category": "secret",
        "severity": "critical",
        "threshold": 0,
        "blocking": true,
        "finding_count": 2,
        "fired": true,
        "description": "No hardcoded secrets"
      },
      {
        "category": "governance",
        "severity": "medium",
        "threshold": 0,
        "blocking": false,
        "finding_count": 0,
        "fired": false,
        "description": "README and CI expected"
      }
    ]
  }
}

Deduplication and the learning loop

Before Gatekeep evaluates findings, two pre-processing steps occur:

Deduplication: findings with the same file_path, category, and title are collapsed into one. This prevents a single issue appearing in multiple layers from inflating gate counts.

Confidence adjustment: the scanner loads a lessons-learned.md document from S3 (if present) that summarises feedback submitted through the scan UI. Findings with a pattern of negative feedback have their confidence score lowered. Gatekeep evaluates all findings regardless of confidence score, but the confidence value is visible in the report for human review.

Rate limits and credits

Gatekeep evaluation does not consume additional credits. One credit is consumed per scan (shallow or deep). Credit consumption occurs at the point the scan is accepted, not when Gatekeep evaluation completes.

The deep scan rate limit (3 per IP per 7-day rolling window) is independent of credit balance. Both checks must pass for a deep scan to proceed.

Next steps