AutoTriage

Architecture Overview

AutoTriage is a Temporal-driven OpenGrep scanning platform structured as a Maven multi-module repository. Java 17 is used consistently for compilation, tests, CI, container builds, and production runtimes, with Maven 3.9 or newer. The parent module coordinates the following actionable submodules:

Temporal namespace scan-platform hosts all workflows. The primary workflow (OpenGrepPRScanWorkflow) drives the ordered activities: resolve repo, fetch/verify suppressions, run OpenGrep, apply suppressions (optionally adjudicating alerts via ZeroFalse using the source archive for context and persisting potential false positives to the triage service), upload results, compute verdict, and update queryable status between steps; suppression bundles are sourced from the PR head ref when provided and fall back to base ref. The triage service loads a repo-managed CEL policy from the default branch (default path .autotriage/policy.cel) to classify findings into true/potential/false positives based on cweId and confidencePercent, stores only potential false positives, and requires JWT role security:vuln_assessor:triager for review actions. On approval, it clones the repo over HTTPS, appends the suppression entry under .opengrep/suppressions, writes a .sig placeholder, pushes a branch autotriage/suppressions/{findingId}, and optionally formats a PR URL using TRIAGE_PR_URL_TEMPLATE. The API and workers ship structured logging enriched with runId/repo/prNumber/sha. Configuration surfaces via environment variables so Kubernetes manifests can mount TLS certs and queue names without code changes, including TEMPORAL_TARGET, TEMPORAL_NAMESPACE, TEMPORAL_TLS_ENABLED, TEMPORAL_TLS_CLIENT_CERT_PATH, TEMPORAL_TLS_CLIENT_KEY_PATH, TEMPORAL_TLS_SERVER_CA_PATH, SUPPRESSION_SERVICE_URL, ARTIFACTS_DIR, GIT_CLONE_TOKEN, OPENGREP_BIN, OPENGREP_CONFIG, ZeroFalse controls (ZEROFALSE_ENABLED, ZEROFALSE_MAX_FINDINGS, ZEROFALSE_MAX_TRACE_STEPS, ZEROFALSE_CONTEXT_LINES_BEFORE, ZEROFALSE_CONTEXT_LINES_AFTER, ZEROFALSE_PROMPTS_VARIANT), triage config (TRIAGE_SERVICE_URL, TRIAGE_POLICY_PATH, TRIAGE_POLICY_CACHE_MINUTES, TRIAGE_PR_URL_TEMPLATE), and the verdict gate settings (GATE_POLICY_FAIL_ON_ANY, GATE_POLICY_MAX_HIGH, GATE_POLICY_MAX_MEDIUM, GATE_POLICY_MAX_LOW).

Health endpoints run in each Quarkus service to satisfy the operational requirement, and Java 17 Dockerfiles live in docker/ for each runnable module. The filter worker produces a suppression-report-*.json alongside final.sarif, and the light worker uploads SARIF URIs plus the report URI to the suppression service mock. A GitHub Actions workflow runs the complete Maven reactor, including core triage tests, as the CI gate.

sequenceDiagram
    participant Client as ASTCLI/Client
    participant API as scan-api
    participant WF as Temporal Workflow
    participant Light as scan-worker-light
    participant Filter as scan-worker-filter
    participant OpenGrep as scan-worker-opengrep
    participant Suppression as suppression-service-mock
    participant Triage as triage-service
    participant TriageDB as triage-db

    Client->>API: POST /scans (ScanRequest)
    API->>WF: start OpenGrepPRScanWorkflow
    WF->>Light: resolveRepoSource
    WF->>Light: fetchSuppressionBundle (head/base)
    WF->>Light: verifySuppressionSignature
    WF->>OpenGrep: runOpenGrep
    WF->>Filter: applySuppressions (bundle + optional ZeroFalse)
    Filter->>Triage: POST /triage/candidates (confidence + metadata)
    Triage->>TriageDB: store potential FP + audit
    WF->>Light: uploadResults
    Light->>Suppression: POST /ingest (URIs + metadata)
    WF->>Light: computeVerdict
    API->>WF: queryStatus
    WF-->>API: ScanStatus
sequenceDiagram
    participant Reviewer as Security Reviewer
    participant Triage as triage-service
    participant TriageDB as triage-db
    participant Repo as Git Repo

    Reviewer->>Triage: GET /triage/findings
    Triage->>TriageDB: load findings + audit
    Reviewer->>Triage: POST /triage/findings/{id}/claim|approve|deny
    Triage->>TriageDB: update status + audit
    Triage->>Repo: clone default branch
    Triage->>Repo: append suppression + .sig, push branch
    Triage-->>Reviewer: PR URL (optional)