openapi: 3.1.0
info:
  title: EUDIStack Issuer — Revocation API
  version: "1"
  summary: Revoke attestations.
  description: |
    Revocation contract shared by operators and systems.
    The attestation is identified by its issuance process. Revocation is irreversible and only
    applies to a valid attestation.
    Errors follow the RFC 9457 problem details shape. `type` is an error code; the codes of each
    HTTP status are listed in its response.

    **Availability.** This operation is **coming soon** for systems (`x-availability: coming-soon`):
    do not build on it until it is available.
  contact:
    name: EUDIStack
    url: https://eudistack.net
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary
servers:
  - url: https://{tenant}.{environment}.eudistack.net/issuer
    description: Tenant endpoint.
    variables:
      tenant:
        default: sandbox
      environment:
        default: stg
tags:
  - name: Revocation
    description: Revocation of attestations.

paths:
  /api/v1/issuances/{id}/revocation:
    post:
      tags: [Revocation]
      operationId: revokeIssuance
      summary: Revoke an attestation (coming soon)
      x-availability: coming-soon
      description: |
        **Coming soon.** Not available to systems yet.

        Marks the attestation of the issuance process as revoked in its status list, moves the
        process to Revoked and notifies the holder, without the reason. The reason is internal and
        stays in the audit trail. What each requester may revoke is decided by authorization by powers.
      parameters:
        - name: id
          in: path
          required: true
          description: Issuance process identifier, as returned by the issuance API in `Location`.
          schema: { type: string, format: uuid }
      security:
        - bearer: []
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/RevocationRequest" }
            examples:
              revocation:
                value:
                  reason: Baja del empleado
      responses:
        "204":
          description: The attestation was revoked. No body.
        "400":
          description: |
            The request is not valid. `type`:
            - `BAD_REQUEST` — the identifier is not a UUID, or the reason is missing or longer than 280 characters, with `violations`.
          content:
            application/problem+json:
              schema: { $ref: "#/components/schemas/Problem" }
              examples:
                missing_reason:
                  value:
                    type: BAD_REQUEST
                    title: Bad request
                    status: 400
                    detail: The request is not valid
                    instance: /api/v1/issuances/0b6f1d2e-8c4a-4b1f-9e2d-7a5c3f8e1b90/revocation
                    violations:
                      - { field: reason, message: is required }
        "401":
          description: |
            The access token is missing, invalid or expired. `type`:
            - `invalid_token` — the token is not valid or has expired.
            - `authentication_error` — the token is missing or authentication failed.
          content:
            application/problem+json:
              schema: { $ref: "#/components/schemas/Problem" }
        "403":
          description: |
            The request is not allowed. `type`:
            - `tenant_mismatch` — the request tenant is not the tenant of the requester's attestation.
            - `tenant_not_resolved` — no tenant could be resolved for the request.
            - `insufficient_permission` — the requester may not revoke (authorization by powers).
          content:
            application/problem+json:
              schema: { $ref: "#/components/schemas/Problem" }
        "404":
          description: |
            `type` `issuance_not_found`: the issuance process does not exist or is outside the
            requester's scope. Both cases get the same response.
          content:
            application/problem+json:
              schema: { $ref: "#/components/schemas/Problem" }
        "409":
          description: |
            The attestation cannot be revoked. `type`:
            - `already_revoked` — the attestation is already revoked. No effect is repeated.
            - `not_revocable` — the attestation is not valid: draft, withdrawn, issued with a future validity start, expired or archived.
          content:
            application/problem+json:
              schema: { $ref: "#/components/schemas/Problem" }
              examples:
                already_revoked:
                  value:
                    type: already_revoked
                    title: Already revoked
                    status: 409
                    detail: The attestation is already revoked
                    instance: /api/v1/issuances/0b6f1d2e-8c4a-4b1f-9e2d-7a5c3f8e1b90/revocation
        "429":
          description: "`type` `rate_limited`: the volume limit was exceeded. Retry after the time in `Retry-After`."
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema: { type: integer, minimum: 0 }
          content:
            application/problem+json:
              schema: { $ref: "#/components/schemas/Problem" }
        "500":
          description: "`type` `INTERNAL_SERVER_ERROR`: unexpected error. Nothing was changed."
          content:
            application/problem+json:
              schema: { $ref: "#/components/schemas/Problem" }
        "503":
          description: |
            `type` `status_list_unavailable`: the attestation could not be marked in its status list.
            Nothing was changed. Retry after the time in `Retry-After`.
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema: { type: integer, minimum: 0 }
          content:
            application/problem+json:
              schema: { $ref: "#/components/schemas/Problem" }

components:
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      description: Access token issued by the Verifier, for a person (H2M) or a system (M2M).

  schemas:
    RevocationRequest:
      type: object
      required: [reason]
      properties:
        reason:
          type: string
          minLength: 1
          maxLength: 280
          description: Why the attestation is revoked. Internal; stored in the audit trail and never sent to the holder.

    Problem:
      type: object
      description: Problem details (RFC 9457 shape). `type` is an error code.
      required: [type, title, status]
      properties:
        type: { type: string, description: Error code. The codes of each HTTP status are listed in its response. }
        title: { type: string }
        status: { type: integer }
        detail: { type: string }
        instance: { type: string, format: uri-reference }
        violations:
          type: array
          description: Field-level violations, for data errors.
          items:
            type: object
            required: [field, message]
            properties:
              field: { type: string }
              message: { type: string }
