openapi: 3.1.0
info:
  title: CGG Enterprise Trust API
  summary: Unified trust infrastructure — identity verification, ledger integrity, deposit reconciliation.
  description: |
    The CGG Enterprise Trust API exposes deterministic verification services backing the
    public marketing surface at https://cleargarmentverify.com.

    **Sandbox is live today** at this domain under the `/api/v1` base path. Sandbox returns
    deterministic stubs and accepts only sandbox keys (`sk_sandbox_…` or `sk_test_…`).
    Production endpoints are gated; production key issuance follows the H3 identity-binding
    flow described in the customer-readiness vault and requires a signed Order Form.

    **Versioning:** URL-based (`/api/v1`). Per `api-terms.html` §9, prior major versions
    are supported for at least 12 months, and breaking changes receive 90-day advance notice.

    **Auth:** API key in the `X-CGV-Key` header. Sandbox keys are self-serve at
    `POST /api/v1/keys/sandbox` (rate-limited 3/min/IP).

    **Errors** use RFC 7807 `application/problem+json` with `type`, `title`, `status`, `code`, `audit_ref`.
  version: 1.0.0
  termsOfService: https://cleargarmentverify.com/api-terms.html
  contact:
    name: CGG Customer Service
    email: cs@cleargarment.com
    url: https://cleargarmentverify.com
  license:
    name: Proprietary — see Terms of Service
    url: https://cleargarmentverify.com/terms.html

servers:
  - url: https://cleargarmentverify.com/api/v1
    description: Sandbox (live; deterministic stubs; sandbox keys only)

security:
  - ApiKeyAuth: []

tags:
  - name: identity
    description: Identity verification — confidence scoring + risk signals.
  - name: keys
    description: Sandbox key issuance (production keys follow H3 flow).
  - name: meta
    description: Service health and reference endpoints.

paths:
  /verify:
    post:
      tags: [identity]
      operationId: verify
      summary: Submit a verification request (sandbox returns deterministic stub).
      parameters:
        - in: header
          name: Idempotency-Key
          required: false
          schema: { type: string, maxLength: 128 }
          description: Optional client-supplied key for safe POST retries.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/VerifyRequest' }
            examples:
              minimal:
                value:
                  subject:
                    reference: order_42
      responses:
        '200':
          description: Verification completed.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/VerifyResponse' }
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '405': { $ref: '#/components/responses/MethodNotAllowed' }
        '413': { $ref: '#/components/responses/PayloadTooLarge' }
        '422': { $ref: '#/components/responses/UnprocessableEntity' }
        '429': { $ref: '#/components/responses/RateLimited' }
        '5XX': { $ref: '#/components/responses/ServerError' }

  /keys/sandbox:
    post:
      tags: [keys]
      operationId: issueSandboxKey
      summary: Issue a sandbox API key (no auth; rate-limited).
      security: []
      responses:
        '201':
          description: Sandbox key issued.
          content:
            application/json:
              schema:
                type: object
                required: [key, environment, issued_at]
                properties:
                  key:         { type: string, pattern: '^sk_sandbox_[A-Fa-f0-9]{48}$' }
                  environment: { type: string, enum: [sandbox] }
                  issued_at:   { type: string, format: date-time }
                  note:        { type: string }
                  docs:        { type: string, format: uri }
        '405': { $ref: '#/components/responses/MethodNotAllowed' }
        '429': { $ref: '#/components/responses/RateLimited' }

  /health:
    get:
      tags: [meta]
      operationId: health
      summary: Health probe (no auth).
      security: []
      responses:
        '200':
          description: Healthy.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:      { type: string, enum: [ok] }
                  service:     { type: string }
                  environment: { type: string, enum: [sandbox, production] }
                  region:      { type: string }
                  build:       { type: string }
                  timestamp:   { type: string, format: date-time }

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-CGV-Key
      description: API key issued by CGG. Sandbox keys are self-serve. Production keys gated per H3 flow.

  schemas:
    VerifyRequest:
      type: object
      required: [subject]
      properties:
        subject:
          type: object
          required: [reference]
          properties:
            reference:  { type: string, description: 'Customer-side opaque identifier (no PII).' }
            attributes:
              type: object
              additionalProperties: { type: string }
        context:
          type: object
          properties:
            ip:        { type: string, format: ipv4 }
            device_id: { type: string }
            channel:   { type: string, enum: [api, web, mobile, partner] }

    VerifyResponse:
      type: object
      required: [status, confidence, audit_ref, latency_ms, timestamp, environment]
      properties:
        status:       { type: string, enum: [verified, inconclusive, declined] }
        confidence:   { type: number, minimum: 0, maximum: 1, example: 0.987 }
        risk_signals:
          type: array
          items:
            type: object
            properties:
              code:    { type: string }
              weight:  { type: number, minimum: 0, maximum: 1 }
              message: { type: string }
        audit_ref:   { type: string, pattern: '^aref_[A-Za-z0-9_]+$' }
        latency_ms:  { type: integer, minimum: 0 }
        timestamp:   { type: string, format: date-time }
        environment: { type: string, enum: [sandbox, production] }

    Problem:
      type: object
      properties:
        type:      { type: string, format: uri }
        title:     { type: string }
        status:    { type: integer }
        code:      { type: string }
        audit_ref: { type: string }

  responses:
    BadRequest:           { description: Malformed JSON or schema violation.,        content: { application/problem+json: { schema: { $ref: '#/components/schemas/Problem' } } } }
    Unauthorized:         { description: Missing or invalid X-CGV-Key.,              content: { application/problem+json: { schema: { $ref: '#/components/schemas/Problem' } } } }
    MethodNotAllowed:     { description: Wrong HTTP method.,                         content: { application/problem+json: { schema: { $ref: '#/components/schemas/Problem' } } } }
    PayloadTooLarge:      { description: Request body exceeds 32KB.,                 content: { application/problem+json: { schema: { $ref: '#/components/schemas/Problem' } } } }
    UnprocessableEntity:  { description: Well-formed but cannot process.,            content: { application/problem+json: { schema: { $ref: '#/components/schemas/Problem' } } } }
    RateLimited:
      description: Tier quota or burst limit exceeded.
      headers:
        Retry-After: { schema: { type: integer, minimum: 1 } }
      content: { application/problem+json: { schema: { $ref: '#/components/schemas/Problem' } } }
    ServerError:
      description: Unexpected server-side condition. Use audit_ref for support.
      content: { application/problem+json: { schema: { $ref: '#/components/schemas/Problem' } } }
