openapi: 3.1.0
info:
  title: HAIEC Assurance API
  version: "1.0.0"
  description: |
    External v1 surface for the HAIEC assurance pipeline. The API invokes the
    same canonical services as the HAIEC dashboard: createRun → engines →
    persisted Assurance Evaluation → summary / report / passport reads.

    Authentication is a Bearer API key. Authorization is scope-based; the
    organization is always derived server-side from the key record — never
    from a caller-supplied organizationId. Cross-organization resources are
    non-enumerating (indistinguishable 404). Keys may carry an expiration;
    revoked or expired keys return 401.

    ## Assurance API vs Evidence Intake API

    This document describes the **Assurance API** (`/api/v1/*`). A second,
    related surface — the **Evidence Intake API** — accepts supported
    evidence through the canonical machine-ingest routes and shares the same
    Bearer credential:

      POST /api/ingest/structured   — structured events (json/jsonl/csv payload)
      POST /api/ingest/log          — raw log lines
      POST /api/otlp/v1/traces      — OTLP traces (JSON or protobuf)
      POST /api/otlp/v1/metrics     — OTLP metrics
      POST /api/otlp/v1/logs        — OTLP logs

    Evidence intake requires the `evidence:ingest` scope and a configured
    environment binder (discover via `GET /api/v1/evidence/binders`). Every
    intake response is an ingestion receipt only: `EVIDENCE_INGESTED` does
    not mean `EVIDENCE_EVALUATED`, `GAP_CLOSED`, or `ASSURANCE_CHANGED`.
    To evaluate newly ingested evidence, attach the receipt's
    `producerRunId` to a NEW assurance run via
    `externalEvidenceAttachments` with `producerId: structured-ingress`.
    Historical evaluations are immutable.

    Recommended agent read sequence: create run → poll run →
    `GET .../summary` → `GET .../agent-audit` →
    `GET .../master-report` (bounded, the default) →
    `GET .../master-report?detail=full` only when deeper analysis is
    required. `GET .../report` and `GET .../report/pdf` remain available
    as the backwards-compatible Assurance Evidence artifacts.

    Artifact distinction — the **Master Assurance Report** is the rich
    canonical report product (Four Assurance Questions, Evaluation-bound
    scenario snapshot, links, limitations). The **Assurance Evidence
    Report** (`/report`, `/report/pdf`) is the legacy profile-scoped
    evidence bundle — a secondary artifact, not a replacement.
    MASTER_REPORT != DECISION_RECEIPT and MASTER_REPORT != PASSPORT;
    INVESTIGATION != EVALUATION — the linked forensic investigation may
    contain evidence received after the Evaluation; the report stays
    bound to the frozen snapshot.
  contact:
    name: HAIEC
    url: https://www.haiec.com/api-platform
servers:
  - url: https://www.haiec.com/api/v1
    description: Production
tags:
  - name: Runs
    description: Assurance run lifecycle
  - name: Evaluations
    description: Persisted evaluation artifacts
  - name: Discovery
    description: Read-only AI System and source discovery
  - name: Evidence
    description: Evidence binder discovery for the canonical intake routes
paths:
  /assurance/runs:
    post:
      tags: [Runs]
      summary: Create and start an assurance run
      description: |
        Creates an audit-orchestrator run for an organization-bound AI System
        and starts the canonical engine chain. Asynchronous — poll the run
        status for the evaluationId.

        Idempotency: pass `Idempotency-Key` (scoped to organization + API key,
        24h TTL). Same key + same payload returns the original run; same key +
        different payload returns 409 IDEMPOTENCY_CONFLICT.
      operationId: createAssuranceRun
      security:
        - bearerAuth: []
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
          description: Caller-generated deduplication key (scoped to org + API key).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateRunRequest"
      responses:
        "202":
          description: Run created and started.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RunEnvelope"
        "200":
          description: Idempotent replay — the original run's current status.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RunEnvelope"
        "400":
          $ref: "#/components/responses/ApiError"
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
        "409":
          $ref: "#/components/responses/ApiError"
        "429":
          $ref: "#/components/responses/ApiError"
    get:
      tags: [Runs]
      summary: List assurance runs
      operationId: listAssuranceRuns
      security:
        - bearerAuth: []
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 50
        - name: status
          in: query
          schema:
            type: string
      responses:
        "200":
          description: Paginated run list.
          content:
            application/json:
              schema:
                type: object
                properties:
                  runs:
                    type: array
                    items:
                      $ref: "#/components/schemas/RunListItem"
                  page:
                    type: integer
                  limit:
                    type: integer
                  total:
                    type: integer
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "429":
          $ref: "#/components/responses/ApiError"
  /assurance/runs/{runId}:
    get:
      tags: [Runs]
      summary: Get assurance run status
      operationId: getAssuranceRun
      security:
        - bearerAuth: []
      parameters:
        - name: runId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Run status envelope with evaluation identity and links when available.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RunEnvelope"
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
        "429":
          $ref: "#/components/responses/ApiError"
  /assurance/evaluations/{evaluationId}/summary:
    get:
      tags: [Evaluations]
      summary: Get evaluation summary
      description: Compact summary for the exact persisted evaluation — same canonical service as the dashboard.
      operationId: getEvaluationSummary
      security:
        - bearerAuth: []
      parameters:
        - name: evaluationId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Exact-evaluation summary.
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
  /assurance/evaluations/{evaluationId}/master-report:
    get:
      tags: [Evaluations]
      summary: Get the canonical Master Assurance Report
      description: |
        The canonical Master Assurance Report product for one exact
        persisted Evaluation — the same product object the dashboard HTML
        report, the Master Report PDF, and the MCP `haiec_get_master_report`
        tool consume. `detail=bounded` (default) returns identity,
        disposition, digests, the Four Assurance Questions, the
        Evaluation-bound scenario snapshot summary, links, and
        limitations. `detail=full` additionally returns the complete
        report projection and evaluation-bound supporting read models.

        No 'latest' resolution, no U5 recomputation, no current
        Investigation substitution. Supplemental current-state context
        (when present under detail=full) is machine-marked
        `timeBasis: CURRENT_CONTEXT` / `truthRole: NON_EVALUATION_CONTEXT`
        and never affects the disposition, the Four Questions, the
        scenario snapshot, or the truth digests.
      operationId: getEvaluationMasterReport
      security:
        - bearerAuth: []
      parameters:
        - name: evaluationId
          in: path
          required: true
          schema:
            type: string
        - name: detail
          in: query
          schema:
            type: string
            enum: [bounded, full]
            default: bounded
      responses:
        "200":
          description: Canonical Master Report product (bounded by default).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MasterReportResponse"
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
  /assurance/evaluations/{evaluationId}/master-report/pdf:
    get:
      tags: [Evaluations]
      summary: Get the Master Assurance Report PDF
      description: |
        PDF rendering of the same canonical Master Report product —
        MASTER_REPORT_HTML_TRUTH == MASTER_REPORT_PDF_TRUTH. Presentation
        bounds are explicit: any omitted items are announced with an
        on-page omitted count. PDF != TRUTH_ENGINE.
      operationId: getEvaluationMasterReportPdf
      security:
        - bearerAuth: []
      parameters:
        - name: evaluationId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: PDF bytes.
          content:
            application/pdf: {}
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
        "503":
          $ref: "#/components/responses/ApiError"
  /assurance/evaluations/{evaluationId}/report:
    get:
      tags: [Evaluations]
      summary: Get the Assurance Evidence report (secondary artifact)
      description: |
        Backwards-compatible Assurance Evidence bundle projection. This is
        NOT the Master Assurance Report — prefer
        `GET .../master-report` for the canonical rich report product.
      operationId: getEvaluationReport
      security:
        - bearerAuth: []
      parameters:
        - name: evaluationId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Canonical evidence-bearing assurance bundle.
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
  /assurance/evaluations/{evaluationId}/agent-audit:
    get:
      tags: [Evaluations]
      summary: Get the deterministic Agent Audit for an evaluation
      description: |
        Projection of the same deterministic agent-audit report the HAIEC
        Master Report uses — purpose-built for coding agents. Carries
        `narrative.established`, `narrative.unestablished`,
        `narrative.notAssessed`, `narrative.evidenceGaps`,
        `narrative.limitations`, `authoritySummary`, and
        `verificationItems[]` (what HAIEC found, what it establishes, what
        it did not establish, and the evidence HAIEC says is still needed).

        No recomputation and no LLM: statuses UNKNOWN / NOT_ASSESSED /
        EVIDENCE_NEEDED pass through verbatim.
      operationId: getEvaluationAgentAudit
      security:
        - bearerAuth: []
      parameters:
        - name: evaluationId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Deterministic agent-audit projection for the exact persisted evaluation.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AgentAuditResponse"
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
  /assurance/evaluations/{evaluationId}/passport:
    get:
      tags: [Evaluations]
      summary: Get evaluation passport
      operationId: getEvaluationPassport
      security:
        - bearerAuth: []
      parameters:
        - name: evaluationId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Portable machine-readable artifact bound to the exact evaluation.
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
  /assurance/evaluations/{evaluationId}/report/pdf:
    get:
      tags: [Evaluations]
      summary: Get the Assurance Evidence PDF (secondary artifact)
      description: |
        Profile-scoped Assurance Evidence PDF — the legacy evidence-bundle
        renderer, retained for backwards compatibility. This is NOT the
        Master Assurance Report — prefer
        `GET .../master-report/pdf` for the canonical report PDF.
        No analysis is rerun.
      operationId: getEvaluationReportPdf
      security:
        - bearerAuth: []
      parameters:
        - name: evaluationId
          in: path
          required: true
          schema:
            type: string
        - name: profile
          in: query
          schema:
            type: string
            enum: [executive, technical, auditor]
            default: executive
        - name: pageSize
          in: query
          schema:
            type: string
            enum: [A4, LETTER]
            default: A4
      responses:
        "200":
          description: PDF bytes.
          content:
            application/pdf: {}
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
        "503":
          $ref: "#/components/responses/ApiError"
  /systems:
    get:
      tags: [Discovery]
      summary: List AI Systems
      description: Read-only discovery of the key's organization AI Systems. Systems are provisioned in the dashboard.
      operationId: listSystems
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Organization AI Systems.
          content:
            application/json:
              schema:
                type: object
                properties:
                  systems:
                    type: array
                    items:
                      $ref: "#/components/schemas/AiSystem"
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
  /systems/{systemId}/evaluation-sources:
    get:
      tags: [Discovery]
      summary: List a system's evaluation sources
      description: |
        Eligibility preflight for the system's source repositories — the same
        canonical preflight the dashboard uses. Only VERIFIED, system-bound,
        non-retired SOURCE_REPOSITORY assets are usable for fresh scans.
      operationId: listEvaluationSources
      security:
        - bearerAuth: []
      parameters:
        - name: systemId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Evaluation-source preflight for the AI System.
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
  /scans:
    post:
      tags: [Runs]
      summary: Submit a qualified local or CI scan artifact
      description: |
        Evidence admission only. The scanner runs on the developer machine,
        IDE, or CI runner. HAIEC validates the existing Evidence Bundle schema,
        content hash, producer identity, AI System binding, and local workspace
        identity, then persists an attachable producer scan. This endpoint does
        not run a second analysis engine.
      operationId: submitQualifiedScan
      security:
        - bearerAuth: []
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/QualifiedScanSubmission"
      responses:
        "201":
          description: Qualified scan accepted and attachable to an Assurance Run.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/QualifiedScanAccepted"
        "400":
          $ref: "#/components/responses/ApiError"
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
        "413":
          $ref: "#/components/responses/ApiError"
  /evidence/binders:
    get:
      tags: [Evidence]
      summary: List configured evidence binders
      description: |
        Read-only discovery of the environment binders an agent may target
        through the canonical Evidence Intake routes. Returns only the
        metadata needed to choose a destination — never credentials, token
        material, or field mappings. Requires scope `source:read`; evidence
        submission itself requires `evidence:ingest`.

        If no suitable binder exists, the source must be connected in the
        HAIEC dashboard first — binder creation is not exposed over the API.
      operationId: listEvidenceBinders
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Organization-bound evidence binders and the canonical intake routes.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EvidenceBinderList"
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
  /scans/{scanId}:
    get:
      tags: [Runs]
      summary: Get qualified scan submission status
      operationId: getQualifiedScan
      security:
        - bearerAuth: []
      parameters:
        - name: scanId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Organization-bound scan provenance and attachment reference.
        "401":
          $ref: "#/components/responses/ApiError"
        "403":
          $ref: "#/components/responses/ApiError"
        "404":
          $ref: "#/components/responses/ApiError"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        HAIEC API key (haiec_live_... or haiec_test_...). Capability is
        scope-based: scan:submit, scan:create, scan:read, report:read,
        system:read, source:read, evidence:ingest.

        `evidence:ingest` authorizes the Evidence Intake routes
        (/api/ingest/*, /api/otlp/v1/*) and is granted only through an
        explicit key purpose — never by role defaults. The `assurance-agent`
        purpose profile is intended for coding agents: run Assurance, read
        reports/agent-audit, discover systems/sources, submit supported
        evidence. It cannot administer HAIEC, manage membership, or access
        GitHub credentials/repositories beyond the GitHub App authorization.
  schemas:
    CreateRunRequest:
      type: object
      required: [aiSystemId, engines]
      properties:
        aiSystemId:
          type: string
          description: Organization-bound AI System ID.
        engines:
          type: object
          properties:
            static:
              type: object
              properties:
                enabled:
                  type: boolean
                executionMode:
                  type: string
                  enum: [ui, api, ci-attached, ci-triggered, reused]
                  description: |
                    `api` = fresh scan of a bound VERIFIED source.
                    `ci-attached`/`reused` = bind an existing CI-produced scan
                    via attachedScanId.
                sourceAssetId:
                  type: string
                  description: Verified SOURCE_REPOSITORY asset bound to the AI System.
                repositoryUrl:
                  type: string
                  description: Must resolve to a bound source asset — arbitrary URLs are rejected.
                branch:
                  type: string
                attachedScanId:
                  type: string
            runtime:
              type: object
              description: Same shape and authorization safeguards as the dashboard runtime engine config.
            wizard:
              type: object
              properties:
                enabled:
                  type: boolean
                framework:
                  type: string
                assessmentId:
                  type: string
        jurisdiction:
          type: string
          nullable: true
          enum: [nyc_ll144, colorado_ai, eu_ai_act, null]
        externalEvidenceAttachments:
          type: array
          items:
            type: object
            properties:
              producerId:
                type: string
                enum: [ci-cd-scanner, sarif-import, structured-ingress]
                description: |
                  `structured-ingress` binds a canonical ingestion batch —
                  use the `producerRunId` returned by an Evidence Intake
                  receipt. Attachment set is frozen at run creation.
              producerRunId:
                type: string
    RunEnvelope:
      type: object
      properties:
        runId:
          type: string
        status:
          type: string
          description: Uppercased canonical orchestrator run status.
        stage:
          type: string
          nullable: true
          description: Current engine, when in progress.
        createdAt:
          type: string
          format: date-time
        startedAt:
          type: string
          format: date-time
          nullable: true
        completedAt:
          type: string
          format: date-time
          nullable: true
        aiSystemId:
          type: string
          nullable: true
        failure:
          type: object
          nullable: true
          properties:
            code:
              type: string
            engine:
              type: string
              nullable: true
            message:
              type: string
            retryable:
              type: boolean
        evaluation:
          type: object
          nullable: true
          properties:
            evaluationId:
              type: string
            status:
              type: string
            disposition:
              type: string
              nullable: true
              description: Canonical ALLOW / REVIEW / BLOCK — bounded to evaluated scope/evidence.
            methodologyVersion:
              type: string
              nullable: true
            createdAt:
              type: string
              format: date-time
        links:
          type: object
          description: All evaluation links are null until the run persists an Evaluation.
          properties:
            self:
              type: string
            summary:
              type: string
              nullable: true
            report:
              type: string
              nullable: true
              description: Assurance Evidence bundle API (secondary artifact).
            masterReport:
              type: string
              nullable: true
              description: Canonical Master Assurance Report API — same product as the dashboard HTML report.
            masterReportPdf:
              type: string
              nullable: true
              description: Master Assurance Report PDF route.
            agentAudit:
              type: string
              nullable: true
              description: Deterministic agent-audit projection for the persisted evaluation.
            passport:
              type: string
              nullable: true
            pdf:
              type: string
              nullable: true
              description: Assurance Evidence PDF route (secondary artifact — not the Master Report PDF).
            dashboard:
              type: string
              nullable: true
              description: Dashboard URL of the persisted evaluation (requires dashboard session).
            dashboardEvaluation:
              type: string
              nullable: true
            dashboardMasterReport:
              type: string
              nullable: true
              description: Dashboard Master Report URL — redirects to the canonical document page.
            dashboardSystemWorkspace:
              type: string
              nullable: true
            dashboardAssurance:
              type: string
              nullable: true
            dashboardReports:
              type: string
              nullable: true
    MasterReportResponse:
      type: object
      description: |
        `masterReport` is the canonical Master Report product. With
        `detail=bounded` (default) it carries the bounded view below;
        `detail=full` returns the complete product including the full
        projection and supporting read models (current-state entries are
        marked `timeBasis: CURRENT_CONTEXT`).
      properties:
        evaluationId:
          type: string
        masterReport:
          type: object
          properties:
            schemaVersion:
              type: string
            timeBasis:
              type: string
              enum: [EVALUATED_SNAPSHOT]
              description: Core report truth is bound to the exact frozen Evaluation.
            evaluationId:
              type: string
            aiSystemId:
              type: string
              nullable: true
            disposition:
              type: string
              description: Canonical U5 ALLOW / REVIEW / BLOCK — verbatim, never re-derived.
            methodologyVersion:
              type: string
              nullable: true
            profile:
              type: string
              enum: [BASE, EXECUTIVE]
            reportId:
              type: string
              nullable: true
            reportVersion:
              type: string
            projectionVersion:
              type: string
            coreTruthDigest:
              type: string
            evidenceBundleDigest:
              type: string
              nullable: true
            fourQuestions:
              type: object
              description: |
                Deterministic Four Assurance Questions projection.
                reach — declared vs code-capable vs unresolved reach
                (DECLARED_SURFACE != CODE_CAPABLE_REACH);
                authority — five independent planes plus per-action
                authority context; observed — exact observed actions, never
                "did not occur" when evidence is missing; proofBoundary —
                verbatim unresolved frontier and next-evidence needs.
            evaluationScenarioSnapshot:
              type: object
              description: |
                Evaluation-bound scenario context built ONLY over the
                Evaluation's frozen evidence membership — status, states,
                declared order (never timestamps), transitions, earliest
                established divergence, snapshotDigest, limitations.
            links:
              type: object
              properties:
                html:
                  type: string
                pdf:
                  type: string
                api:
                  type: string
                apiPdf:
                  type: string
                evaluation:
                  type: string
                  nullable: true
                agentAudit:
                  type: string
                passport:
                  type: string
                assuranceReport:
                  type: string
                assuranceEvidencePdf:
                  type: string
                decisionReceipt:
                  type: string
                  nullable: true
                systemWorkspace:
                  type: string
                  nullable: true
                investigation:
                  type: string
                  nullable: true
                  description: Current Investigation — may contain evidence received after this Evaluation.
            limitations:
              type: array
              items:
                type: string
            semantics:
              type: array
              items:
                type: string
    RunListItem:
      type: object
      properties:
        runId:
          type: string
        aiSystemId:
          type: string
          nullable: true
        status:
          type: string
        stage:
          type: string
          nullable: true
        staticExecutionMode:
          type: string
          nullable: true
        jurisdiction:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
        startedAt:
          type: string
          format: date-time
          nullable: true
        completedAt:
          type: string
          format: date-time
          nullable: true
        links:
          type: object
          properties:
            self:
              type: string
    AiSystem:
      type: object
      properties:
        aiSystemId:
          type: string
        name:
          type: string
        systemType:
          type: string
          nullable: true
        criticality:
          type: string
          nullable: true
        lifecycleStatus:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
    QualifiedScanSubmission:
      type: object
      required: [aiSystemId, producerId, origin, sourceIdentity, bundle]
      properties:
        aiSystemId:
          type: string
        producerId:
          type: string
          enum: [ci-cd-scanner]
        origin:
          type: string
          enum: [local, ide, ci]
        sourceIdentity:
          type: object
          required: [version, sourceKind, dirty, workspaceDigest, pathSetDigest]
          properties:
            version:
              type: string
            sourceKind:
              type: string
              enum: [LOCAL_WORKSPACE]
            gitRemote:
              type: string
              nullable: true
            gitCommit:
              type: string
              nullable: true
            branch:
              type: string
              nullable: true
            dirty:
              oneOf:
                - type: boolean
                - type: string
                  enum: [unknown]
            workspaceDigest:
              type: string
            pathSetDigest:
              type: string
        bundle:
          type: object
          description: Existing Evidence Bundle v1.0.0; raw source files/snippets are not accepted as part of this contract.
        commitSha:
          type: string
          nullable: true
        branch:
          type: string
          nullable: true
    QualifiedScanAccepted:
      type: object
      properties:
        scanId:
          type: string
        status:
          type: string
          enum: [COMPLETED]
        aiSystemId:
          type: string
        sourceIdentity:
          $ref: "#/components/schemas/QualifiedScanSubmission/properties/sourceIdentity"
        qualifiedEvidence:
          type: object
          properties:
            schemaVersion:
              type: string
            producerId:
              type: string
            contentHash:
              type: string
            limitations:
              type: array
              items:
                type: string
        attach:
          type: object
          properties:
            executionMode:
              type: string
            attachedScanId:
              type: string
    AgentAuditResponse:
      type: object
      description: |
        Deterministic projection of the persisted evaluation for coding
        agents. The `agentAudit` payload is produced by the same canonical
        builder the Master Report uses; statuses such as UNKNOWN,
        NOT_ASSESSED, and EVIDENCE_NEEDED are verbatim, never upgraded.
      properties:
        evaluationId:
          type: string
        agentAudit:
          type: object
          description: |
            Canonical agent-audit report. Key members:
            - sections — ordered report sections
            - narrative.established — what HAIEC established
            - narrative.unestablished — material facts not established
            - narrative.notAssessed — explicitly not-assessed areas
            - narrative.evidenceGaps — exact evidence gaps
            - narrative.limitations — bounded limitations
            - authoritySummary — authority-plane state
            - verificationItems[] — per-item: whatHaiecFound,
              whatItEstablishes, whatHaiecDidNotEstablish, whyItMatters,
              verificationNeeded, affectedQuestionIds, affectedPathIds,
              evidenceRefs, relationIds, boundary
            `verificationNeeded` is the authoritative evidence request — do
            not invent evidence requirements beyond it.
    EvidenceBinderList:
      type: object
      properties:
        binders:
          type: array
          items:
            type: object
            properties:
              binderId:
                type: string
                description: Pass as `binderId` (body/query/header) to the Evidence Intake routes.
              sourceSystem:
                type: string
              domain:
                type: string
                nullable: true
              aiSystemId:
                type: string
                nullable: true
                description: AI System the binder is bound to, when bound. Ingested batches inherit this binding.
              adapterId:
                type: string
              adapterVersion:
                type: string
              binderVersion:
                type: string
              accessMethod:
                type: string
              active:
                type: boolean
                description: Inactive binders reject ingestion — do not target them.
              sourceAuthorityRole:
                type: string
                nullable: true
                description: Authority ceiling for all records under this binder.
              supportedEvidenceClasses:
                type: array
                items:
                  type: string
              canEstablish:
                type: array
                items:
                  type: string
              cannotEstablish:
                type: array
                items:
                  type: string
              coverageSemantics:
                type: object
                nullable: true
              requireEventId:
                type: boolean
              maxRecordBytes:
                type: integer
                nullable: true
              limitations:
                type: array
                items:
                  type: object
        intake:
          type: object
          description: Evidence Intake API contract — same Bearer credential, evidence:ingest scope.
          properties:
            authentication:
              type: string
              enum: [bearer]
            requiredScope:
              type: string
              enum: [evidence:ingest]
            routes:
              type: object
              properties:
                structured:
                  type: string
                logs:
                  type: string
                otlpTraces:
                  type: string
                otlpMetrics:
                  type: string
                otlpLogs:
                  type: string
    ApiErrorBody:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - UNAUTHORIZED
                - INSUFFICIENT_SCOPE
                - INVALID_REQUEST
                - AI_SYSTEM_NOT_FOUND
                - SOURCE_NOT_VERIFIED
                - SOURCE_CONFLICTED
                - SOURCE_UNAVAILABLE
                - SOURCE_AMBIGUOUS
                - BRANCH_REQUIRED
                - CONSENT_REQUIRED
                - RATE_LIMITED
                - RUN_NOT_FOUND
                - RUN_FAILED
                - RUN_CONFLICT
                - IDEMPOTENCY_CONFLICT
                - RESOURCE_NOT_FOUND
                - INTERNAL_ERROR
            message:
              type: string
            retryable:
              type: boolean
  responses:
    ApiError:
      description: Machine-readable error envelope.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ApiErrorBody"
