{
  "openapi": "3.0.0",
  "paths": {
    "/scans": {
      "post": {
        "operationId": "RestScanController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestCreateScanDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestCreateScanResponseDto"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits"
          }
        },
        "summary": "Trigger a pentest scan",
        "tags": [
          "REST API - Scans"
        ]
      },
      "get": {
        "operationId": "RestScanController_list",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "The page number to retrieve.",
            "schema": {
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "The number of items to retrieve per page.",
            "schema": {
              "default": 100,
              "type": "number"
            }
          },
          {
            "name": "scan_type",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pr",
                "full"
              ]
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "running",
                "completed",
                "failed",
                "stopped",
                "cancelled",
                "skipped",
                "pending_verification",
                "pending_triage",
                "draft",
                "estimating",
                "estimated"
              ]
            }
          },
          {
            "name": "sort_by",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "updated_at",
                "status"
              ]
            }
          },
          {
            "name": "sort_order",
            "required": false,
            "in": "query",
            "schema": {
              "default": "DESC",
              "type": "string",
              "enum": [
                "ASC",
                "DESC"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestScanListResponseDto"
                }
              }
            }
          }
        },
        "summary": "List scans with pagination and filters",
        "tags": [
          "REST API - Scans"
        ]
      }
    },
    "/scans/{id}/stop": {
      "post": {
        "operationId": "RestScanController_stop",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestScanStatusResponseDto"
                }
              }
            }
          }
        },
        "summary": "Stop a running scan. Members can stop pentests they started and any PR scan; admins can stop any scan.",
        "tags": [
          "REST API - Scans"
        ]
      }
    },
    "/scans/{id}/status": {
      "get": {
        "operationId": "RestScanController_getStatus",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestScanStatusResponseDto"
                }
              }
            }
          }
        },
        "summary": "Get scan status",
        "tags": [
          "REST API - Scans"
        ]
      }
    },
    "/scans/{id}/findings/export": {
      "get": {
        "operationId": "RestScanController_exportFindings",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "required": true,
            "in": "query",
            "description": "Export format",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv",
                "sarif"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Export findings for a scan",
        "tags": [
          "REST API - Scans"
        ]
      }
    },
    "/scans/{id}/findings": {
      "get": {
        "operationId": "RestScanController_listScanFindings",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "The page number to retrieve.",
            "schema": {
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "The number of items to retrieve per page.",
            "schema": {
              "default": 100,
              "type": "number"
            }
          },
          {
            "name": "severity",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "critical",
                "high",
                "medium",
                "low",
                "info"
              ]
            }
          },
          {
            "name": "state",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "true_positive",
                "false_positive",
                "accepted_risk",
                "resolved",
                "closed"
              ]
            }
          },
          {
            "name": "scan_id",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scan_type",
            "required": false,
            "in": "query",
            "description": "Filter by scan type across all scans associated with the finding.",
            "schema": {
              "type": "string",
              "enum": [
                "pr",
                "full"
              ]
            }
          },
          {
            "name": "repo_url",
            "required": false,
            "in": "query",
            "description": "Filter by repository URL. Case-insensitive; a trailing slash or .git suffix is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "found_since",
            "required": false,
            "in": "query",
            "description": "Only include findings discovered on/after this ISO 8601 timestamp.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "found_until",
            "required": false,
            "in": "query",
            "description": "Only include findings discovered before this ISO 8601 timestamp.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_by",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "found_at",
                "updated_at",
                "severity"
              ]
            }
          },
          {
            "name": "sort_order",
            "required": false,
            "in": "query",
            "schema": {
              "default": "DESC",
              "type": "string",
              "enum": [
                "ASC",
                "DESC"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestFindingListResponseDto"
                }
              }
            }
          }
        },
        "summary": "List findings for a specific scan",
        "tags": [
          "REST API - Scans"
        ]
      }
    },
    "/scans/{id}": {
      "get": {
        "operationId": "RestScanController_getById",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestScanResponseDto"
                }
              }
            }
          }
        },
        "summary": "Get scan by UUID",
        "tags": [
          "REST API - Scans"
        ]
      }
    },
    "/findings": {
      "get": {
        "operationId": "RestFindingController_list",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "The page number to retrieve.",
            "schema": {
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "The number of items to retrieve per page.",
            "schema": {
              "default": 100,
              "type": "number"
            }
          },
          {
            "name": "severity",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "critical",
                "high",
                "medium",
                "low",
                "info"
              ]
            }
          },
          {
            "name": "state",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "true_positive",
                "false_positive",
                "accepted_risk",
                "resolved",
                "closed"
              ]
            }
          },
          {
            "name": "scan_id",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scan_type",
            "required": false,
            "in": "query",
            "description": "Filter by scan type across all scans associated with the finding.",
            "schema": {
              "type": "string",
              "enum": [
                "pr",
                "full"
              ]
            }
          },
          {
            "name": "repo_url",
            "required": false,
            "in": "query",
            "description": "Filter by repository URL. Case-insensitive; a trailing slash or .git suffix is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "found_since",
            "required": false,
            "in": "query",
            "description": "Only include findings discovered on/after this ISO 8601 timestamp.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "found_until",
            "required": false,
            "in": "query",
            "description": "Only include findings discovered before this ISO 8601 timestamp.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_by",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "found_at",
                "updated_at",
                "severity"
              ]
            }
          },
          {
            "name": "sort_order",
            "required": false,
            "in": "query",
            "schema": {
              "default": "DESC",
              "type": "string",
              "enum": [
                "ASC",
                "DESC"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestFindingListResponseDto"
                }
              }
            }
          }
        },
        "summary": "List findings with pagination and filters",
        "tags": [
          "REST API - Findings"
        ]
      }
    },
    "/findings/counts": {
      "get": {
        "operationId": "RestFindingController_counts",
        "parameters": [
          {
            "name": "severity",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "critical",
                "high",
                "medium",
                "low",
                "info"
              ]
            }
          },
          {
            "name": "state",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "true_positive",
                "false_positive",
                "accepted_risk",
                "resolved",
                "closed"
              ]
            }
          },
          {
            "name": "scan_id",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scan_type",
            "required": false,
            "in": "query",
            "description": "Filter by scan type across all scans associated with the finding.",
            "schema": {
              "type": "string",
              "enum": [
                "pr",
                "full"
              ]
            }
          },
          {
            "name": "repo_url",
            "required": false,
            "in": "query",
            "description": "Filter by repository URL. Case-insensitive; a trailing slash or .git suffix is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "found_since",
            "required": false,
            "in": "query",
            "description": "Only include findings discovered on/after this ISO 8601 timestamp.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "found_until",
            "required": false,
            "in": "query",
            "description": "Only include findings discovered before this ISO 8601 timestamp.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestFindingCountsResponseDto"
                }
              }
            }
          }
        },
        "summary": "Count findings matching the list filters, by severity, state and repository",
        "tags": [
          "REST API - Findings"
        ]
      }
    },
    "/findings/export": {
      "get": {
        "operationId": "RestFindingController_exportFindings",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "The page number to retrieve.",
            "schema": {
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "The number of items to retrieve per page.",
            "schema": {
              "default": 100,
              "type": "number"
            }
          },
          {
            "name": "severity",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "critical",
                "high",
                "medium",
                "low",
                "info"
              ]
            }
          },
          {
            "name": "state",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "true_positive",
                "false_positive",
                "accepted_risk",
                "resolved",
                "closed"
              ]
            }
          },
          {
            "name": "scan_id",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scan_type",
            "required": false,
            "in": "query",
            "description": "Filter by scan type across all scans associated with the finding.",
            "schema": {
              "type": "string",
              "enum": [
                "pr",
                "full"
              ]
            }
          },
          {
            "name": "repo_url",
            "required": false,
            "in": "query",
            "description": "Filter by repository URL. Case-insensitive; a trailing slash or .git suffix is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "found_since",
            "required": false,
            "in": "query",
            "description": "Only include findings discovered on/after this ISO 8601 timestamp.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "found_until",
            "required": false,
            "in": "query",
            "description": "Only include findings discovered before this ISO 8601 timestamp.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_by",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "found_at",
                "updated_at",
                "severity"
              ]
            }
          },
          {
            "name": "sort_order",
            "required": false,
            "in": "query",
            "schema": {
              "default": "DESC",
              "type": "string",
              "enum": [
                "ASC",
                "DESC"
              ]
            }
          },
          {
            "name": "format",
            "required": true,
            "in": "query",
            "description": "Export format",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv",
                "sarif"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Export findings as JSON, CSV, or SARIF, optionally filtered by repository",
        "tags": [
          "REST API - Findings"
        ]
      }
    },
    "/findings/{id}": {
      "patch": {
        "operationId": "RestFindingController_update",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Finding UUID or display id (KEY-FD-NUMBER, e.g. HAC-FD-1104)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestUpdateFindingDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestUpdateFindingResponseDto"
                }
              }
            }
          }
        },
        "summary": "Update finding state, severity, and/or duplicate link",
        "tags": [
          "REST API - Findings"
        ]
      },
      "get": {
        "operationId": "RestFindingController_getById",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Finding UUID or display id (KEY-FD-NUMBER, e.g. HAC-FD-1104)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestFindingDetailResponseDto"
                }
              }
            }
          }
        },
        "summary": "Get finding details",
        "tags": [
          "REST API - Findings"
        ]
      }
    },
    "/findings/{id}/comments": {
      "post": {
        "operationId": "RestFindingController_addComment",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Finding UUID or display id (KEY-FD-NUMBER, e.g. HAC-FD-1104)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestAddCommentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestAddCommentResponseDto"
                }
              }
            }
          }
        },
        "summary": "Add a comment to a finding",
        "tags": [
          "REST API - Findings"
        ]
      }
    },
    "/cost-estimations": {
      "post": {
        "operationId": "RestCostEstimationController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCostEstimationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CostEstimationResponseDto"
                }
              }
            }
          }
        },
        "summary": "Create a cost estimation for one or more repos",
        "tags": [
          "REST API - Cost Estimations"
        ]
      },
      "get": {
        "operationId": "RestCostEstimationController_list",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestCostEstimationListResponseDto"
                }
              }
            }
          }
        },
        "summary": "List cost estimations",
        "tags": [
          "REST API - Cost Estimations"
        ]
      }
    },
    "/cost-estimations/{id}": {
      "get": {
        "operationId": "RestCostEstimationController_findOne",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CostEstimationResponseDto"
                }
              }
            }
          }
        },
        "summary": "Get cost estimation details",
        "tags": [
          "REST API - Cost Estimations"
        ]
      }
    },
    "/repos": {
      "get": {
        "operationId": "RestRepoController_list",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MergedReposResponseDto"
                }
              }
            }
          }
        },
        "summary": "List repositories from all connected providers, including whether PR scans are enabled",
        "tags": [
          "REST API - Repos"
        ]
      }
    },
    "/hfw/verdicts/batch": {
      "post": {
        "description": "Public, fast-mode HFW batch verdict proxy. This endpoint is intentionally scoped to feed-backed verdicts and can be moved behind X-Api-Key later.",
        "operationId": "RestHfwController_getBatchVerdicts",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestHfwBatchRequestDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestHfwBatchResponseDto"
                }
              }
            }
          }
        },
        "security": [],
        "summary": "Get fast dependency verdicts for landing and GitHub Action scans",
        "tags": [
          "REST API - HFW"
        ]
      }
    },
    "/hfw/osv/feed": {
      "get": {
        "operationId": "RestHfwController_getOsvFeed",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 500,
              "default": 200,
              "type": "number"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 0,
              "default": 0,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestHfwOsvFeedResponseDto"
                }
              }
            }
          }
        },
        "security": [],
        "summary": "List known-malware feed entries for package sitemap generation",
        "tags": [
          "REST API - HFW"
        ]
      }
    },
    "/hfw/verdict/{ecosystem}/{packageName}": {
      "get": {
        "description": "Public, fast-mode HFW verdict proxy. This endpoint is intentionally scoped to feed-backed verdicts and can be moved behind X-Api-Key later.",
        "operationId": "RestHfwController_getPackageVerdict",
        "parameters": [
          {
            "name": "version",
            "required": true,
            "in": "query",
            "description": "Package version to check",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wait_seconds",
            "required": false,
            "in": "query",
            "description": "Seconds to wait for an upstream verdict. Fast mode normally returns immediately.",
            "schema": {
              "minimum": 0,
              "maximum": 60,
              "default": 0,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestHfwVerdictResponseDto"
                }
              }
            }
          }
        },
        "security": [],
        "summary": "Get a fast dependency verdict for GitHub Action scans",
        "tags": [
          "REST API - HFW"
        ]
      }
    },
    "/hfw/verdict/{ecosystem}/{scope}/{packageName}": {
      "get": {
        "operationId": "RestHfwController_getScopedNpmPackageVerdict",
        "parameters": [
          {
            "name": "version",
            "required": true,
            "in": "query",
            "description": "Package version to check",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wait_seconds",
            "required": false,
            "in": "query",
            "description": "Seconds to wait for an upstream verdict. Fast mode normally returns immediately.",
            "schema": {
              "minimum": 0,
              "maximum": 60,
              "default": 0,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestHfwVerdictResponseDto"
                }
              }
            }
          }
        },
        "security": [],
        "summary": "Get a fast dependency verdict for scoped npm GitHub Action scans",
        "tags": [
          "REST API - HFW"
        ]
      }
    },
    "/pentests": {
      "post": {
        "operationId": "RestPentestController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestCreatePentestDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestPentestResponseDto"
                }
              }
            }
          }
        },
        "summary": "Create a draft pentest of repositories or uploaded archives, optionally with live sites",
        "tags": [
          "REST API - Pentests"
        ]
      }
    },
    "/pentests/{id}": {
      "patch": {
        "operationId": "RestPentestController_update",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestUpdatePentestDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestPentestResponseDto"
                }
              }
            }
          }
        },
        "summary": "Change a pentest that has not started. Changing its repositories clears the estimate.",
        "tags": [
          "REST API - Pentests"
        ]
      },
      "delete": {
        "operationId": "RestPentestController_discard",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestDiscardPentestResponseDto"
                }
              }
            }
          }
        },
        "summary": "Discard a pentest that has not started",
        "tags": [
          "REST API - Pentests"
        ]
      }
    },
    "/pentests/{id}/login-checks": {
      "post": {
        "operationId": "RestPentestController_checkLogins",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wait_seconds",
            "required": false,
            "in": "query",
            "description": "Wait up to this many seconds for the work to finish before answering",
            "schema": {
              "minimum": 0,
              "maximum": 50,
              "default": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestPentestResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "The pentest has no login targets"
          }
        },
        "summary": "Check that Hacktron can sign in to each login target, which it must before the pentest starts",
        "tags": [
          "REST API - Pentests"
        ]
      }
    },
    "/pentests/{id}/estimate": {
      "post": {
        "operationId": "RestPentestController_estimate",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestPentestResponseDto"
                }
              }
            }
          }
        },
        "summary": "Price a draft pentest; read it at GET /cost-estimations/{cost_estimation_id}",
        "tags": [
          "REST API - Pentests"
        ]
      }
    },
    "/pentests/{id}/start": {
      "post": {
        "operationId": "RestPentestController_start",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestStartPentestDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestPentestResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "A login target has no passing login check from the last hour"
          },
          "402": {
            "description": "Insufficient credits"
          },
          "409": {
            "description": "expected_credits no longer matches the total; read the estimate again and confirm the new total"
          }
        },
        "summary": "Start an estimated pentest, spending the confirmed credits (organization admins only)",
        "tags": [
          "REST API - Pentests"
        ]
      }
    },
    "/archives/uploads": {
      "post": {
        "operationId": "RestArchiveController_requestUpload",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RequestUploadDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestUploadResponseDto"
                }
              }
            }
          }
        },
        "summary": "Get a URL to upload a code archive (.zip, .7z or .tar.gz) to, then pentest it as a repo with source upload",
        "tags": [
          "REST API - Archives"
        ]
      }
    },
    "/credits": {
      "get": {
        "operationId": "RestCreditController_balance",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PentestCreditBalanceResponseDto"
                }
              }
            }
          }
        },
        "summary": "The organization's pentest credit balance",
        "tags": [
          "REST API - Credits"
        ]
      }
    },
    "/repos/pr-reviews": {
      "post": {
        "operationId": "RestRepoController_setPrReviews",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "description": "Organization ID",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RepositoryIdBatchDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RepositoryBatchResultDto"
                }
              }
            }
          }
        },
        "summary": "Turn PR/MR reviews on or off for repositories, by their id from the repository list. A repository must be selected for Hacktron access before its reviews can be turned on.",
        "tags": [
          "REST API - Repos"
        ]
      }
    },
    "/pr-review-settings": {
      "get": {
        "operationId": "RestPrReviewSettingsController_get",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "description": "Organization ID",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestPrReviewSettingsDto"
                }
              }
            }
          }
        },
        "summary": "Get the organization's PR/MR review settings: whether reviews post comments, the severity that fails the PR check, and which PRs are reviewed",
        "tags": [
          "REST API - Repos"
        ]
      },
      "patch": {
        "operationId": "RestPrReviewSettingsController_update",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "description": "Organization ID",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestPrReviewSettingsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestPrReviewSettingsDto"
                }
              }
            }
          }
        },
        "summary": "Change the organization's PR/MR review settings. Only the fields sent change; null turns off the fail-on severity or clears a filter. A repository's .hacktron/config.yaml overrides these.",
        "tags": [
          "REST API - Repos"
        ]
      }
    }
  },
  "info": {
    "title": "Hacktron REST API",
    "description": "Public REST API for programmatic access to Hacktron",
    "version": "1.0",
    "contact": {}
  },
  "tags": [],
  "servers": [
    {
      "url": "https://api.hacktron.ai/v1"
    }
  ],
  "components": {
    "securitySchemes": {
      "api-key": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key"
      }
    },
    "schemas": {
      "RestRepoDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "Repository URL"
          },
          "branch": {
            "type": "string",
            "description": "Branch name"
          },
          "source": {
            "type": "string",
            "description": "Repository source",
            "enum": [
              "connected",
              "public",
              "upload"
            ],
            "default": "connected"
          }
        },
        "required": [
          "url",
          "branch"
        ]
      },
      "RestCreateScanDto": {
        "type": "object",
        "properties": {
          "cost_estimation_id": {
            "type": "string",
            "description": "Completed cost estimation UUID"
          },
          "repos": {
            "description": "Repositories to scan",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RestRepoDto"
            }
          },
          "target_urls": {
            "description": "Target URLs for pentest",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "auth_instructions": {
            "type": "string",
            "description": "Target websites and browser login instructions, including URLs and credentials",
            "maxLength": 2000
          },
          "custom_context": {
            "type": "string",
            "description": "Custom context for the pentest",
            "maxLength": 2000
          },
          "context_document_ids": {
            "description": "Context document UUIDs to include",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "cost_estimation_id",
          "repos"
        ]
      },
      "RestCreateScanResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "task_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "task_id",
          "status",
          "message"
        ]
      },
      "RestScanStatusResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "task_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "completed",
              "failed",
              "stopped",
              "cancelled",
              "skipped",
              "pending_verification",
              "pending_triage",
              "draft",
              "estimating",
              "estimated"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "task_id",
          "status",
          "created_at",
          "updated_at"
        ]
      },
      "RestScanFindingsSummaryDto": {
        "type": "object",
        "properties": {
          "critical": {
            "type": "number"
          },
          "high": {
            "type": "number"
          },
          "medium": {
            "type": "number"
          },
          "low": {
            "type": "number"
          },
          "info": {
            "type": "number"
          }
        },
        "required": [
          "critical",
          "high",
          "medium",
          "low",
          "info"
        ]
      },
      "RestScanResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "task_id": {
            "type": "string"
          },
          "scan_type": {
            "type": "string",
            "enum": [
              "pr",
              "full"
            ]
          },
          "status": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "repo_url": {
            "type": "string",
            "nullable": true
          },
          "branch": {
            "type": "string",
            "nullable": true
          },
          "pr_number": {
            "type": "number",
            "nullable": true
          },
          "target_urls": {
            "nullable": true,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "findings_summary": {
            "$ref": "#/components/schemas/RestScanFindingsSummaryDto"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "task_id",
          "scan_type",
          "status",
          "name",
          "repo_url",
          "branch",
          "pr_number",
          "target_urls",
          "findings_summary",
          "created_at",
          "updated_at"
        ]
      },
      "RestScanListResponseDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RestScanResponseDto"
            }
          },
          "total": {
            "type": "number"
          },
          "page": {
            "type": "number"
          },
          "limit": {
            "type": "number"
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit"
        ]
      },
      "RestFindingResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Finding UUID"
          },
          "display_id": {
            "type": "string",
            "description": "Human-readable id (KEY-FD-NUMBER).",
            "example": "HAC-FD-1104"
          },
          "number": {
            "type": "integer",
            "description": "Per-organization sequence number behind display_id.",
            "example": 1104
          },
          "title": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "high",
              "medium",
              "low",
              "info"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "open",
              "true_positive",
              "false_positive",
              "accepted_risk",
              "resolved",
              "closed"
            ]
          },
          "description": {
            "type": "string"
          },
          "affected_file": {
            "type": "string"
          },
          "affected_code": {
            "type": "string"
          },
          "proof_of_concept": {
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scan_id": {
            "type": "string",
            "nullable": true
          },
          "found_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "resolved_at": {
            "type": "string",
            "nullable": true,
            "description": "Timestamp of the most recent transition to resolved (ISO 8601). Null if never resolved."
          }
        },
        "required": [
          "id",
          "display_id",
          "number",
          "title",
          "category",
          "severity",
          "state",
          "description",
          "affected_file",
          "affected_code",
          "proof_of_concept",
          "tags",
          "scan_id",
          "found_at",
          "updated_at",
          "resolved_at"
        ]
      },
      "RestFindingListResponseDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RestFindingResponseDto"
            }
          },
          "total": {
            "type": "number"
          },
          "page": {
            "type": "number"
          },
          "limit": {
            "type": "number"
          }
        },
        "required": [
          "data",
          "total",
          "page",
          "limit"
        ]
      },
      "RestSeverityCountsDto": {
        "type": "object",
        "properties": {
          "critical": {
            "type": "number"
          },
          "high": {
            "type": "number"
          },
          "medium": {
            "type": "number"
          },
          "low": {
            "type": "number"
          },
          "info": {
            "type": "number"
          }
        },
        "required": [
          "critical",
          "high",
          "medium",
          "low",
          "info"
        ]
      },
      "RestStateCountsDto": {
        "type": "object",
        "properties": {
          "open": {
            "type": "number"
          },
          "true_positive": {
            "type": "number"
          },
          "false_positive": {
            "type": "number"
          },
          "accepted_risk": {
            "type": "number"
          },
          "resolved": {
            "type": "number"
          },
          "closed": {
            "type": "number"
          }
        },
        "required": [
          "open",
          "true_positive",
          "false_positive",
          "accepted_risk",
          "resolved",
          "closed"
        ]
      },
      "RestRepositoryFindingCountsDto": {
        "type": "object",
        "properties": {
          "repository": {
            "type": "string",
            "nullable": true,
            "description": "Repository URL, or null for findings with no repository"
          },
          "total": {
            "type": "number"
          },
          "by_severity": {
            "$ref": "#/components/schemas/RestSeverityCountsDto"
          }
        },
        "required": [
          "repository",
          "total",
          "by_severity"
        ]
      },
      "RestFindingCountsResponseDto": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number"
          },
          "by_severity": {
            "$ref": "#/components/schemas/RestSeverityCountsDto"
          },
          "by_state": {
            "$ref": "#/components/schemas/RestStateCountsDto"
          },
          "by_repository": {
            "description": "Most findings first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RestRepositoryFindingCountsDto"
            }
          }
        },
        "required": [
          "total",
          "by_severity",
          "by_state",
          "by_repository"
        ]
      },
      "RestUpdateFindingDto": {
        "type": "object",
        "properties": {
          "state": {
            "type": "string",
            "enum": [
              "open",
              "true_positive",
              "false_positive",
              "accepted_risk",
              "resolved",
              "closed"
            ],
            "description": "New finding state"
          },
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "high",
              "medium",
              "low",
              "info"
            ],
            "description": "New severity level"
          },
          "state_reason": {
            "type": "string",
            "description": "Reason for the state change (defaults to reason if omitted)"
          },
          "severity_reason": {
            "type": "string",
            "description": "Reason for the severity change (defaults to reason if omitted)"
          },
          "reason": {
            "type": "string",
            "description": "Shorthand reason applied to both state and severity changes when their specific reason is not provided"
          },
          "duplicate_of": {
            "type": "string",
            "nullable": true,
            "description": "UUID of the canonical finding to mark this finding as a duplicate of, or null to unmark. The target must be in the same repository."
          }
        }
      },
      "RestUpdateFindingResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "open",
              "true_positive",
              "false_positive",
              "accepted_risk",
              "resolved",
              "closed"
            ]
          },
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "high",
              "medium",
              "low",
              "info"
            ]
          },
          "duplicate_of": {
            "type": "string",
            "nullable": true,
            "description": "UUID of the canonical finding this duplicates, if any."
          }
        },
        "required": [
          "id",
          "state",
          "severity",
          "duplicate_of"
        ]
      },
      "RestAddCommentDto": {
        "type": "object",
        "properties": {
          "comment": {
            "type": "string",
            "description": "Comment text",
            "maxLength": 4000
          }
        },
        "required": [
          "comment"
        ]
      },
      "RestAddCommentResponseDto": {
        "type": "object",
        "properties": {
          "comment_id": {
            "type": "string"
          }
        },
        "required": [
          "comment_id"
        ]
      },
      "RestTriageThreadEntryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "reaction": {
            "type": "string",
            "nullable": true
          },
          "comment": {
            "type": "string",
            "nullable": true
          },
          "user_id": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "timestamp": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "reaction",
          "comment",
          "user_id",
          "source",
          "timestamp"
        ]
      },
      "TaintStepDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "source",
              "propagation",
              "sink"
            ]
          },
          "file": {
            "type": "string"
          },
          "line": {
            "type": "number"
          },
          "end_line": {
            "type": "number"
          },
          "symbol": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "detail": {
            "type": "string",
            "description": "Raw symbol docstring; supplemental context for the stepped taint flow."
          },
          "taint_sources": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "code": {
            "type": "string",
            "description": "Source code lines for this step's symbol, pre-sliced by the worker."
          },
          "code_start_line": {
            "type": "number",
            "description": "1-based start line number of the `code` slice in the source file. Used by the frontend as the anchor for chevron-expand requests to GET /findings/:uuid/source."
          },
          "code_end_line": {
            "type": "number",
            "description": "1-based end line number of the `code` slice in the source file. Used by the frontend as the anchor for chevron-expand requests to GET /findings/:uuid/source."
          }
        },
        "required": [
          "type",
          "file",
          "line",
          "end_line",
          "symbol",
          "description",
          "taint_sources"
        ]
      },
      "RestFindingDetailResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Finding UUID"
          },
          "display_id": {
            "type": "string",
            "description": "Human-readable id (KEY-FD-NUMBER).",
            "example": "HAC-FD-1104"
          },
          "number": {
            "type": "integer",
            "description": "Per-organization sequence number behind display_id.",
            "example": 1104
          },
          "title": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "high",
              "medium",
              "low",
              "info"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "open",
              "true_positive",
              "false_positive",
              "accepted_risk",
              "resolved",
              "closed"
            ]
          },
          "description": {
            "type": "string"
          },
          "affected_file": {
            "type": "string"
          },
          "affected_code": {
            "type": "string"
          },
          "proof_of_concept": {
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scan_id": {
            "type": "string",
            "nullable": true
          },
          "found_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "resolved_at": {
            "type": "string",
            "nullable": true,
            "description": "Timestamp of the most recent transition to resolved (ISO 8601). Null if never resolved."
          },
          "triage_thread": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RestTriageThreadEntryDto"
            }
          },
          "taint_path": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaintStepDto"
            }
          },
          "occurrence_count": {
            "type": "number"
          },
          "repo_url": {
            "type": "string",
            "nullable": true
          },
          "scan_type": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "display_id",
          "number",
          "title",
          "category",
          "severity",
          "state",
          "description",
          "affected_file",
          "affected_code",
          "proof_of_concept",
          "tags",
          "scan_id",
          "found_at",
          "updated_at",
          "resolved_at",
          "triage_thread",
          "taint_path",
          "occurrence_count",
          "repo_url",
          "scan_type"
        ]
      },
      "ConnectedCostEstimationRepoDto": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "description": "Source type",
            "enum": [
              "connected"
            ],
            "default": "connected"
          },
          "repo_url": {
            "type": "string",
            "description": "Repository URL"
          },
          "branch": {
            "type": "string",
            "description": "Branch name"
          },
          "github_installation_id": {
            "type": "number",
            "description": "GitHub App installation ID. Omitted for PAT-based connections (e.g. GitHub Enterprise), where the installation is resolved from repo_url and the organization instead."
          }
        },
        "required": [
          "source",
          "repo_url",
          "branch"
        ]
      },
      "PublicCostEstimationRepoDto": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "description": "Source type",
            "enum": [
              "public"
            ]
          },
          "repo_url": {
            "type": "string",
            "description": "Repository URL"
          },
          "branch": {
            "type": "string",
            "description": "Branch name"
          }
        },
        "required": [
          "source",
          "repo_url",
          "branch"
        ]
      },
      "UploadCostEstimationRepoDto": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "description": "Source type",
            "enum": [
              "upload"
            ]
          },
          "archive_id": {
            "type": "string",
            "description": "Scan archive ID"
          }
        },
        "required": [
          "source",
          "archive_id"
        ]
      },
      "CreateCostEstimationDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Friendly name for this estimation"
          },
          "repos": {
            "type": "array",
            "description": "Repositories to estimate",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/ConnectedCostEstimationRepoDto"
                },
                {
                  "$ref": "#/components/schemas/PublicCostEstimationRepoDto"
                },
                {
                  "$ref": "#/components/schemas/UploadCostEstimationRepoDto"
                }
              ],
              "discriminator": {
                "propertyName": "source",
                "mapping": {
                  "connected": "#/components/schemas/ConnectedCostEstimationRepoDto",
                  "public": "#/components/schemas/PublicCostEstimationRepoDto",
                  "upload": "#/components/schemas/UploadCostEstimationRepoDto"
                }
              }
            }
          }
        },
        "required": [
          "repos"
        ]
      },
      "RepoInputResponseDto": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "description": "Source type",
            "enum": [
              "connected",
              "public",
              "upload"
            ]
          },
          "repo_url": {
            "type": "string",
            "description": "Repository URL",
            "example": "https://github.com/owner/repo"
          },
          "branch": {
            "type": "string",
            "description": "Branch name",
            "example": "main"
          },
          "commit_sha": {
            "type": "string",
            "description": "Resolved commit SHA",
            "example": "abc123def456"
          },
          "archive_id": {
            "type": "string",
            "description": "Archive ID (for upload sources)"
          }
        }
      },
      "RepoResultApplicationDto": {
        "type": "object",
        "properties": {
          "app_name": {
            "type": "string",
            "description": "Application name",
            "example": "backend-api"
          },
          "app_root_path": {
            "type": "string",
            "description": "Application root path",
            "example": "apps/api"
          },
          "architecture": {
            "type": "string",
            "description": "Architecture description",
            "example": "NestJS REST API with PostgreSQL"
          }
        },
        "required": [
          "app_name",
          "app_root_path"
        ]
      },
      "RepoResultResponseDto": {
        "type": "object",
        "properties": {
          "repo_url": {
            "type": "string",
            "description": "Repository URL",
            "example": "https://github.com/owner/repo"
          },
          "branch": {
            "type": "string",
            "description": "Branch name",
            "example": "main"
          },
          "commit_sha": {
            "type": "string",
            "description": "Commit SHA",
            "example": "abc123def456"
          },
          "status": {
            "type": "string",
            "description": "Result status",
            "enum": [
              "completed",
              "failed"
            ],
            "example": "completed"
          },
          "from_cache": {
            "type": "boolean",
            "description": "Whether result was served from cache",
            "example": false
          },
          "applications": {
            "description": "Detected applications",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RepoResultApplicationDto"
            }
          },
          "credits": {
            "type": "number",
            "description": "Estimated credits for this repo",
            "example": 4000
          },
          "error": {
            "type": "string",
            "description": "Error message (when status is failed)"
          },
          "failure_reason": {
            "type": "string",
            "description": "Structured failure reason",
            "enum": [
              "unsupported_language",
              "scope_no_match"
            ]
          },
          "unsupported_languages": {
            "description": "Detected unsupported languages among the top languages",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scoped_file_count": {
            "type": "number",
            "description": "Files that matched the repository's whitebox scope rules, counted on disk before analysis. Absent for unscoped repositories.",
            "example": 42
          }
        },
        "required": [
          "repo_url",
          "status",
          "from_cache"
        ]
      },
      "CostEstimationResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Estimation UUID",
            "example": "123e4567-e89b-12d3-a456-426614174000"
          },
          "organization_id": {
            "type": "string",
            "description": "Organization UUID",
            "example": "f336d0bc-b841-465b-8045-024475c079dd"
          },
          "user_id": {
            "type": "string",
            "description": "User UUID",
            "example": "f336d0bc-b841-465b-8045-024475c079dd"
          },
          "name": {
            "type": "string",
            "description": "Friendly name for this estimation"
          },
          "task_id": {
            "type": "string",
            "description": "Task identifier",
            "example": "cost_est_owner-repo_12345"
          },
          "status": {
            "type": "string",
            "description": "Estimation status",
            "enum": [
              "pending",
              "running",
              "completed",
              "partial",
              "failed"
            ],
            "example": "completed"
          },
          "repos": {
            "description": "Input repositories",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RepoInputResponseDto"
            }
          },
          "total_credits": {
            "type": "number",
            "description": "Total estimated credits across all repos",
            "example": 8000
          },
          "repo_results": {
            "description": "Per-repo estimation results",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RepoResultResponseDto"
            }
          },
          "error": {
            "type": "string",
            "description": "Error message"
          },
          "triage_required": {
            "type": "boolean",
            "description": "Whether human triage is mandatory for a scan of this estimation (large app, above the predicted-cost threshold). The customer cannot opt out when true.",
            "example": false
          },
          "triage_fee_credits": {
            "type": "number",
            "description": "Triage fee in credits (a percentage of the scan base credits) added when triage is enabled",
            "example": 1600
          },
          "created_at": {
            "format": "date-time",
            "type": "string",
            "description": "Timestamp when estimation was created",
            "example": "2026-03-10T12:00:00.000Z"
          },
          "updated_at": {
            "format": "date-time",
            "type": "string",
            "description": "Timestamp when estimation was last updated",
            "example": "2026-03-10T12:05:00.000Z"
          }
        },
        "required": [
          "id",
          "organization_id",
          "user_id",
          "task_id",
          "status",
          "repos",
          "triage_required",
          "triage_fee_credits",
          "created_at",
          "updated_at"
        ]
      },
      "RestCostEstimationListResponseDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CostEstimationResponseDto"
            }
          },
          "total": {
            "type": "number"
          }
        },
        "required": [
          "data",
          "total"
        ]
      },
      "UnifiedRepoDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Internal UUID",
            "example": "123e4567-e89b-12d3-a456-426614174000"
          },
          "provider": {
            "type": "string",
            "description": "Source provider",
            "enum": [
              "github",
              "gitlab",
              "bitbucket",
              "azure"
            ],
            "example": "github"
          },
          "name": {
            "type": "string",
            "description": "Display name (owner/repo for GitHub, namespace/project for GitLab, workspace/slug for Bitbucket, project/repository for Azure DevOps)",
            "example": "octocat/Hello-World"
          },
          "providerKey": {
            "type": "string",
            "description": "Provider-native identifier for mutation endpoints. GitHub: owner/repo, GitLab: numeric projectId (as string), Bitbucket: repository UUID, Azure DevOps: repository UUID.",
            "example": "octocat/Hello-World"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the repository is enabled for scanning",
            "example": true
          },
          "threatModelUpdatedAt": {
            "type": "string",
            "nullable": true,
            "description": "ISO timestamp of the repo's most recent threat_model.md update, or null if it has none. Repos are returned ordered by this (most recent first; repos without a threat model last).",
            "example": "2026-06-22T12:00:00.000Z"
          },
          "openFindingsCount": {
            "type": "number",
            "description": "Number of approved, visible findings that remain open for this repository",
            "example": 3
          },
          "lastScanAt": {
            "type": "string",
            "nullable": true,
            "description": "ISO timestamp of the most recent completed scan containing this repository, or null if it has not been scanned",
            "example": "2026-09-15T12:00:00.000Z"
          },
          "ossApproved": {
            "type": "boolean",
            "description": "Whether this github.com repository is approved for free OSS PR reviews. Independent of whether PR scans are enabled.",
            "example": true
          },
          "prScansEnabled": {
            "type": "boolean",
            "description": "Whether PR/MR scans are enabled (GitHub and GitLab)",
            "example": true
          },
          "prScanBranches": {
            "description": "Target branch patterns for PR/MR scans (GitHub and GitLab)",
            "example": [
              "main",
              "**/release/**"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "installationId": {
            "type": "number",
            "description": "GitHub App installation ID (GitHub only)",
            "example": 12345678
          },
          "baseUrl": {
            "type": "string",
            "nullable": true,
            "description": "GitHub Enterprise base URL for self-hosted (PAT) installations (null/absent for github.com), the GitLab installation URL, or the Azure DevOps organization URL. Clients should build clone/display URLs from this host instead of assuming the public provider host.",
            "example": "https://ghe.example.com"
          },
          "defaultBranch": {
            "type": "string",
            "description": "Default branch (GitLab only)",
            "example": "main"
          },
          "visibility": {
            "type": "string",
            "description": "Project visibility (GitLab only)",
            "example": "private"
          },
          "webhookRegistered": {
            "type": "boolean",
            "description": "Whether a webhook is registered for this project (GitLab only)",
            "example": true
          },
          "isPrivate": {
            "type": "boolean",
            "description": "Whether the repository is private (Bitbucket only)",
            "example": true
          }
        },
        "required": [
          "id",
          "provider",
          "name",
          "providerKey",
          "enabled",
          "threatModelUpdatedAt",
          "openFindingsCount",
          "lastScanAt"
        ]
      },
      "MergedReposResponseDto": {
        "type": "object",
        "properties": {
          "repos": {
            "description": "Unified list of repositories from all providers",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UnifiedRepoDto"
            }
          },
          "errors": {
            "description": "Providers that failed to respond",
            "example": [],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "repos",
          "errors"
        ]
      },
      "RestHfwBatchPackageDto": {
        "type": "object",
        "properties": {
          "ecosystem": {
            "type": "string",
            "enum": [
              "npm",
              "pypi"
            ]
          },
          "package": {
            "type": "string"
          },
          "version": {
            "type": "string"
          }
        },
        "required": [
          "ecosystem",
          "package",
          "version"
        ]
      },
      "RestHfwBatchRequestDto": {
        "type": "object",
        "properties": {
          "packages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RestHfwBatchPackageDto"
            }
          }
        },
        "required": [
          "packages"
        ]
      },
      "RestHfwVerdictResponseDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ready",
              "pending",
              "scanning"
            ]
          },
          "ecosystem": {
            "type": "string",
            "enum": [
              "npm",
              "pypi"
            ]
          },
          "package": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "level": {
            "type": "string",
            "enum": [
              "clean",
              "suspicious",
              "malicious",
              "unknown"
            ]
          },
          "confidence": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "findings": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "source": {
            "type": "string"
          },
          "osv_id": {
            "type": "string"
          }
        },
        "required": [
          "status",
          "ecosystem",
          "package",
          "version",
          "level",
          "confidence",
          "summary",
          "findings"
        ]
      },
      "RestHfwBatchResponseDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "verdicts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RestHfwVerdictResponseDto"
            }
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "status",
          "verdicts",
          "errors"
        ]
      },
      "RestHfwOsvFeedResultDto": {
        "type": "object",
        "properties": {
          "ecosystem": {
            "type": "string"
          },
          "package": {
            "type": "string"
          },
          "versions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "ecosystem",
          "package",
          "versions"
        ]
      },
      "RestHfwOsvFeedResponseDto": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RestHfwOsvFeedResultDto"
            }
          }
        },
        "required": [
          "results"
        ]
      },
      "ConnectedRepoInputDto": {
        "type": "object",
        "properties": {
          "include_paths": {
            "description": "Whitebox scope: gitignore-style globs (relative to the repo root) that narrow the scan to matching paths. Empty means the whole repository.",
            "example": [
              "services/gateway/**"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "exclude_paths": {
            "description": "Whitebox scope: gitignore-style globs removed from the scan after include_paths is applied; use `*.md` to drop a file type.",
            "example": [
              "**/tests/**",
              "vendor/",
              "*.md"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "connected"
            ]
          },
          "url": {
            "type": "string",
            "description": "Repository URL",
            "example": "https://github.com/owner/repo"
          },
          "branch": {
            "type": "string",
            "description": "Branch name, tag name, or commit SHA"
          },
          "ref_type": {
            "type": "string",
            "enum": [
              "branch",
              "tag",
              "sha"
            ],
            "description": "How `branch` was selected (UI hint for draft re-use)"
          },
          "github_installation_id": {
            "type": "number",
            "description": "GitHub App installation id. Omitted for PAT-based connections (e.g. GitHub Enterprise), where the installation is resolved from the repository URL and the organization instead."
          }
        },
        "required": [
          "source",
          "url",
          "branch"
        ]
      },
      "PublicRepoInputDto": {
        "type": "object",
        "properties": {
          "include_paths": {
            "description": "Whitebox scope: gitignore-style globs (relative to the repo root) that narrow the scan to matching paths. Empty means the whole repository.",
            "example": [
              "services/gateway/**"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "exclude_paths": {
            "description": "Whitebox scope: gitignore-style globs removed from the scan after include_paths is applied; use `*.md` to drop a file type.",
            "example": [
              "**/tests/**",
              "vendor/",
              "*.md"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "public"
            ]
          },
          "url": {
            "type": "string",
            "description": "Repository URL",
            "example": "https://github.com/owner/repo"
          },
          "branch": {
            "type": "string",
            "description": "Branch name, tag name, or commit SHA"
          },
          "ref_type": {
            "type": "string",
            "enum": [
              "branch",
              "tag",
              "sha"
            ],
            "description": "How `branch` was selected (UI hint for draft re-use)"
          }
        },
        "required": [
          "source",
          "url",
          "branch"
        ]
      },
      "UploadRepoInputDto": {
        "type": "object",
        "properties": {
          "include_paths": {
            "description": "Whitebox scope: gitignore-style globs (relative to the repo root) that narrow the scan to matching paths. Empty means the whole repository.",
            "example": [
              "services/gateway/**"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "exclude_paths": {
            "description": "Whitebox scope: gitignore-style globs removed from the scan after include_paths is applied; use `*.md` to drop a file type.",
            "example": [
              "**/tests/**",
              "vendor/",
              "*.md"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "upload"
            ]
          },
          "archive_id": {
            "type": "string",
            "description": "Scan archive ID"
          }
        },
        "required": [
          "source",
          "archive_id"
        ]
      },
      "RestLoginTargetDto": {
        "type": "object",
        "properties": {
          "site": {
            "type": "string",
            "description": "A deployed copy of the app to test signed in, e.g. https://staging.acme.dev",
            "maxLength": 2048
          },
          "login_instructions": {
            "type": "string",
            "description": "How to sign in: the login page, username, password and any steps. Stored encrypted and never returned.",
            "maxLength": 2000
          }
        },
        "required": [
          "site",
          "login_instructions"
        ]
      },
      "RestCreatePentestDto": {
        "type": "object",
        "properties": {
          "target_urls": {
            "description": "Target URLs (pentest only)",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "custom_context": {
            "type": "string",
            "description": "Custom context (pentest only)"
          },
          "application_id": {
            "type": "string",
            "description": "iva application this scan targets (group of repos)"
          },
          "login_targets": {
            "description": "Deployed sites to test signed in, each with how to sign in. On update the list replaces the saved one, and [] removes them. A pentest tests live sites either all signed in or all without a login (target_urls). Check each login with POST /pentests/{id}/login-checks before starting.",
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RestLoginTargetDto"
            }
          },
          "repos": {
            "type": "array",
            "description": "Repositories or uploaded archives to test",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/ConnectedRepoInputDto"
                },
                {
                  "$ref": "#/components/schemas/PublicRepoInputDto"
                },
                {
                  "$ref": "#/components/schemas/UploadRepoInputDto"
                }
              ],
              "discriminator": {
                "propertyName": "source",
                "mapping": {
                  "connected": "#/components/schemas/ConnectedRepoInputDto",
                  "public": "#/components/schemas/PublicRepoInputDto",
                  "upload": "#/components/schemas/UploadRepoInputDto"
                }
              }
            },
            "minItems": 1
          }
        },
        "required": [
          "repos"
        ]
      },
      "RepoDataDto": {
        "type": "object",
        "properties": {
          "include_paths": {
            "description": "Whitebox scope: gitignore-style globs (relative to the repo root) that narrow the scan to matching paths. Empty means the whole repository.",
            "example": [
              "services/gateway/**"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "exclude_paths": {
            "description": "Whitebox scope: gitignore-style globs removed from the scan after include_paths is applied; use `*.md` to drop a file type.",
            "example": [
              "**/tests/**",
              "vendor/",
              "*.md"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "connected",
              "public",
              "upload"
            ]
          },
          "provider": {
            "type": "string",
            "enum": [
              "github",
              "gitlab",
              "bitbucket",
              "azure"
            ],
            "readOnly": true,
            "description": "Resolved by the server at scan start; ignored on input"
          },
          "url": {
            "type": "string",
            "description": "Repository URL",
            "example": "https://github.com/owner/repo"
          },
          "branch": {
            "type": "string",
            "description": "Branch name, tag name, or commit SHA"
          },
          "ref_type": {
            "type": "string",
            "enum": [
              "branch",
              "tag",
              "sha"
            ],
            "description": "How `branch` was selected (UI hint for draft re-use)"
          },
          "archive_id": {
            "type": "string",
            "description": "Scan archive ID"
          },
          "github_installation_id": {
            "type": "number",
            "description": "GitHub App installation ID (connected repos only)"
          }
        }
      },
      "RestPentestLoginTargetDto": {
        "type": "object",
        "properties": {
          "site": {
            "type": "string"
          },
          "login_check": {
            "type": "string",
            "enum": [
              "unverified",
              "pending",
              "running",
              "succeeded",
              "failed",
              "cancelled",
              "expired"
            ],
            "description": "Whether Hacktron could sign in with the login the site has now. A pass lasts an hour, and changing the site or login makes it unverified."
          },
          "failure_reason": {
            "type": "string",
            "nullable": true,
            "description": "Why the check failed, without credentials"
          }
        },
        "required": [
          "site",
          "login_check",
          "failure_reason"
        ]
      },
      "RestPentestResponseDto": {
        "type": "object",
        "properties": {
          "scan_id": {
            "type": "string",
            "format": "uuid",
            "description": "Stable pentest id; task_id changes when it starts"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "completed",
              "failed",
              "stopped",
              "cancelled",
              "skipped",
              "pending_verification",
              "pending_triage",
              "draft",
              "estimating",
              "estimated"
            ]
          },
          "repos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RepoDataDto"
            }
          },
          "target_urls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "login_targets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RestPentestLoginTargetDto"
            }
          },
          "custom_context": {
            "type": "string",
            "nullable": true
          },
          "application_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid"
          },
          "cost_estimation_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid"
          },
          "triage_enabled": {
            "type": "boolean",
            "nullable": true
          },
          "credits_used": {
            "type": "number",
            "nullable": true
          }
        },
        "required": [
          "scan_id",
          "status",
          "repos",
          "target_urls",
          "login_targets",
          "custom_context",
          "application_id",
          "cost_estimation_id",
          "triage_enabled",
          "credits_used"
        ]
      },
      "RestUpdatePentestDto": {
        "type": "object",
        "properties": {
          "target_urls": {
            "description": "Target URLs (pentest only)",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "custom_context": {
            "type": "string",
            "description": "Custom context (pentest only)"
          },
          "application_id": {
            "type": "string",
            "description": "iva application this scan targets (group of repos)"
          },
          "login_targets": {
            "description": "Deployed sites to test signed in, each with how to sign in. On update the list replaces the saved one, and [] removes them. A pentest tests live sites either all signed in or all without a login (target_urls). Check each login with POST /pentests/{id}/login-checks before starting.",
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RestLoginTargetDto"
            }
          },
          "repos": {
            "type": "array",
            "description": "Repositories or uploaded archives to test, replacing the saved ones. Changing them clears the estimate, so estimate again before starting.",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/ConnectedRepoInputDto"
                },
                {
                  "$ref": "#/components/schemas/PublicRepoInputDto"
                },
                {
                  "$ref": "#/components/schemas/UploadRepoInputDto"
                }
              ],
              "discriminator": {
                "propertyName": "source",
                "mapping": {
                  "connected": "#/components/schemas/ConnectedRepoInputDto",
                  "public": "#/components/schemas/PublicRepoInputDto",
                  "upload": "#/components/schemas/UploadRepoInputDto"
                }
              }
            },
            "minItems": 1
          }
        }
      },
      "RestStartPentestDto": {
        "type": "object",
        "properties": {
          "expected_credits": {
            "type": "integer",
            "description": "The total the user confirmed: the estimate's total_credits, plus triage_fee_credits when triage is required or opted in",
            "minimum": 1
          },
          "triage_enabled": {
            "type": "boolean",
            "description": "Opt in to human triage of findings when it is not already required"
          }
        },
        "required": [
          "expected_credits"
        ]
      },
      "RestDiscardPentestResponseDto": {
        "type": "object",
        "properties": {
          "scan_id": {
            "type": "string",
            "format": "uuid"
          },
          "discarded": {
            "type": "boolean"
          }
        },
        "required": [
          "scan_id",
          "discarded"
        ]
      },
      "RequestUploadDto": {
        "type": "object",
        "properties": {
          "file_name": {
            "type": "string",
            "description": "Original filename (e.g. \"my-project.zip\")",
            "example": "my-project.zip"
          },
          "name": {
            "type": "string",
            "description": "Display name (defaults to filename)"
          }
        },
        "required": [
          "file_name"
        ]
      },
      "RequestUploadResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Archive ID"
          },
          "upload_url": {
            "type": "string",
            "description": "Signed GCS upload URL (PUT)"
          },
          "content_type": {
            "type": "string",
            "description": "Content-Type to use in the PUT request",
            "example": "application/zip"
          }
        },
        "required": [
          "id",
          "upload_url",
          "content_type"
        ]
      },
      "PentestCreditBalanceResponseDto": {
        "type": "object",
        "properties": {
          "organization_id": {
            "type": "string",
            "description": "Organization UUID",
            "example": "f336d0bc-b841-465b-8045-024475c079dd"
          },
          "balance": {
            "type": "number",
            "description": "Current pentest credit balance available for use",
            "example": 12000
          },
          "total_purchased": {
            "type": "number",
            "description": "Total pentest credits purchased across all time",
            "example": 16000
          },
          "total_used": {
            "type": "number",
            "description": "Total pentest credits deducted for completed/running pentests",
            "example": 8000
          },
          "total_refunded": {
            "type": "number",
            "description": "Total pentest credits refunded from cancelled pentests",
            "example": 4000
          },
          "total_granted": {
            "type": "number",
            "description": "Total pentest credits granted at no charge",
            "example": 2000
          },
          "used_this_period": {
            "type": "number",
            "nullable": true,
            "description": "Credits deducted since the start of the current billing period, null when the organization has no billing period",
            "example": 1240
          },
          "is_unlimited": {
            "type": "boolean",
            "description": "Whether this organization has internal unlimited pentest entitlement",
            "example": false
          }
        },
        "required": [
          "organization_id",
          "balance",
          "total_purchased",
          "total_used",
          "total_refunded",
          "total_granted",
          "used_this_period",
          "is_unlimited"
        ]
      },
      "RepositoryBatchResultDto": {
        "type": "object",
        "properties": {
          "processed": {
            "type": "number",
            "description": "Keys applied",
            "example": 2
          },
          "failed": {
            "type": "number",
            "description": "Keys that failed",
            "example": 0
          },
          "failedRepositories": {
            "description": "Keys that failed, with the reason",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RepositoryBatchFailureDto"
            }
          },
          "webhookPending": {
            "description": "Keys turned on whose provider webhook could not be registered",
            "example": [],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "processed",
          "failed",
          "failedRepositories",
          "webhookPending"
        ]
      },
      "RepositoryBatchFailureDto": {
        "type": "object",
        "properties": {
          "repo": {
            "type": "string",
            "description": "The key the request named",
            "example": "acme/api"
          },
          "reason": {
            "type": "string",
            "description": "Why the key was not applied",
            "example": "Repository acme/api not found"
          }
        },
        "required": [
          "repo",
          "reason"
        ]
      },
      "RepositoryIdBatchDto": {
        "type": "object",
        "properties": {
          "enable": {
            "description": "Ids from the repository list of the repositories to turn on",
            "example": [
              "123e4567-e89b-12d3-a456-426614174000"
            ],
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "disable": {
            "description": "Ids from the repository list of the repositories to turn off",
            "example": [],
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "required": [
          "enable",
          "disable"
        ]
      },
      "RestPrReviewSettingsDto": {
        "type": "object",
        "properties": {
          "scm_comments_enabled": {
            "type": "boolean",
            "description": "Whether Hacktron publishes comments and finding details to connected source control pull and merge requests"
          },
          "scm_system_comments_enabled": {
            "type": "boolean",
            "description": "Whether Hacktron posts system comments such as skipped reviews, usage limits, and configuration warnings. Defaults to true. Requires scm_comments_enabled."
          },
          "fail_on_severity": {
            "type": "string",
            "description": "Org-wide default fail_on severity threshold for PR/MR checks. A repo's .hacktron/config.yaml fail_on.severity overrides this. Send null to disable.",
            "enum": [
              "critical",
              "high",
              "medium",
              "low",
              "info"
            ],
            "nullable": true
          },
          "scan_include_branches": {
            "description": "Org-wide default target branch patterns to scan PRs/MRs for (null = all branches). Glob patterns (`*`, `**`, `?`, `{a,b}`), case-insensitive. A repo's .hacktron/config.yaml include.branches overrides this.",
            "example": [
              "main",
              "**/release/**"
            ],
            "nullable": true,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scan_exclude_branches": {
            "description": "Org-wide default target branch patterns to exclude from PR/MR scans (null = none). Takes precedence over scan_include_branches. A repo's .hacktron/config.yaml exclude.branches overrides this.",
            "example": [
              "**/release/legacy/**"
            ],
            "nullable": true,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scan_include_labels": {
            "description": "Org-wide default labels to require on PRs/MRs for scanning (null = any). A repo's .hacktron/config.yaml include.labels overrides this.",
            "example": [
              "feature",
              "bugfix"
            ],
            "nullable": true,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scan_exclude_labels": {
            "description": "Org-wide default labels to exclude PR/MR scans for (null = none). Takes precedence over scan_include_labels. A repo's .hacktron/config.yaml exclude.labels overrides this.",
            "example": [
              "wip",
              "no-scan"
            ],
            "nullable": true,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scan_include_authors": {
            "description": "Org-wide default author patterns to require on PRs/MRs for scanning (null = any). Glob patterns (`*`, `**`, `?`, `{a,b}`), case-insensitive. A repo's .hacktron/config.yaml include.authors overrides this.",
            "example": [
              "alice",
              "bob"
            ],
            "nullable": true,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scan_exclude_authors": {
            "description": "Org-wide default author patterns to exclude PR/MR scans for (null = none). Glob patterns (`*`, `**`, `?`, `{a,b}`), case-insensitive. Takes precedence over scan_include_authors. A repo's .hacktron/config.yaml exclude.authors overrides this.",
            "example": [
              "dependabot[bot]",
              "renovate[bot]",
              "*-bot"
            ],
            "nullable": true,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scan_include_keywords": {
            "description": "Org-wide default title keywords to require on PRs/MRs for scanning (null = any). Case-insensitive substring match. A repo's .hacktron/config.yaml include.keywords overrides this.",
            "example": [
              "release",
              "security"
            ],
            "nullable": true,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scan_exclude_keywords": {
            "description": "Org-wide default title keywords to exclude PR/MR scans for (null = none). Case-insensitive substring match. A repo's .hacktron/config.yaml exclude.keywords overrides this.",
            "example": [
              "[exclude hacktron]",
              "wip"
            ],
            "nullable": true,
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "api-key": []
    }
  ]
}
