openapi: 3.1.0
info:
  title: Aldenburg City Portal (OIDC ↔ SIOP / OpenID4VP bridge)
  description: >
    Reusable OIDC Provider that translates authorization-code + PKCE into
    SIOP v2 (and, at first login for authWithClaims clients, OpenID4VP DCQL
    for PID given_name, family_name, resident_city). The trust-listed
    verifier client_id is https://city.aldenburg.example. JWT iss for any
    credential remains the HTTPS credential-issuer URL, never did:web.
  version: 0.1.0
paths:
  /:
    get:
      summary: Bridge home (Login with AldenWallet)
      responses:
        '200':
          description: HTML
  /demo/login:
    get:
      summary: Start a PKCE authorization-code flow as the seeded authWithClaims client
      responses:
        '302':
          description: Redirect to /auth
  /demo/callback:
    get:
      summary: Minimal Fastify callback that exchanges the code and shows ID token claims
      responses:
        '200':
          description: HTML with decoded claims
  /interaction/{uid}:
    get:
      summary: SIOP (and optional OpenID4VP) login UI with QR / deep link
      parameters:
        - in: path
          name: uid
          required: true
          schema: { type: string }
      responses:
        '200':
          description: HTML login page
        '302':
          description: Resume OIDC after the wallet is recognized
  /api/interactions/{uid}:
    get:
      summary: JSON view of the login session for a given OIDC interaction
      parameters:
        - in: path
          name: uid
          required: true
          schema: { type: string }
      responses:
        '200':
          description: phase, SIOP request, optional VP/DCQL
  /api/login-sessions/{id}:
    get:
      summary: Poll login session after SIOP or OpenID4VP direct_post
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      responses:
        '200':
          description: siop | vp | complete | rejected
  /api/login-sessions/{id}/continue:
    post:
      summary: Finish the OIDC interaction after the wallet is recognized
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      responses:
        '303':
          description: Resume authorization-code redirect with code
        '409':
          description: Login session is not complete
  /siop/direct_post:
    post:
      summary: Wallet posts the SIOP v2 id_token
      responses:
        '200':
          description: SIOP accepted; phase may become vp or complete
        '400':
          description: Untrusted client_id, wrong nonce/audience, or malformed id_token
  /oid4vp/{verifierId}/authorize:
    post:
      summary: OpenID4VP direct_post response endpoint (Credo)
      parameters:
        - in: path
          name: verifierId
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Presentation accepted by the protocol layer
  /.well-known/openid-configuration:
    get:
      summary: OIDC discovery document
      responses:
        '200':
          description: issuer, authorization_endpoint, token_endpoint, jwks_uri, PKCE S256
  /jwks:
    get:
      summary: OIDC JWKS
      responses:
        '200':
          description: Signing keys
  /auth:
    get:
      summary: OIDC authorization endpoint (authorization-code + PKCE)
      responses:
        '302':
          description: Redirect to /interaction/{uid} or back to the RP
  /token:
    post:
      summary: OIDC token endpoint
      responses:
        '200':
          description: access_token + id_token
  /me:
    get:
      summary: OIDC UserInfo
      responses:
        '200':
          description: profile claims including resident_city
  /openapi.yaml:
    get:
      summary: This OpenAPI document
      responses:
        '200':
          description: YAML
