# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from typing import List, Union, Optional
from typing_extensions import Literal, Annotated, TypeAlias

from ..._utils import PropertyInfo
from ..._models import BaseModel

__all__ = [
    "ScanCreateResponse",
    "Report",
    "ReportReport",
    "ReportReportSummary",
    "ReportReportTest",
    "ReportReportTestStep",
    "ReportReportTestStepAssertion",
    "ReportReportTestStepAssertionKind",
    "ReportReportTestStepAssertionKindParameters",
    "ReportReportTestStepError",
    "ReportReportTestStepRequest",
    "ReportReportTestStepRequestCredentialSet",
    "ReportReportTestStepRequestVariableCapture",
    "ReportReportTestStepResponse",
    "ReportReportTestStepResponseBody",
    "ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseNotFound",
    "ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseBytes",
    "ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseText",
    "ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseJson",
    "ReportReportTestPreflightError",
]


class ReportReportSummary(BaseModel):
    """Summary of all steps and findings."""

    verdict: Literal["ok", "warning", "inconclusive"]
    """Overall verdict of the vulnerability scan."""


class ReportReportTestStepAssertionKindParameters(BaseModel):
    """Range of HTTP status codes."""

    max: int
    """Maximum (inclusive) status code of the range."""

    min: int
    """Minimum (inclusive) status code of the range."""


class ReportReportTestStepAssertionKind(BaseModel):
    """Kind of assertion."""

    parameters: ReportReportTestStepAssertionKindParameters
    """Range of HTTP status codes."""

    type: Literal["http_status_within_range"]


class ReportReportTestStepAssertion(BaseModel):
    """Assertion that was made against the received response."""

    description: str
    """Human-readable description of the assertion, explaining what was checked."""

    kind: ReportReportTestStepAssertionKind
    """Kind of assertion."""

    observed: Optional[int] = None
    """Observed value on which the assertion was made."""

    outcome: Literal["ok", "fail", "inconclusive"]
    """Outcome of the assertion."""


class ReportReportTestStepError(BaseModel):
    """Error that occurred during a test."""

    description: str
    """Human-readable error description."""

    error_code: Optional[int] = None
    """Numeric error code identifying the class of error, if available."""


class ReportReportTestStepRequestCredentialSet(BaseModel):
    """Credential set that was used."""

    id: str
    """ID of the credential set."""

    role: Literal["owner", "attacker"]
    """Role of the credential set."""


class ReportReportTestStepRequestVariableCapture(BaseModel):
    """A variable to capture from the response body."""

    json_path: str
    """JSONPath expression used for capture, e.g. `"$.id"`."""

    name: str
    """Variable name, e.g. `"resource_id"`."""


class ReportReportTestStepRequest(BaseModel):
    """HTTP request that was made, if any."""

    credential_set: ReportReportTestStepRequestCredentialSet
    """Credential set that was used."""

    header_names: List[str]
    """Names of headers that were sent."""

    method: Literal["GET", "DELETE", "PATCH", "POST", "PUT"]
    """HTTP method."""

    url: str
    """Exact and full URL (including host, query parameters) that was requested."""

    variable_captures: List[ReportReportTestStepRequestVariableCapture]
    """Variable captures requested for this step."""

    body: Optional[object] = None
    """Request body, if any."""


class ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseNotFound(BaseModel):
    """No body was received."""

    kind: Literal["not_found"]


class ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseBytes(BaseModel):
    """Body received but unable to read as UTF-8. Raw bytes, base64-encoded."""

    contents: str

    kind: Literal["bytes"]

    truncated: bool


class ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseText(BaseModel):
    """Body received as valid UTF-8 text but not valid JSON."""

    contents: str

    kind: Literal["text"]

    truncated: bool


class ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseJson(BaseModel):
    """Body received as valid JSON."""

    contents: str

    kind: Literal["json"]

    truncated: bool


ReportReportTestStepResponseBody: TypeAlias = Annotated[
    Union[
        ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseNotFound,
        ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseBytes,
        ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseText,
        ReportReportTestStepResponseBodyVulnScannerBOLABodyResponseJson,
    ],
    PropertyInfo(discriminator="kind"),
]


class ReportReportTestStepResponse(BaseModel):
    """HTTP response that was received, if any."""

    body: ReportReportTestStepResponseBody
    """HTTP response body."""

    header_names: List[str]
    """Names of headers that were received."""

    status: int
    """HTTP status code."""

    status_text: Optional[str] = None
    """HTTP status text, if available for the status code."""


class ReportReportTestStep(BaseModel):
    """A single step in a test."""

    assertions: List[ReportReportTestStepAssertion]
    """Assertions that were made against the received response."""

    errors: Optional[List[ReportReportTestStepError]] = None
    """Errors the step encountered that may explain absent or incomplete fields."""

    request: Optional[ReportReportTestStepRequest] = None
    """HTTP request that was made, if any."""

    response: Optional[ReportReportTestStepResponse] = None
    """HTTP response that was received, if any."""


class ReportReportTestPreflightError(BaseModel):
    """Error that occurred during a test."""

    description: str
    """Human-readable error description."""

    error_code: Optional[int] = None
    """Numeric error code identifying the class of error, if available."""


class ReportReportTest(BaseModel):
    """Result of a single test."""

    steps: List[ReportReportTestStep]
    """Steps that were executed."""

    verdict: Literal["ok", "warning", "inconclusive"]
    """Verdict of this single test."""

    preflight_errors: Optional[List[ReportReportTestPreflightError]] = None
    """Errors that prevented step execution."""


class ReportReport(BaseModel):
    """Version 1 of the BOLA vulnerability scan report."""

    summary: ReportReportSummary
    """Summary of all steps and findings."""

    tests: List[ReportReportTest]
    """List of tests that were run."""


class Report(BaseModel):
    """Vulnerability report produced after the scan completes.

    The shape depends on the scan type. Present only for finished scans.
    """

    report: ReportReport
    """Version 1 of the BOLA vulnerability scan report."""

    report_schema_version: Literal["v1"]
    """Version of the report schema."""


class ScanCreateResponse(BaseModel):
    id: str
    """Scan identifier."""

    scan_type: Literal["bola"]
    """The type of vulnerability scan."""

    status: Literal["created", "scheduled", "planning", "running", "finished", "failed"]
    """Current lifecycle status of the scan."""

    target_environment_id: str
    """The target environment this scan runs against."""

    report: Optional[Report] = None
    """Vulnerability report produced after the scan completes.

    The shape depends on the scan type. Present only for finished scans.
    """
