openapi: 3.1.0
info:
  title: AgentFit
  version: 1.0.0
  description: |
    Audit public API documentation for AI/agent-readiness against the 26-criteria rubric
    defined at https://gumeniuk.com/en/tech/api-docs-llm-era/.

    Output JSON is byte-compatible with the LLM-audit prompt described in the article,
    so a human can compare an LLM-driven audit and this service's code-driven audit
    side by side.
  contact:
    name: Stanislav Gumeniuk
    email: i@gumeniuk.com
  license:
    name: Private
servers:
  - url: http://localhost:8080
    description: local development
  - url: https://agentfit.dev
    description: production (planned — not yet deployed)
paths:
  /healthz:
    get:
      summary: Liveness probe
      operationId: healthz
      responses:
        '200':
          description: Service is alive
          content:
            application/json:
              schema:
                type: object
                required: [status, version]
                properties:
                  status: { type: string, example: ok }
                  version: { type: string, example: v1.2.8 }
  /openapi.yaml:
    get:
      summary: This OpenAPI specification
      operationId: openapi
      responses:
        '200':
          description: OK
          content:
            application/yaml:
              schema:
                type: string
  /audit:
    post:
      summary: Run an AI-readiness audit
      operationId: audit
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuditRequest'
            example:
              base_url: https://docs.stripe.com
      responses:
        '200':
          description: Audit completed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuditReport'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Target URL unreachable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '504':
          description: Audit exceeded timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    AuditRequest:
      type: object
      required: [base_url]
      properties:
        base_url:
          type: string
          format: uri
          description: Root URL of the documentation site, no trailing slash.
          example: https://docs.stripe.com
    AuditReport:
      type: object
      required:
        - base_url
        - audit_date
        - auditor
        - e1_gating_passed
        - unreliable_marker
        - total_score
        - max_score
        - categories
        - criteria
      properties:
        base_url:
          type: string
          format: uri
        audit_date:
          type: string
          format: date
          example: "2026-05-15"
        auditor:
          type: string
          example: agentfit/v1.3.34
        e1_gating_passed:
          type: boolean
          description: True when E1 (no-JS content visibility) scored > 0.
        unreliable_marker:
          type: boolean
          description: True when E1 failed OR when the VK-trap (duplicate bodies across URLs) was detected.
        total_score:
          type: integer
          minimum: 0
          maximum: 100
        max_score:
          type: integer
          enum: [100]
        categories:
          type: object
          required: [A_discovery, B_page_artifacts, C_api_spec, D_content, E_hygiene, F_agent_surface]
          properties:
            A_discovery: { $ref: '#/components/schemas/CategoryScore' }
            B_page_artifacts: { $ref: '#/components/schemas/CategoryScore' }
            C_api_spec: { $ref: '#/components/schemas/CategoryScore' }
            D_content: { $ref: '#/components/schemas/CategoryScore' }
            E_hygiene: { $ref: '#/components/schemas/CategoryScore' }
            F_agent_surface: { $ref: '#/components/schemas/CategoryScore' }
        criteria:
          type: array
          items: { $ref: '#/components/schemas/CriterionResult' }
          minItems: 30
          maxItems: 30
          description: 30 results in canonical order A1, A2, A3, A4, A5, B1…B6, C1a, C1b, C2, C3, D1…D6, E1…E5, F1, F2, F3, F4.
    CategoryScore:
      type: object
      required: [score, max]
      properties:
        score: { type: integer, minimum: 0 }
        max:   { type: integer, minimum: 0 }
    CriterionResult:
      type: object
      required:
        - id
        - status
        - score
        - max
        - evidence_url
        - evidence_snippet
        - http_status
      properties:
        id:
          type: string
          enum:
            - A1
            - A2
            - A3
            - A4
            - A5
            - B1
            - B2
            - B3
            - B4
            - B5
            - B6
            - C1a
            - C1b
            - C2
            - C3
            - D1
            - D2
            - D3
            - D4
            - D5
            - D6
            - E1
            - E2
            - E3
            - E4
            - E5
            - F1
            - F2
            - F3
            - F4
        status:
          type: string
          enum: [present, partial, absent, error, not_applicable]
        score:
          type: integer
          minimum: 0
        max:
          type: integer
          minimum: 0
        evidence_url:
          type: string
          description: URL of the resource that informed this result (may be empty if no useful URL).
        evidence_snippet:
          type: string
          maxLength: 50
          description: Up to 50 runes of representative evidence (snippet, header value, or summary).
        http_status:
          type: integer
          description: HTTP status of the most relevant fetch (0 if no fetch was performed).
    Error:
      type: object
      required: [error]
      properties:
        error:
          type: string
