openapi: 3.0.0
info:
  version: 3.8.0
  title: Cloud Native Controller for Edge Native Workloads
paths:
  /status:
    get:
      tags:
        - Controller
      summary: Returns service health status
      operationId: getServiceStatus
      responses:
        '200':
          description: Service status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceStatusResponse'
        '500':
          description: Internal Server Error
  /architectures:
    get:
      tags:
        - Controller
      summary: Gets architecture list
      operationId: getArchitectures
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArchitecturesResponse'
        '500':
          description: Internal Server Error
  /iofog-list:
    get:
      tags:
        - ioFog
      summary: Returns list of ioFog nodes
      operationId: getIOFogNodes
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IOFogNodesListFilters'
      responses:
        '200':
          description: List of ioFog nodes
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IOFogNodesListResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /iofog:
    post:
      tags:
        - ioFog
      summary: Creates a new ioFog node
      description: >-
        Platform reconcile is asynchronous. Poll GET /iofog/{uuid} for
        platformStatus, or POST /iofog/{uuid}/reconcile to retry after failure.
      operationId: createIOFogNode
      security:
        - authToken: []
      requestBody:
        $ref: '#/components/requestBodies/UpdateIOFogNodeRequestBody'
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NewIOFogNodeResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /iofog/{uuid}:
    patch:
      tags:
        - ioFog
      summary: Updates existing ioFog node
      description: >-
        Platform reconcile is asynchronous. Poll GET /iofog/{uuid} for
        platformStatus, or POST /iofog/{uuid}/reconcile to retry after failure.
      operationId: updateIOFogNode
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        $ref: '#/components/requestBodies/UpdateIOFogNodeRequestBody'
      responses:
        '204':
          description: Updated
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Invalid Node Id
        '500':
          description: Internal Server Error
    delete:
      tags:
        - ioFog
      summary: Deletes an ioFog node
      operationId: deleteIOFogNode
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '202':
          description: Accepted
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Invalid Node Id
        '500':
          description: Internal Server Error
    get:
      tags:
        - ioFog
      summary: Gets ioFog node info
      operationId: getIOFogNode
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IOFogNodeInfoResponse'
        '401':
          description: Not Authorized
        '404':
          description: Invalid Node Id
        '500':
          description: Internal Server Error
  /iofog/{uuid}/reconcile:
    post:
      tags:
        - ioFog
      summary: Manually retries fog platform reconcile
      operationId: reconcileIOFogNode
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IOFogUuidResponse'
        '401':
          description: Not Authorized
        '404':
          description: Invalid Node Id
        '500':
          description: Internal Server Error
  /iofog/{uuid}/provisioning-key:
    get:
      tags:
        - ioFog
      summary: Generates provisioning key for an ioFog node
      operationId: generateProvisioningKey
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '201':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProvisioningKeyResponse'
        '401':
          description: Not Authorized
        '404':
          description: Invalid Node Id
        '500':
          description: Internal Server Error
  /iofog/{uuid}/version/{versionCommand}:
    post:
      tags:
        - ioFog
      summary: Set change version command
      operationId: setVersionCommand
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
        - in: path
          name: versionCommand
          description: change version command
          required: true
          schema:
            type: string
            enum:
              - upgrade
              - rollback
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                semver:
                  type: string
                  description: Target semver for upgrade or rollback
                  pattern: >-
                    ^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:[+]([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Invalid Node Id
        '500':
          description: Internal Server Error
  /iofog/{uuid}/reboot:
    post:
      tags:
        - ioFog
      summary: remote reboot fog agent
      operationId: setRebootCommand
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /iofog/{uuid}/prune:
    post:
      tags:
        - ioFog
      summary: prune remote fog agent
      operationId: setPruneCommand
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /iofog/{uuid}/hal/hw:
    get:
      tags:
        - ioFog
      summary: Retrieves HAL hardware info
      operationId: getFogHalHardwareInfo
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HalInfo'
        '401':
          description: Not Authorized
        '404':
          description: Invalid Node Id
        '500':
          description: Internal Server Error
  /iofog/{uuid}/hal/usb:
    get:
      tags:
        - ioFog
      summary: Retrieves HAL USB info
      operationId: getFogHalUsbInfo
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HalInfo'
        '401':
          description: Not Authorized
        '404':
          description: Invalid Node Id
        '500':
          description: Internal Server Error
  /application:
    get:
      tags:
        - Application
      summary: Lists all applications
      operationId: listApplication
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApplicationListResponse'
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /application/system:
    get:
      tags:
        - Application
      summary: Lists all system applications
      operationId: listSystemApplication
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApplicationListResponse'
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /application/system/{name}:
    get:
      tags:
        - Application
      summary: Gets an application details
      operationId: getApplication
      parameters:
        - in: path
          name: name
          description: Application name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApplicationGetResponse'
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Application
      summary: Deletes a system application
      operationId: deleteSystemApplication
      parameters:
        - in: path
          name: name
          description: Application name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /application/yaml:
    post:
      tags:
        - Application
      summary: Creates an application using a YAML file
      operationId: createApplicationYAML
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                application:
                  type: string
                  format: binary
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApplicationCreateResponse'
        '400':
          description: Bad Request
        '500':
          description: Internal Server Error
  /application/{name}:
    patch:
      tags:
        - Application
      summary: Updates an application metadata
      operationId: patchApplication
      parameters:
        - in: path
          name: name
          description: Application name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                description:
                  type: string
                isActivated:
                  type: boolean
        required: true
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Application
      summary: Deletes an application
      operationId: deleteApplication
      parameters:
        - in: path
          name: name
          description: Application name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    get:
      tags:
        - Application
      summary: Gets an application details
      operationId: getApplication
      parameters:
        - in: path
          name: name
          description: Application name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApplicationGetResponse'
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /application/yaml/{name}:
    put:
      tags:
        - Application
      summary: Updates an application using a YAML file
      operationId: updateApplicationYAML
      parameters:
        - in: path
          name: name
          description: Application name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                application:
                  type: string
                  format: binary
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /cluster/controllers:
    get:
      tags:
        - Cluster
      summary: Lists cluster controllers (active replicas by default)
      operationId: listClusterControllers
      security:
        - authToken: []
      parameters:
        - in: query
          name: includeInactive
          description: >-
            When true, include inactive controller rows (historical replicas
            from past rollouts). Default false returns only active replicas.
          required: false
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClusterControllerListResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /cluster/controllers/{uuid}:
    get:
      tags:
        - Cluster
      summary: Gets a cluster controller details
      operationId: getClusterController
      parameters:
        - in: path
          name: uuid
          description: Cluster controller UUID
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClusterControllerResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Cluster
      summary: Updates a cluster controller
      operationId: updateClusterController
      parameters:
        - in: path
          name: uuid
          description: Cluster controller UUID
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ClusterControllerUpdateRequest'
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClusterControllerResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Cluster
      summary: Deletes a cluster controller
      operationId: deleteClusterController
      parameters:
        - in: path
          name: uuid
          description: Cluster controller UUID
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /applicationTemplates:
    get:
      tags:
        - Application Template
      summary: Lists all application templates
      operationId: listApplicationTemplates
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApplicationTemplateListResponse'
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /applicationTemplate/yaml:
    post:
      tags:
        - Application Template
      summary: Creates an application template using a YAML file
      operationId: createApplicationTemplateYAML
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                application:
                  type: string
                  format: binary
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApplicationTemplateCreateResponse'
        '400':
          description: Bad Request
        '500':
          description: Internal Server Error
  /applicationTemplate/{name}:
    patch:
      tags:
        - Application Template
      summary: Patches an application template
      operationId: patchApplicationTemplate
      parameters:
        - in: path
          name: name
          description: Application template name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApplicationTemplatePatchRequest'
        required: true
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Application Template
      summary: Deletes an application template
      operationId: deleteApplicationTemplate
      parameters:
        - in: path
          name: name
          description: Application template name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    get:
      tags:
        - Application Template
      summary: Gets an application template
      operationId: getApplicationTemplate
      parameters:
        - in: path
          name: name
          description: Application template name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApplicationTemplateGetResponse'
        '400':
          description: Bad Request
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /applicationTemplate/yaml/{name}:
    put:
      tags:
        - Application Template
      summary: Updates or creates an application template
      operationId: updateOrCreateApplicationTemplateFromYaml
      parameters:
        - in: path
          name: name
          description: Application template name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                template:
                  type: string
                  format: binary
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApplicationTemplateCreateResponse'
        '400':
          description: Bad Request
        '500':
          description: Internal Server Error
  /agent/provision:
    post:
      tags:
        - Agent
      summary: Provision agent with an ioFog node
      operationId: agentProvision
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AgentProvisioningRequest'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentProvisioningResponse'
        '400':
          description: Bad Request
        '401':
          description: Expired Provisioning Key
        '404':
          description: Invalid Provisioning Key
        '500':
          description: Internal Server Error
  /agent/deprovision:
    post:
      tags:
        - Agent
      summary: Deprovision agent
      operationId: agentDeprovision
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AgentDeprovisioningRequest'
        required: true
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /agent/cert:
    get:
      tags:
        - Agent
      summary: Move Controller CA to Agent
      operationId: agentControllerCert
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /agent/config:
    get:
      tags:
        - Agent
      summary: Get an ioFog node configuration
      operationId: getIOFogNodeConfig
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IOFogNodeConfig'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Agent
      summary: Updates an ioFog node configuration
      operationId: updateIOFogNodeConfig
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IOFogNodeConfigRequest'
        required: true
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /agent/config/gps:
    patch:
      tags:
        - Agent
      summary: Updates an ioFog node GPS configuration
      operationId: updateIOFogNodeGps
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IOFogNodeGpsRequest'
        required: true
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /agent/config/changes:
    get:
      tags:
        - Agent
      summary: Gets ioFog node changes
      operationId: getIOFogNodeChanges
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IOFogNodeConfigChanges'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Agent
      summary: Resets ioFog node changes list
      operationId: resetIOFogNodeChanges
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /agent/status:
    put:
      tags:
        - Agent
      summary: Posts agent status to ioFog node
      operationId: postAgentStatus
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AgentStatus'
        required: true
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /agent/controller/register:
    post:
      tags:
        - Agent
      summary: Register ControlPlane controller microservice
      description: >-
        Agent-only endpoint (fog token). Edgelet registers the controller
        workload on system fogs. Not available via user RBAC - do not add to
        rbac-resources.yaml user resources.
      operationId: registerControllerMicroservice
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ControllerRegisterRequest'
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ControllerRegisterResponse'
        '400':
          description: Bad Request - invalid body or name other than controller
        '401':
          description: Not Authorized
        '403':
          description: Forbidden - authenticated fog is not a system fog
        '500':
          description: Internal Server Error
  /agent/microservices:
    get:
      tags:
        - Agent
      summary: Gets microservices running on an ioFog node
      operationId: getAgentMicroservicesList
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentMicroservicesListResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /agent/microservices/{microserviceUuid}:
    get:
      tags:
        - Agent
      summary: Gets microservices running on an ioFog node
      operationId: getAgentMicroserviceInfo
      parameters:
        - in: path
          required: true
          name: microserviceUuid
          description: Microservice UUID
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentMicroservicesInfoResponse'
        '401':
          description: Not Authorized
        '404':
          description: Invalid Microservice Uuid
        '500':
          description: Internal Server Error
  /agent/registries:
    get:
      tags:
        - Agent
      summary: Gets list of Docker registries
      operationId: getRegistriesList
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegistriesListResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /agent/tunnel:
    get:
      tags:
        - Agent
      summary: Get an ioFog node tunnel configuration
      operationId: getIOFogNodeTunnelConfig
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IOFogNodeTunnelConfigResponse'
        '401':
          description: Not Authorized
        '404':
          description: Tunnel Not Found
        '500':
          description: Internal Server Error
  /agent/version:
    get:
      tags:
        - Agent
      summary: Get change version command
      operationId: getChangeVersion
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VersionCommandResponse'
        '401':
          description: Not Authorized
        '404':
          description: Version Command Not Found
        '500':
          description: Internal Server Error
  /agent/hal/hw:
    put:
      tags:
        - Agent
      summary: Updates HAL hardware info
      operationId: putHalHardwareInfo
      security:
        - authToken: []
      requestBody:
        $ref: '#/components/requestBodies/HalInfo'
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /agent/hal/usb:
    get:
      tags:
        - ioFog
      summary: Retrieves HAL USB info
      operationId: getAgentHalUsbInfo
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HalInfo'
        '401':
          description: Not Authorized
        '404':
          description: Invalid Node Id
        '500':
          description: Internal Server Error
    put:
      tags:
        - Agent
      summary: Updates HAL USB info
      operationId: putHalUsbInfo
      security:
        - authToken: []
      requestBody:
        $ref: '#/components/requestBodies/HalInfo'
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /agent/delete-node:
    delete:
      tags:
        - Agent
      summary: Deletes an ioFog node
      operationId: deleteAgentNode
      security:
        - authToken: []
      responses:
        '204':
          description: No Content
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /agent/tracking:
    post:
      tags:
        - Agent
      summary: Post tracking info
      operationId: postTracking
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostTrackingRequest'
        required: true
      responses:
        '204':
          description: Success
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /catalog/microservices:
    get:
      tags:
        - Catalog
      summary: Gets microservices catalog
      operationId: getMicroservicesCatalog
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MicroservicesCatalogResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
    post:
      tags:
        - Catalog
      summary: Creates a new microservice catalog item
      operationId: createMicroserviceCatalogItem
      security:
        - authToken: []
      requestBody:
        $ref: '#/components/requestBodies/CreateUpdateCatalogItemRequestBody'
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: Duplicate Name
        '500':
          description: Internal Server Error
  /catalog/microservices/{id}:
    get:
      tags:
        - Catalog
      summary: Gets microservice catalog item info
      operationId: getMicroserviceCatalogItem
      parameters:
        - in: path
          name: id
          description: Catalog Item Id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Catalog Item Info
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CatalogItemInfoResponse'
        '401':
          description: Not Authorized
        '404':
          description: Invalid Catalog Item Id
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Catalog
      summary: Updates a microservice catalog item
      operationId: updateMicroserviceCatalogItem
      parameters:
        - in: path
          name: id
          description: Catalog Item Id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        $ref: '#/components/requestBodies/CreateUpdateCatalogItemRequestBody'
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Invalid Catalog Item Id
        '409':
          description: Duplicate Name
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Catalog
      summary: Deletes a microservice catalog item
      operationId: deleteMicroserviceCatalogItem
      parameters:
        - in: path
          name: id
          description: Catalog Item Id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Invalid Catalog Item Id
        '500':
          description: Internal Server Error
  /microservices:
    get:
      tags:
        - Microservices
      summary: Gets list of microservices
      operationId: getMicroservicesList
      parameters:
        - in: query
          name: application
          description: Application name
          required: false
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetMicroservicesResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
    post:
      tags:
        - Microservices
      summary: Creates a new microservice
      operationId: createMicroservice
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewMicroserviceRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  uuid:
                    type: string
                  name:
                    type: string
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /microservices/yaml:
    post:
      tags:
        - Microservices
      summary: Creates a new microservice in an Application
      operationId: createMicroserviceYAML
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                microservice:
                  type: string
                  format: binary
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                type: object
                properties:
                  uuid:
                    type: string
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: Duplicate Name
        '500':
          description: Internal Server Error
  /microservices/{uuid}:
    get:
      tags:
        - Microservices
      summary: Gets a microservice info
      operationId: getMicroserviceInfo
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MicroserviceInfoResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Microservices
      summary: Deletes a microservice
      operationId: deleteMicroservice
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Microservices
      summary: Updates a microservice
      operationId: updateMicroservice
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Updated
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Invalid Registry Id
        '500':
          description: Internal Server Error
  /microservices/system:
    get:
      tags:
        - Microservices
      summary: Gets list of system microservices
      operationId: getSystemMicroservicesList
      security:
        - authToken: []
      parameters:
        - in: query
          name: application
          description: Application name
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                type: object
                properties:
                  microservices:
                    type: array
                    items:
                      type: object
                      properties:
                        uuid:
                          type: string
                        name:
                          type: string
                        config:
                          type: object
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/system/{uuid}:
    get:
      tags:
        - Microservices
      summary: Gets a system microservice info
      operationId: getSystemMicroserviceInfo
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MicroserviceInfoResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Microservices
      summary: Updates a system microservice
      operationId: updateSystemMicroservice
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Updated
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Invalid Registry Id
        '500':
          description: Internal Server Error
  /microservices/yaml/{uuid}:
    patch:
      tags:
        - Microservices
      summary: Updates a microservice
      operationId: updateMicroserviceYAML
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                microservice:
                  type: string
                  format: binary
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '409':
          description: Duplicate Name
        '500':
          description: Internal Server Error
  /microservices/{uuid}/config:
    get:
      tags:
        - Microservices
      summary: Gets a microservice config
      operationId: getMicroserviceConfig
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/microservicesConfig'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Microservices
      summary: Updates a microservice config
      operationId: updateMicroserviceConfig
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/microservicesConfig'
        description: information about microservice config
        required: true
      responses:
        '204':
          description: Updated
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Microservices
      summary: Deletes a microservice config
      operationId: deleteMicroserviceConfig
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/system/{uuid}/config:
    get:
      tags:
        - Microservices
      summary: Gets a system microservice config
      operationId: getSystemMicroserviceConfig
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/microservicesConfig'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Microservices
      summary: Updates a system microservice config
      operationId: updateSystemMicroserviceConfig
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/microservicesConfig'
        description: information about microservice config
        required: true
      responses:
        '204':
          description: Updated
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Microservices
      summary: Deletes a system microservice config
      operationId: deleteSystemMicroserviceConfig
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/{uuid}/port-mapping:
    post:
      tags:
        - Microservices
      summary: Creates a port mapping for microservice
      operationId: createMicroservicePortMapping
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PortMappingsRequest'
        description: information about port mapping
        required: true
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortMappingsPublicResponse'
        '400':
          description: Not Valid
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    get:
      tags:
        - Microservices
      summary: Get a port mapping list for microservice
      operationId: getMicroservicePortMapping
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortMappingsListResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/system/{uuid}/port-mapping:
    post:
      tags:
        - Microservices
      summary: Creates a port mapping for system microservice
      operationId: createSystemMicroservicePortMapping
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PortMappingsRequest'
        description: information about port mapping
        required: true
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortMappingsPublicResponse'
        '400':
          description: Not Valid
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/{uuid}/port-mapping/{internalPort}:
    delete:
      tags:
        - Microservices
      summary: Deletes a port mapping for microservice
      operationId: deleteMicroservicePortMapping
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
        - in: path
          name: internalPort
          description: Internal Port
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/system/{uuid}/port-mapping/{internalPort}:
    delete:
      tags:
        - Microservices
      summary: Deletes a port mapping for system microservice
      operationId: deleteSystemMicroservicePortMapping
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
        - in: path
          name: internalPort
          description: Internal Port
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/{uuid}/volume-mapping:
    post:
      tags:
        - Microservices
      summary: Creates a volume mapping for microservice
      operationId: createMicroserviceVolumeMapping
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VolumeMapping'
        description: information about volume mapping
        required: true
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: number
        '400':
          description: Not Valid
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    get:
      tags:
        - Microservices
      summary: Get a volume mapping list for microservice
      operationId: getMicroserviceVolumeMapping
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VolumeMappingResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/system/{uuid}/volume-mapping:
    post:
      tags:
        - Microservices
      summary: Creates a volume mapping for system microservice
      operationId: createSystemMicroserviceVolumeMapping
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VolumeMapping'
        description: information about volume mapping
        required: true
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: number
        '400':
          description: Not Valid
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/{uuid}/volume-mapping/{id}:
    delete:
      tags:
        - Microservices
      summary: Deletes a volume mapping for microservice
      operationId: deleteMicroserviceVolumeMapping
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
        - in: path
          name: id
          description: Volume id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Not Valid
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/system/{uuid}/volume-mapping/{id}:
    delete:
      tags:
        - Microservices
      summary: Deletes a volume mapping for system microservice
      operationId: deleteSystemMicroserviceVolumeMapping
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
        - in: path
          name: id
          description: Volume id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Not Valid
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/system/{uuid}/rebuild:
    patch:
      tags:
        - Microservices
      summary: Rebuilds a system microservice
      operationId: rebuildSystemMicroservice
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/{uuid}/rebuild:
    patch:
      tags:
        - Microservices
      summary: Rebuilds a microservice
      operationId: rebuildMicroservice
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/{uuid}/start:
    patch:
      tags:
        - Microservices
      summary: Starts a microservice
      operationId: startMicroservice
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/{uuid}/stop:
    patch:
      tags:
        - Microservices
      summary: Stops a microservice
      operationId: stopMicroservice
      parameters:
        - in: path
          name: uuid
          description: Microservice Uuid
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /microservices/exec/{microserviceUuid}:
    get:
      tags:
        - WebSocketSessions
      summary: User exec WebSocket (HTTP upgrade)
      description: >
        Upgrades to a binary MessagePack WebSocket for interactive exec.


        **Auth:** Bearer JWT in `Authorization` header or `?token=` query param.

        **RBAC:** `execSessions` on `microservices` resource.


        Pairing: user connects directly via WebSocket; Controller creates a
        per-session row

        in `MicroserviceExecSessions` and relays STDIN/STDOUT/STDERR by
        `sessionId`.

        No prior REST enable step is required (Plan 17). Max **5** concurrent
        exec sessions

        per microservice (close code **1008** when quota exceeded).


        On connect, Controller sends **ACTIVATION** (type 5) with JSON

        `{ sessionId, microserviceUuid }` in the `data` field and top-level
        `sessionId`,

        followed by STDERR "waiting for agent…". Relay frames use `execId` equal
        to `sessionId`.


        **HA:** Multi-replica deployments require a **relay backend** selected
        at startup by **`nats.enabled`**: AMQP router queues when `false`
        (default), NATS Core pub/sub on the platform hub when `true`.
        Cross-replica sessions fail fast with close code **1013** when the
        active relay backend is unavailable. See
        `docs/operations/ws-sessions.md`.


        See `#/components/schemas/WsExecMessageTypes` and
        `#/components/schemas/WsCloseCodes`.
      operationId: userMicroserviceExecWebSocket
      parameters:
        - in: path
          name: microserviceUuid
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: token
          description: Bearer JWT for browser clients (redact in ingress access logs)
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '101':
          description: Switching Protocols - WebSocket established
        '401':
          description: Not Authorized
        '403':
          description: RBAC denied
  /microservices/system/exec/{microserviceUuid}:
    get:
      tags:
        - WebSocketSessions
      summary: User system microservice exec WebSocket
      description: Same as user exec WS; **RBAC** `systemExecSessions`.
      operationId: userSystemMicroserviceExecWebSocket
      parameters:
        - in: path
          name: microserviceUuid
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: token
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '101':
          description: Switching Protocols
  /microservices/{uuid}/logs:
    get:
      tags:
        - WebSocketSessions
      summary: User microservice log streaming WebSocket
      description: >
        Upgrades to binary MessagePack log stream (agent → user after pairing).


        **RBAC:** `logs`. Max **5** concurrent user log WS per microservice.


        Query params control tail behaviour (see parameters). Live relay only -
        no log persistence.
      operationId: userMicroserviceLogsWebSocket
      parameters:
        - in: path
          name: uuid
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: token
          schema:
            type: string
        - in: query
          name: tail
          description: Number of tail lines (1–5000, default from config)
          schema:
            type: integer
            minimum: 1
            maximum: 5000
        - in: query
          name: follow
          description: Stream new lines after tail (default true)
          schema:
            type: boolean
            default: true
        - in: query
          name: since
          description: ISO 8601 timestamp - include lines after this time
          schema:
            type: string
            format: date-time
        - in: query
          name: until
          description: ISO 8601 timestamp - include lines before this time
          schema:
            type: string
            format: date-time
      security:
        - authToken: []
      responses:
        '101':
          description: Switching Protocols
  /microservices/system/{uuid}/logs:
    get:
      tags:
        - WebSocketSessions
      summary: User system microservice log WebSocket
      operationId: userSystemMicroserviceLogsWebSocket
      parameters:
        - in: path
          name: uuid
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: token
          schema:
            type: string
        - in: query
          name: tail
          schema:
            type: integer
            minimum: 1
            maximum: 5000
        - in: query
          name: follow
          schema:
            type: boolean
        - in: query
          name: since
          schema:
            type: string
            format: date-time
        - in: query
          name: until
          schema:
            type: string
            format: date-time
      security:
        - authToken: []
      responses:
        '101':
          description: Switching Protocols
  /iofog/{uuid}/logs:
    get:
      tags:
        - WebSocketSessions
      summary: User fog (node) log streaming WebSocket
      description: >-
        Node-level logs; **RBAC** `systemLogs`. Max **5** concurrent sessions
        per fog.
      operationId: userFogLogsWebSocket
      parameters:
        - in: path
          name: uuid
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: token
          schema:
            type: string
        - in: query
          name: tail
          schema:
            type: integer
            minimum: 1
            maximum: 5000
        - in: query
          name: follow
          schema:
            type: boolean
        - in: query
          name: since
          schema:
            type: string
            format: date-time
        - in: query
          name: until
          schema:
            type: string
            format: date-time
      security:
        - authToken: []
      responses:
        '101':
          description: Switching Protocols
  /agent/exec/sessions:
    get:
      tags:
        - Agent
      summary: List pending and active exec sessions for this agent
      description: >
        Returns exec sessions for microservices on the authenticated fog node.

        Poll when `GET /agent/changes` reports `execSessions: true` (Plan 17).


        Each entry includes `microserviceUuid`, `sessionId`, `status` (`PENDING`
        | `ACTIVE`),

        and `agentConnected`. Agent connects with

        `WS /agent/exec/microservice/{microserviceUuid}/{sessionId}`.
      operationId: getAgentExecSessions
      security:
        - fogToken: []
      responses:
        '200':
          description: Exec session list
          content:
            application/json:
              schema:
                type: object
                properties:
                  execSessions:
                    type: array
                    items:
                      type: object
                      properties:
                        microserviceUuid:
                          type: string
                          format: uuid
                        sessionId:
                          type: string
                          format: uuid
                        status:
                          type: string
                          enum:
                            - PENDING
                            - ACTIVE
                        agentConnected:
                          type: boolean
        '401':
          description: Not Authorized
  /agent/exec/microservice/{microserviceUuid}/{sessionId}:
    get:
      tags:
        - WebSocketSessions
      summary: Agent exec WebSocket (session-scoped)
      description: >
        Agent-side exec pairing for a specific session. **Auth:** fog token (not
        OIDC).


        Path includes the `sessionId` from `GET /agent/exec/sessions` or from
        user ACTIVATION.

        Controller validates the session row and strict `sessionId` /
        `microserviceUuid` match

        before relay. Legacy `WS /agent/exec/{microserviceUuid}` with initial
        MessagePack frame

        is **removed** (Plan 17, R96).


        Agent handlers validate fog token **before** accepting messages (R86).
      operationId: agentExecMicroserviceWebSocket
      parameters:
        - in: path
          name: microserviceUuid
          required: true
          schema:
            type: string
            format: uuid
        - in: path
          name: sessionId
          required: true
          schema:
            type: string
            format: uuid
      security:
        - fogToken: []
      responses:
        '101':
          description: Switching Protocols
  /agent/logs/microservice/{microserviceUuid}/{sessionId}:
    get:
      tags:
        - WebSocketSessions
      summary: Agent microservice log WebSocket
      operationId: agentMicroserviceLogsWebSocket
      parameters:
        - in: path
          name: microserviceUuid
          required: true
          schema:
            type: string
            format: uuid
        - in: path
          name: sessionId
          required: true
          schema:
            type: string
            format: uuid
      security:
        - fogToken: []
      responses:
        '101':
          description: Switching Protocols
  /agent/logs/iofog/{iofogUuid}/{sessionId}:
    get:
      tags:
        - WebSocketSessions
      summary: Agent fog log WebSocket
      operationId: agentFogLogsWebSocket
      parameters:
        - in: path
          name: iofogUuid
          required: true
          schema:
            type: string
            format: uuid
        - in: path
          name: sessionId
          required: true
          schema:
            type: string
            format: uuid
      security:
        - fogToken: []
      responses:
        '101':
          description: Switching Protocols
  /iofog/{uuid}/tunnel:
    patch:
      tags:
        - Tunnel
      summary: Opens/closes ssh tunnel
      operationId: openIOFogNodeSshTunnel
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ActionBody'
        required: true
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Invalid Node Id
        '500':
          description: Internal Server Error
    get:
      tags:
        - Tunnel
      summary: Gets current info about ioFog node ssh tunnel status
      operationId: getIOFogNodeSshTunnelStatusInfo
      parameters:
        - in: path
          name: uuid
          description: ioFog node id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IOFogNodeTunnelStatusInfoResponse'
        '401':
          description: Not Authorized
        '404':
          description: Invalid Node Id
        '500':
          description: Internal Server Error
  /registries:
    post:
      tags:
        - Registries
      summary: Creates new registry
      operationId: createRegistry
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegistryBody'
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
    get:
      tags:
        - Registries
      summary: Gets list of registries
      operationId: getRegistryList
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegistriesListResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /registries/{id}:
    delete:
      tags:
        - Registries
      summary: Deletes a registry
      operationId: deleteRegistry
      parameters:
        - in: path
          name: id
          description: Registry id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Deleted
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Invalid Registry Id
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Registries
      summary: Updates a registry
      operationId: updateRegistry
      parameters:
        - in: path
          name: id
          description: Registry id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegistryBody'
        required: true
      responses:
        '204':
          description: Updated
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Invalid Registry Id
        '500':
          description: Internal Server Error
    get:
      tags:
        - Registries
      summary: Gets a registry
      operationId: getRegistry
      parameters:
        - in: path
          name: id
          description: Registry id
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegistryResponse'
        '401':
          description: Not Authorized
        '404':
          description: Invalid Registry Id
        '500':
          description: Internal Server Error
  /user/login:
    post:
      tags:
        - User
      summary: Login
      operationId: login
      description: >
        CLI login. The `email` field is the login identifier (username or
        email); bootstrap admin may use a non-email username. User creation via
        POST /users still requires a valid email address.

        When the account has a temporary password (`mustChangePassword`), the
        access token includes JWT claim `password_change_required: true`. RBAC
        allows only `GET /user/profile` and `POST /user/change-password` until
        the password is changed.
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LoginSuccessResponse'
        '400':
          description: bad request
        '401':
          description: incorrect credentials
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
  /user/refresh:
    post:
      tags:
        - User
      summary: Refresh accessToken with refreshToken
      operationId: refresh
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RefreshRequest'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RefreshSuccessResponse'
        '400':
          description: bad request
        '401':
          description: incorrect credentials
  /user/logout:
    post:
      tags:
        - User
      summary: Logout
      operationId: logout
      security:
        - authToken: []
      responses:
        '204':
          description: Success
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /user/profile:
    get:
      tags:
        - User
      summary: Get current user profile data
      description: >
        In **embedded** auth mode, returns a flat profile object derived from
        the access token

        plus embedded MFA enrollment state (`mfaEnabled`).


        In **external** auth mode, returns the upstream IdP UserInfo payload
        (shape depends on the IdP).
      operationId: getUserProfile
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserProfileDetailsResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /user/change-password:
    post:
      tags:
        - User
      summary: Change password (authenticated or via reset token)
      operationId: changePassword
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChangePasswordRequest'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StatusResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
        '501':
          description: Embedded auth mode only
  /user/mfa/enroll:
    post:
      tags:
        - User
      summary: Begin MFA enrollment (embedded mode)
      operationId: enrollMfa
      security:
        - authToken: []
      description: Start TOTP enrollment for the authenticated user.
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MfaEnrollResponse'
        '401':
          description: Not Authorized
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
        '501':
          description: Embedded auth mode only
  /user/mfa/confirm:
    post:
      tags:
        - User
      summary: Confirm MFA enrollment with TOTP code
      operationId: confirmMfa
      security:
        - authToken: []
      description: Complete TOTP enrollment for the authenticated user.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MfaConfirmRequest'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StatusResponse'
        '400':
          description: Bad Request
        '401':
          description: Invalid credentials or enrollment token
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
        '501':
          description: Embedded auth mode only
  /user/mfa:
    delete:
      tags:
        - User
      summary: Disable MFA for the current user
      operationId: disableMfa
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MfaDisableRequest'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StatusResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '501':
          description: Embedded auth mode only
  /user/oauth/authorize:
    get:
      tags:
        - User
      summary: Start OAuth authorization (BFF)
      operationId: oauthAuthorize
      description: >
        Browser OAuth BFF entry point for EdgeOps Console. EdgeOps Console Sign
        in performs a full-page redirect here; do **not** POST credentials from
        the browser.

        **External mode:** redirects to the external IdP authorize endpoint.

        **Embedded mode:** redirects to the in-process issuer at
        `{CONTROLLER_PUBLIC_URL}/oidc/auth`, which starts an OAuth interaction
        and redirects the browser to
        `{consoleUrl}{auth.oauthInteractionUrl}?interaction=<uid>` for
        Console-owned login/MFA steps.

        Redirect chain (external):

        `Console → GET /user/oauth/authorize → external IdP (login, MFA,
        password policy) → GET /user/oauth/callback → 302
        {consoleUrl}/login#accessToken=...&refreshToken=...`

        Redirect chain (embedded):

        `Console → GET /user/oauth/authorize → /oidc/auth →
        {consoleUrl}/login/oauth?interaction=<uid> → interaction APIs → GET
        /user/oauth/callback → 302 {consoleUrl}/login#tokens`

        OAuth callback redirect URI:
        `{CONTROLLER_PUBLIC_URL}/api/v3/user/oauth/callback`. Requires
        `CONSOLE_URL` in embedded mode. External mode requires
        `OIDC_ISSUER_URL`, `OIDC_CLIENT_ID`, and `OIDC_CLIENT_SECRET` for the
        confidential Controller client.
      responses:
        '302':
          description: Redirect to IdP or embedded issuer authorization endpoint
        '401':
          description: Auth not configured or OAuth session error
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
        '501':
          description: Embedded OAuth BFF requires CONSOLE_URL
  /user/oauth/callback:
    get:
      tags:
        - User
      summary: OAuth authorization callback (BFF)
      operationId: oauthCallback
      description: >
        Exchanges the authorization code for tokens using the confidential
        Controller OIDC client. Validates `state` and `nonce` from the server
        session (10-minute TTL). Works in **embedded** and **external** auth
        modes.

        When `CONSOLE_URL` is configured (recommended for browser login),
        responds with **302** to
        `{consoleUrl}/login#accessToken=...&refreshToken=...`. EdgeOps Console
        `/login` parses the URL fragment, stores tokens, clears the hash, and
        navigates to the app. When `CONSOLE_URL` is unset, returns JSON **200**
        `{ accessToken, refreshToken }` (CLI/automation only).

        **External forced password change** is enforced by the IdP during
        authorize (e.g. Keycloak required actions: `UPDATE_PASSWORD`).
        **Embedded forced password** uses the interaction `change-password`
        step.

        MFA in external browser login is IdP-owned; embedded browser MFA uses
        interaction endpoints.
      responses:
        '200':
          description: Token response when CONSOLE_URL is not configured
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LoginSuccessResponse'
        '302':
          description: Redirect to EdgeOps Console `/login` with tokens in URL fragment
        '401':
          description: >-
            OAuth session expired, state/nonce mismatch, or authorization code
            exchange failed
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
        '501':
          description: Embedded OAuth BFF requires CONSOLE_URL
  /user/interaction/{uid}:
    get:
      tags:
        - User
      summary: Get embedded OAuth interaction status
      operationId: interactionStatus
      description: >
        **Embedded auth mode only.** Returns the next interaction step for the
        OAuth BFF flow. Unauthenticated - the interaction uid comes from the
        Viewer redirect query string (`?interaction=<uid>`). Steps: `login`,
        `mfa`, `enroll`, `confirm-enroll`, `change-password`, `complete`.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Current interaction step
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InteractionStepResponse'
        '401':
          description: Interaction session not found or expired
        '501':
          description: External auth mode only (embedded interactions)
  /user/interaction/{uid}/login:
    post:
      tags:
        - User
      summary: Submit credentials for embedded OAuth interaction
      operationId: interactionLogin
      description: >
        **Embedded auth mode only.** Verifies email/login identifier and
        password for the OAuth interaction. Returns the next step on success.
        Failures return **401** (no custom MFA JSON).
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InteractionLoginRequest'
      responses:
        '200':
          description: Credentials accepted; returns next step
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InteractionStepResponse'
        '400':
          description: Validation error
        '401':
          description: Invalid credentials or interaction expired
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
        '501':
          description: External auth mode only
  /user/interaction/{uid}/mfa:
    post:
      tags:
        - User
      summary: Submit TOTP for embedded OAuth interaction
      operationId: interactionMfa
      description: >
        **Embedded auth mode only.** Verifies TOTP for admin users with MFA
        enabled during the OAuth interaction. Returns the next step on success.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InteractionMfaRequest'
      responses:
        '200':
          description: MFA verified; returns next step
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InteractionStepResponse'
        '400':
          description: Validation error
        '401':
          description: Invalid MFA code or interaction expired
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
        '501':
          description: External auth mode only
  /user/interaction/{uid}/enroll:
    post:
      tags:
        - User
      summary: Start MFA enrollment during embedded OAuth interaction
      operationId: interactionEnroll
      description: >
        **Embedded auth mode only.** Starts admin MFA enrollment during the
        browser OAuth interaction (browser-only first enrollment). Returns TOTP
        secret material for QR display.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Enrollment started
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InteractionEnrollResponse'
        '400':
          description: Validation error
        '401':
          description: Interaction expired or credentials not verified
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
        '501':
          description: External auth mode only
  /user/interaction/{uid}/confirm-enroll:
    post:
      tags:
        - User
      summary: Confirm MFA enrollment during embedded OAuth interaction
      operationId: interactionConfirmEnroll
      description: >
        **Embedded auth mode only.** Confirms MFA enrollment with a TOTP code
        during the browser OAuth interaction. Returns recovery codes on success.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InteractionMfaRequest'
      responses:
        '200':
          description: MFA enrollment confirmed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InteractionConfirmEnrollResponse'
        '400':
          description: Validation error
        '401':
          description: Invalid code or interaction expired
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
        '501':
          description: External auth mode only
  /user/interaction/{uid}/change-password:
    post:
      tags:
        - User
      summary: Forced password change during embedded OAuth interaction
      operationId: interactionChangePassword
      description: >
        **Embedded auth mode only.** Forced password change step before OAuth
        tokens are issued when `mustChangePassword` is true. Requires
        `currentPassword` and `newPassword` in the body.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChangePasswordRequest'
      responses:
        '200':
          description: Password changed; returns next step
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InteractionStepResponse'
        '400':
          description: Validation error
        '401':
          description: Invalid credentials or interaction expired
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
        '501':
          description: External auth mode only
  /user/interaction/{uid}/complete:
    post:
      tags:
        - User
      summary: Finish embedded OAuth interaction
      operationId: interactionComplete
      description: >
        **Embedded auth mode only.** Completes the oidc-provider interaction
        after all required steps are satisfied. Returns `{ redirectTo }` -
        Viewer should navigate the browser to this URL to resume the OAuth
        authorize flow and reach `/user/oauth/callback`.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Interaction finished; resume OAuth at redirectTo
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InteractionCompleteResponse'
        '400':
          description: Required interaction step not yet completed
        '401':
          description: Interaction expired or credentials invalid
        '429':
          $ref: '#/components/responses/AuthRateLimitExceeded'
        '501':
          description: External auth mode only
  /auth/migration/export:
    post:
      tags:
        - Auth Admin
      summary: Export embedded auth users for external IdP migration
      operationId: exportAuthMigration
      description: >-
        Admin-only. Exports user UUIDs, emails, and group memberships. No
        secrets or password hashes.
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthMigrationExportResponse'
        '401':
          description: Not Authorized
        '403':
          description: Forbidden
        '501':
          description: Embedded auth mode only
  /auth/jwks/rotate:
    post:
      tags:
        - Auth Admin
      summary: Rotate embedded OIDC signing keys (manual)
      operationId: rotateAuthJwks
      description: >
        Admin-only. Generates a new JWKS signing key and deactivates the
        previous active key. Restart Controller pods after rotation so the
        embedded issuer loads the new key.
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthJwksRotateResponse'
        '401':
          description: Not Authorized
        '403':
          description: Forbidden
        '501':
          description: Embedded auth mode only
  /users:
    get:
      tags:
        - Auth Users
      summary: List embedded auth users
      operationId: listAuthUsers
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/AuthUserResponse'
        '401':
          description: Not Authorized
        '501':
          description: Embedded auth mode only
    post:
      tags:
        - Auth Users
      summary: Create embedded auth user
      operationId: createAuthUser
      description: >
        Admin-created users receive `mustChangePassword: true` so the first
        login forces a password change (browser interaction step or CLI JWT
        `password_change_required` gate).
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthUserCreateRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthUserResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: Conflict
        '501':
          description: Embedded auth mode only
  /users/{id}:
    get:
      tags:
        - Auth Users
      summary: Get embedded auth user
      operationId: getAuthUser
      security:
        - authToken: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthUserResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '501':
          description: Embedded auth mode only
    patch:
      tags:
        - Auth Users
      summary: Update embedded auth user
      operationId: updateAuthUser
      security:
        - authToken: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthUserUpdateRequest'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthUserResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '501':
          description: Embedded auth mode only
    delete:
      tags:
        - Auth Users
      summary: Soft-delete embedded auth user
      operationId: deleteAuthUser
      security:
        - authToken: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '204':
          description: Deleted
        '401':
          description: Not Authorized
        '403':
          description: Forbidden
        '404':
          description: Not Found
        '501':
          description: Embedded auth mode only
  /users/{id}/reset-password:
    post:
      tags:
        - Auth Users
      summary: Reset user password to a temporary value
      operationId: resetAuthUserPassword
      security:
        - authToken: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthUserResetPasswordResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '501':
          description: Embedded auth mode only
  /users/{id}/reset-token:
    post:
      tags:
        - Auth Users
      summary: Issue a one-time password reset token
      operationId: resetAuthUserToken
      security:
        - authToken: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthUserResetTokenResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '501':
          description: Embedded auth mode only
  /groups:
    get:
      tags:
        - Auth Groups
      summary: List auth groups
      operationId: listAuthGroups
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/AuthGroupResponse'
        '401':
          description: Not Authorized
        '501':
          description: Embedded auth mode only
    post:
      tags:
        - Auth Groups
      summary: Create custom auth group
      operationId: createAuthGroup
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthGroupCreateRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthGroupResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: Conflict
        '501':
          description: Embedded auth mode only
  /groups/{name}:
    get:
      tags:
        - Auth Groups
      summary: Get auth group
      operationId: getAuthGroup
      security:
        - authToken: []
      parameters:
        - name: name
          in: path
          required: true
          schema:
            type: string
          description: Unique auth group name (e.g. viewer, platform-ops)
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthGroupResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '501':
          description: Embedded auth mode only
    patch:
      tags:
        - Auth Groups
      summary: Update auth group
      operationId: updateAuthGroup
      description: >
        Updates a custom auth group name and/or `mfaRequired`. System groups
        (`admin`, `sre`, `developer`, `viewer`) allow `mfaRequired` changes
        only; rename is forbidden. Requires RBAC `authGroups` resource with
        `patch` verb.
      security:
        - authToken: []
      parameters:
        - name: name
          in: path
          required: true
          schema:
            type: string
          description: Current auth group name
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthGroupUpdateRequest'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthGroupResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '403':
          description: Forbidden
        '404':
          description: Not Found
        '501':
          description: Embedded auth mode only
    delete:
      tags:
        - Auth Groups
      summary: Delete custom auth group
      operationId: deleteAuthGroup
      security:
        - authToken: []
      parameters:
        - name: name
          in: path
          required: true
          schema:
            type: string
          description: Auth group name
      responses:
        '204':
          description: Deleted
        '401':
          description: Not Authorized
        '403':
          description: Forbidden
        '404':
          description: Not Found
        '501':
          description: Embedded auth mode only
  /secrets:
    post:
      tags:
        - Secrets
      summary: Creates a new secret
      operationId: createSecret
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SecretCreate'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SecretResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: Secret Already Exists
        '500':
          description: Internal Server Error
    get:
      tags:
        - Secrets
      summary: Lists all secrets
      operationId: listSecrets
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SecretListResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /secrets/{name}:
    get:
      tags:
        - Secrets
      summary: Gets a secret by name
      operationId: getSecret
      parameters:
        - in: path
          name: name
          description: Secret name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SecretResponse'
        '401':
          description: Not Authorized
        '404':
          description: Secret Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Secrets
      summary: Updates an existing secret
      operationId: updateSecret
      parameters:
        - in: path
          name: name
          description: Secret name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SecretUpdate'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SecretResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Secret Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Secrets
      summary: Deletes a secret
      operationId: deleteSecret
      parameters:
        - in: path
          name: name
          description: Secret name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
        '401':
          description: Not Authorized
        '404':
          description: Secret Not Found
        '500':
          description: Internal Server Error
  /secrets/yaml:
    post:
      tags:
        - Secrets
      summary: Create a secret from YAML file
      operationId: createSecretFromYAML
      security:
        - authToken: []
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                secret:
                  type: string
                  format: binary
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SecretResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: Secret Already Exists
        '500':
          description: Internal Server Error
  /secrets/yaml/{name}:
    patch:
      tags:
        - Secrets
      summary: Updates an existing secret using YAML
      operationId: updateSecretFromYAML
      parameters:
        - in: path
          name: name
          description: Secret name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                secret:
                  type: string
                  format: binary
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SecretResponse'
        '400':
          description: Bad Request
        '401':
          description: Unauthorized
        '404':
          description: Secret Not Found
  /certificates/ca/{name}:
    get:
      tags:
        - Certificates
      summary: Get a Certificate Authority (CA) by name
      operationId: getCA
      parameters:
        - in: path
          name: name
          description: CA name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CAResponse'
        '401':
          description: Unauthorized
        '404':
          description: CA not found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Certificates
      summary: Delete a Certificate Authority (CA) by name
      operationId: deleteCA
      parameters:
        - in: path
          name: name
          description: CA name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
        '401':
          description: Unauthorized
        '404':
          description: CA not found
        '500':
          description: Internal Server Error
  /certificates:
    post:
      tags:
        - Certificates
      summary: Create a new certificate
      operationId: createCertificate
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CertificateCreateRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CertificateResponse'
        '400':
          description: Bad Request
        '401':
          description: Unauthorized
        '404':
          description: Not Found - Referenced CA not found
        '409':
          description: Conflict - Certificate already exists
    get:
      tags:
        - Certificates
      summary: List all certificates
      operationId: listCertificates
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CertificateListResponse'
        '401':
          description: Unauthorized
        '500':
          description: Internal Server Error
  /certificates/expiring:
    get:
      tags:
        - Certificates
      summary: List certificates that will expire soon
      operationId: listExpiringCertificates
      parameters:
        - in: query
          name: days
          description: Number of days ahead to check for expiration (default 30)
          required: false
          schema:
            type: integer
            default: 30
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CertificateListResponse'
        '400':
          description: Bad Request
        '401':
          description: Unauthorized
        '500':
          description: Internal Server Error
  /certificates/{name}:
    get:
      tags:
        - Certificates
      summary: Get a certificate by name
      operationId: getCertificate
      parameters:
        - in: path
          name: name
          description: Certificate name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CertificateResponse'
        '401':
          description: Unauthorized
        '404':
          description: Certificate not found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Certificates
      summary: Delete a certificate by name
      operationId: deleteCertificate
      parameters:
        - in: path
          name: name
          description: Certificate name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
        '401':
          description: Unauthorized
        '404':
          description: Certificate not found
        '500':
          description: Internal Server Error
  /certificates/{name}/renew:
    post:
      tags:
        - Certificates
      summary: Renew a certificate
      operationId: renewCertificate
      parameters:
        - in: path
          name: name
          description: Certificate name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CertificateRenewResponse'
        '400':
          description: Bad Request
        '401':
          description: Unauthorized
        '404':
          description: Certificate not found
        '500':
          description: Internal Server Error
  /certificates/yaml:
    post:
      tags:
        - Certificates
      summary: Create a certificate or CA from YAML file
      operationId: createCertificateFromYAML
      security:
        - authToken: []
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                certificate:
                  type: string
                  format: binary
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/CAResponse'
                  - $ref: '#/components/schemas/CertificateResponse'
        '400':
          description: Bad Request
        '401':
          description: Unauthorized
        '404':
          description: Not Found - Referenced CA not found
        '409':
          description: Conflict - Certificate or CA already exists
  /services:
    get:
      tags:
        - Services
      summary: Gets list of services
      operationId: getServicesList
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Service'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
    post:
      tags:
        - Services
      summary: Creates a new service
      operationId: createService
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Service'
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Service'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: Duplicate Name
        '500':
          description: Internal Server Error
  /services/{name}:
    get:
      tags:
        - Services
      summary: Gets a service info
      operationId: getServiceInfo
      parameters:
        - in: path
          name: name
          description: Service name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Service'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Services
      summary: Deletes a service
      operationId: deleteService
      parameters:
        - in: path
          name: name
          description: Service name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Services
      summary: Patches a service
      operationId: patchService
      parameters:
        - in: path
          name: name
          description: Service name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Service'
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Service'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /services/{name}/reconcile:
    post:
      tags:
        - Services
      summary: Manually retries service platform reconcile
      description: >-
        Enqueues a service platform reconcile task. When `provisioningStatus` is
        `failed`, resets it to `pending` and clears `provisioningError` before
        enqueue. Hub connector/listener, K8s Service, and ConfigMap updates run
        asynchronously in the platform reconcile worker.
        `provisioningStatus=ready` means hub provisioning completed
        successfully; tagged edge fogs receive bridge updates via separate fog
        platform reconcile tasks.
      operationId: reconcileService
      parameters:
        - in: path
          name: name
          description: Service name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Service'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /services/yaml:
    post:
      tags:
        - Services
      summary: Creates a new service from YAML
      operationId: createServiceYAML
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                service:
                  type: string
                  format: binary
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: number
                  name:
                    type: string
                  type:
                    type: string
                  resource:
                    type: string
                  targetPort:
                    type: number
                  defaultBridge:
                    type: string
                  bridgePort:
                    type: number
                  updatedAt:
                    type: string
                    format: date-time
                  createdAt:
                    type: string
                    format: date-time
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: Duplicate Name
        '500':
          description: Internal Server Error
  /services/yaml/{name}:
    patch:
      tags:
        - Services
      summary: Updates a service using YAML
      operationId: updateServiceYAML
      parameters:
        - in: path
          name: name
          description: Service name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                service:
                  type: string
                  format: binary
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Service'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /configmaps:
    post:
      tags:
        - ConfigMap
      summary: Creates a new ConfigMap
      operationId: createConfigMap
      security:
        - authToken: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConfigMapCreate'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConfigMapResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: ConfigMap Already Exists
        '500':
          description: Internal Server Error
    get:
      tags:
        - ConfigMap
      summary: Lists all ConfigMaps
      operationId: listConfigMaps
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConfigMapListResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /configmaps/yaml:
    post:
      tags:
        - ConfigMap
      summary: Creates a new ConfigMap from YAML
      operationId: createConfigMapFromYaml
      security:
        - authToken: []
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                configMap:
                  type: string
                  format: binary
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConfigMapResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: ConfigMap Already Exists
        '500':
          description: Internal Server Error
  /configmaps/{name}:
    get:
      tags:
        - ConfigMap
      summary: Gets a ConfigMap by name
      operationId: getConfigMap
      security:
        - authToken: []
      parameters:
        - in: path
          name: name
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConfigMapResponse'
        '401':
          description: Not Authorized
        '404':
          description: ConfigMap Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - ConfigMap
      summary: Updates a ConfigMap
      operationId: updateConfigMap
      security:
        - authToken: []
      parameters:
        - in: path
          name: name
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConfigMapUpdate'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConfigMapResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: ConfigMap Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - ConfigMap
      summary: Deletes a ConfigMap
      operationId: deleteConfigMap
      security:
        - authToken: []
      parameters:
        - in: path
          name: name
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
        '401':
          description: Not Authorized
        '404':
          description: ConfigMap Not Found
        '500':
          description: Internal Server Error
  /configmaps/yaml/{name}:
    patch:
      tags:
        - ConfigMap
      summary: Updates a ConfigMap from YAML
      operationId: updateConfigMapFromYaml
      security:
        - authToken: []
      parameters:
        - in: path
          name: name
          required: true
          schema:
            type: string
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                configMap:
                  type: string
                  format: binary
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConfigMapResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: ConfigMap Not Found
        '500':
          description: Internal Server Error
  /volumeMounts:
    get:
      tags:
        - VolumeMounts
      summary: Returns list of volume mounts
      operationId: listVolumeMounts
      security:
        - authToken: []
      responses:
        '200':
          description: List of volume mounts
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/VolumeMount'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
    post:
      tags:
        - VolumeMounts
      summary: Creates a new volume mount
      operationId: createVolumeMount
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VolumeMountCreate'
      responses:
        '200':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VolumeMount'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /volumeMounts/yaml:
    post:
      tags:
        - VolumeMounts
      summary: Creates a new volume mount from YAML
      operationId: createVolumeMountYaml
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/x-yaml:
            schema:
              type: string
      responses:
        '200':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VolumeMount'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /volumeMounts/{name}:
    get:
      tags:
        - VolumeMounts
      summary: Gets volume mount info
      operationId: getVolumeMount
      parameters:
        - in: path
          name: name
          description: Volume mount name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VolumeMount'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - VolumeMounts
      summary: Updates existing volume mount
      operationId: updateVolumeMount
      parameters:
        - in: path
          name: name
          description: Volume mount name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VolumeMountUpdate'
      responses:
        '200':
          description: Updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VolumeMount'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - VolumeMounts
      summary: Deletes a volume mount
      operationId: deleteVolumeMount
      parameters:
        - in: path
          name: name
          description: Volume mount name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '202':
          description: Accepted
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /volumeMounts/yaml/{name}:
    patch:
      tags:
        - VolumeMounts
      summary: Updates existing volume mount from YAML
      operationId: updateVolumeMountYaml
      parameters:
        - in: path
          name: name
          description: Volume mount name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/x-yaml:
            schema:
              type: string
      responses:
        '200':
          description: Updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VolumeMount'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /volumeMounts/{name}/link:
    get:
      tags:
        - VolumeMounts
      summary: Gets volume mount link info
      operationId: getVolumeMountLink
      parameters:
        - in: path
          name: name
          description: Volume mount name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  fogUuids:
                    type: array
                    items:
                      type: string
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    post:
      tags:
        - VolumeMounts
      summary: Links volume mount to fog nodes
      operationId: linkVolumeMount
      parameters:
        - in: path
          name: name
          description: Volume mount name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VolumeMountLink'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VolumeMount'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - VolumeMounts
      summary: Unlinks volume mount from fog nodes
      operationId: unlinkVolumeMount
      parameters:
        - in: path
          name: name
          description: Volume mount name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VolumeMountUnlink'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VolumeMount'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /events:
    get:
      tags:
        - Events
      summary: List audit events
      description: Retrieve audit events with optional filters and pagination.
      operationId: listEvents
      security:
        - authToken: []
      parameters:
        - in: query
          name: limit
          description: Maximum number of events to return (default 200, max 1000)
          schema:
            type: integer
            minimum: 1
            maximum: 1000
          required: false
        - in: query
          name: offset
          description: Number of events to skip before collecting results
          schema:
            type: integer
            minimum: 0
          required: false
        - in: query
          name: startTime
          description: Start of time range (Unix timestamp in ms or ISO 8601)
          schema:
            type: string
          required: false
        - in: query
          name: endTime
          description: End of time range (Unix timestamp in ms or ISO 8601)
          schema:
            type: string
          required: false
        - in: query
          name: endpointType
          description: Filter by endpoint type (agent or user)
          schema:
            type: string
          required: false
        - in: query
          name: resourceType
          description: Filter by resource type (agent, microservice, etc.)
          schema:
            type: string
          required: false
        - in: query
          name: status
          description: Filter by status (SUCCESS or FAILED)
          schema:
            type: string
          required: false
        - in: query
          name: method
          description: Filter by HTTP/WS method(s)
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
          required: false
        - in: query
          name: actorId
          description: Filter by actor identifier (username or fog UUID)
          schema:
            type: string
          required: false
        - in: query
          name: eventType
          description: Filter by event type (HTTP, WS_CONNECT, WS_DISCONNECT)
          schema:
            type: string
          required: false
      responses:
        '200':
          description: Events list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventListResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Events
      summary: Delete audit events
      description: >-
        Delete all events when `days` is 0, or delete events older than the
        provided number of days.
      operationId: deleteEvents
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EventDeleteRequest'
      responses:
        '200':
          description: Deletion summary
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventDeleteResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /roles:
    get:
      tags:
        - Roles
      summary: Lists all roles
      operationId: listRoles
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleListResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
    post:
      tags:
        - Roles
      summary: Creates a new role
      operationId: createRole
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RoleCreateRequest'
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: Role Already Exists
        '500':
          description: Internal Server Error
  /roles/yaml:
    post:
      tags:
        - Roles
      summary: Create a role from YAML file
      operationId: createRoleFromYAML
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                role:
                  type: string
                  format: binary
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: Role Already Exists
        '500':
          description: Internal Server Error
  /roles/{name}:
    get:
      tags:
        - Roles
      summary: Gets a role by name
      operationId: getRole
      parameters:
        - in: path
          name: name
          description: Role name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleResponse'
        '401':
          description: Not Authorized
        '404':
          description: Role Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - Roles
      summary: Updates an existing role
      operationId: updateRole
      parameters:
        - in: path
          name: name
          description: Role name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RoleCreateRequest'
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Role Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - Roles
      summary: Deletes a role
      operationId: deleteRole
      parameters:
        - in: path
          name: name
          description: Role name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: Role Not Found
        '500':
          description: Internal Server Error
  /roles/yaml/{name}:
    patch:
      tags:
        - Roles
      summary: Updates an existing role using YAML
      operationId: updateRoleFromYAML
      parameters:
        - in: path
          name: name
          description: Role name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                role:
                  type: string
                  format: binary
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Role Not Found
        '500':
          description: Internal Server Error
  /rolebindings:
    get:
      tags:
        - RoleBindings
      summary: Lists all role bindings
      operationId: listRoleBindings
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleBindingListResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
    post:
      tags:
        - RoleBindings
      summary: Creates a new role binding
      operationId: createRoleBinding
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RoleBindingCreateRequest'
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleBindingResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: RoleBinding Already Exists
        '500':
          description: Internal Server Error
  /rolebindings/yaml:
    post:
      tags:
        - RoleBindings
      summary: Create a role binding from YAML file
      operationId: createRoleBindingFromYAML
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                rolebinding:
                  type: string
                  format: binary
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleBindingResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: RoleBinding Already Exists
        '500':
          description: Internal Server Error
  /rolebindings/{name}:
    get:
      tags:
        - RoleBindings
      summary: Gets a role binding by name
      operationId: getRoleBinding
      parameters:
        - in: path
          name: name
          description: RoleBinding name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleBindingResponse'
        '401':
          description: Not Authorized
        '404':
          description: RoleBinding Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - RoleBindings
      summary: Updates an existing role binding
      operationId: updateRoleBinding
      parameters:
        - in: path
          name: name
          description: RoleBinding name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RoleBindingCreateRequest'
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleBindingResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: RoleBinding Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - RoleBindings
      summary: Deletes a role binding
      operationId: deleteRoleBinding
      parameters:
        - in: path
          name: name
          description: RoleBinding name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: RoleBinding Not Found
        '500':
          description: Internal Server Error
  /rolebindings/yaml/{name}:
    patch:
      tags:
        - RoleBindings
      summary: Updates an existing role binding using YAML
      operationId: updateRoleBindingFromYAML
      parameters:
        - in: path
          name: name
          description: RoleBinding name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                rolebinding:
                  type: string
                  format: binary
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleBindingResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: RoleBinding Not Found
        '500':
          description: Internal Server Error
  /network-topology/summary:
    get:
      tags:
        - NetworkTopology
      summary: Network topology summary counts
      operationId: getNetworkTopologySummary
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NetworkTopologySummaryResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /network-topology/router/overview:
    get:
      tags:
        - NetworkTopology
      summary: Router topology overview
      operationId: getRouterTopologyOverview
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterTopologyOverviewResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /network-topology/nats/overview:
    get:
      tags:
        - NetworkTopology
      summary: NATS topology overview
      operationId: getNatsTopologyOverview
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsTopologyOverviewResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /network-topology/router/nodes:
    get:
      tags:
        - NetworkTopology
      summary: List router topology nodes
      operationId: listRouterTopologyNodes
      security:
        - authToken: []
      parameters:
        - $ref: '#/components/parameters/NetworkTopologyLimitParam'
        - $ref: '#/components/parameters/NetworkTopologyOffsetParam'
        - $ref: '#/components/parameters/NetworkTopologyRouterRoleParam'
        - $ref: '#/components/parameters/NetworkTopologyDeploymentTargetParam'
        - $ref: '#/components/parameters/NetworkTopologySearchParam'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterTopologyNodeListResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /network-topology/nats/nodes:
    get:
      tags:
        - NetworkTopology
      summary: List NATS topology nodes
      operationId: listNatsTopologyNodes
      security:
        - authToken: []
      parameters:
        - $ref: '#/components/parameters/NetworkTopologyLimitParam'
        - $ref: '#/components/parameters/NetworkTopologyOffsetParam'
        - $ref: '#/components/parameters/NetworkTopologyNatsRoleParam'
        - $ref: '#/components/parameters/NetworkTopologyDeploymentTargetParam'
        - $ref: '#/components/parameters/NetworkTopologySearchParam'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsTopologyNodeListResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /network-topology/router/nodes/{id}:
    get:
      tags:
        - NetworkTopology
      summary: Get a router topology node
      operationId: getRouterTopologyNode
      security:
        - authToken: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
          description: Router node id (`default-router` or agent iofog UUID)
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterTopologyNodeDetail'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /network-topology/nats/nodes/{id}:
    get:
      tags:
        - NetworkTopology
      summary: Get a NATS topology node
      operationId: getNatsTopologyNode
      security:
        - authToken: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
          description: NATS node id (`default-nats-hub` or agent iofog UUID)
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsTopologyNodeDetail'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /network-topology/router/nodes/{id}/connections:
    get:
      tags:
        - NetworkTopology
      summary: Get router node connections
      operationId: getRouterTopologyNodeConnections
      security:
        - authToken: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TopologyNodeConnectionsResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /network-topology/nats/nodes/{id}/connections:
    get:
      tags:
        - NetworkTopology
      summary: Get NATS node connections
      operationId: getNatsTopologyNodeConnections
      security:
        - authToken: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TopologyNodeConnectionsResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /network-topology/router/connections:
    get:
      tags:
        - NetworkTopology
      summary: List router topology connections
      operationId: listRouterTopologyConnections
      security:
        - authToken: []
      parameters:
        - $ref: '#/components/parameters/NetworkTopologyLimitParam'
        - $ref: '#/components/parameters/NetworkTopologyOffsetParam'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RouterTopologyConnectionListResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /network-topology/nats/connections:
    get:
      tags:
        - NetworkTopology
      summary: List NATS topology connections
      operationId: listNatsTopologyConnections
      security:
        - authToken: []
      parameters:
        - $ref: '#/components/parameters/NetworkTopologyLimitParam'
        - $ref: '#/components/parameters/NetworkTopologyOffsetParam'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsTopologyConnectionListResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /network-topology/router/subgraph:
    get:
      tags:
        - NetworkTopology
      summary: Get router topology subgraph
      operationId: getRouterTopologySubgraph
      security:
        - authToken: []
      parameters:
        - in: query
          name: center
          required: true
          schema:
            type: string
        - in: query
          name: depth
          schema:
            type: integer
            minimum: 1
            maximum: 2
            default: 1
        - $ref: '#/components/parameters/NetworkTopologyLimitParam'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TopologySubgraphResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /network-topology/nats/subgraph:
    get:
      tags:
        - NetworkTopology
      summary: Get NATS topology subgraph
      operationId: getNatsTopologySubgraph
      security:
        - authToken: []
      parameters:
        - in: query
          name: center
          required: true
          schema:
            type: string
        - in: query
          name: depth
          schema:
            type: integer
            minimum: 1
            maximum: 2
            default: 1
        - $ref: '#/components/parameters/NetworkTopologyLimitParam'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TopologySubgraphResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
        '500':
          description: Internal Server Error
  /router:
    get:
      tags:
        - Router
      summary: Gets the default network router configuration
      operationId: getDefaultRouter
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefaultRouterResponse'
        '401':
          description: Not Authorized
        '404':
          description: Default router not found
        '500':
          description: Internal Server Error
    put:
      tags:
        - Router
      summary: Creates or updates the default network router
      operationId: upsertDefaultRouter
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DefaultRouterUpsertRequest'
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefaultRouterRecordResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
  /serviceaccounts:
    get:
      tags:
        - ServiceAccounts
      summary: Lists all service accounts
      operationId: listServiceAccounts
      parameters:
        - in: query
          name: applicationName
          description: Filter by application name
          required: false
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceAccountListResponse'
        '401':
          description: Not Authorized
        '500':
          description: Internal Server Error
    post:
      tags:
        - ServiceAccounts
      summary: Creates a new service account
      operationId: createServiceAccount
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ServiceAccountCreateRequest'
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceAccountResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: ServiceAccount Already Exists
        '500':
          description: Internal Server Error
  /serviceaccounts/yaml:
    post:
      tags:
        - ServiceAccounts
      summary: Create a service account from YAML file
      description: >
        The YAML file must include metadata.applicationName (application name
        this service account belongs to),

        metadata.name (service account name), and roleRef with a name. Example:

        kind: ServiceAccount

        metadata:
          name: my-sa
          applicationName: my-app
        roleRef:
          kind: Role
          name: microservice
      operationId: createServiceAccountFromYAML
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                serviceaccount:
                  type: string
                  format: binary
      responses:
        '201':
          description: Created
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceAccountResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '409':
          description: ServiceAccount Already Exists
        '500':
          description: Internal Server Error
  /serviceaccounts/{appName}/{name}:
    get:
      tags:
        - ServiceAccounts
      summary: Gets a service account by application name and service account name
      operationId: getServiceAccount
      parameters:
        - in: path
          name: appName
          description: Application name
          required: true
          schema:
            type: string
        - in: path
          name: name
          description: ServiceAccount name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceAccountResponse'
        '401':
          description: Not Authorized
        '404':
          description: ServiceAccount Not Found
        '500':
          description: Internal Server Error
    patch:
      tags:
        - ServiceAccounts
      summary: Updates an existing service account
      operationId: updateServiceAccount
      parameters:
        - in: path
          name: appName
          description: Application name
          required: true
          schema:
            type: string
        - in: path
          name: name
          description: ServiceAccount name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ServiceAccountCreateRequest'
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceAccountResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: ServiceAccount Not Found
        '500':
          description: Internal Server Error
    delete:
      tags:
        - ServiceAccounts
      summary: Deletes a service account
      operationId: deleteServiceAccount
      parameters:
        - in: path
          name: appName
          description: Application name
          required: true
          schema:
            type: string
        - in: path
          name: name
          description: ServiceAccount name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
        '401':
          description: Not Authorized
        '404':
          description: ServiceAccount Not Found
        '409':
          description: Conflict - ServiceAccount is referenced by a microservice
        '500':
          description: Internal Server Error
  /serviceaccounts/yaml/{appName}/{name}:
    patch:
      tags:
        - ServiceAccounts
      summary: Updates an existing service account using YAML
      operationId: updateServiceAccountFromYAML
      parameters:
        - in: path
          name: appName
          description: Application name
          required: true
          schema:
            type: string
        - in: path
          name: name
          description: ServiceAccount name
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                serviceaccount:
                  type: string
                  format: binary
      responses:
        '200':
          description: Success
          headers:
            X-Timestamp:
              description: FogController server timestamp
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceAccountResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: ServiceAccount Not Found
        '500':
          description: Internal Server Error
  /nats/operator:
    get:
      tags:
        - NATS
      summary: Gets current NATS operator metadata
      operationId: getNatsOperator
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsOperatorResponse'
        '401':
          description: Not Authorized
  /nats/operator/rotate:
    post:
      tags:
        - NATS
      summary: Rotates NATS operator keys and JWT
      description: >-
        Schedules account/user re-sign and resolver reconciliation in background
        after operator rotation is accepted.
      operationId: rotateNatsOperator
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsOperatorResponse'
        '401':
          description: Not Authorized
  /nats/bootstrap:
    get:
      tags:
        - NATS
      summary: >-
        Returns NATS operator and hub system user bootstrap data for K8s
        installer
      operationId: getNatsBootstrap
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsBootstrapResponse'
        '401':
          description: Not Authorized
        '403':
          description: >-
            Forbidden (only available when Controller runs on Kubernetes control
            plane)
        '404':
          description: Not Found (bootstrap data or secrets missing)
  /nats/hub:
    get:
      tags:
        - NATS
      summary: Gets default NATS hub configuration
      operationId: getNatsHub
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsHubResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
    put:
      tags:
        - NATS
      summary: Creates or updates default NATS hub
      operationId: upsertNatsHub
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NatsHubRequest'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsHubResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
  /nats/users:
    get:
      tags:
        - NATS
      summary: Lists all NATS users across accounts
      operationId: listAllNatsUsers
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsAllUsersListResponse'
        '401':
          description: Not Authorized
  /nats/accounts:
    get:
      tags:
        - NATS
      summary: Lists NATS accounts
      operationId: listNatsAccounts
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsAccountsListResponse'
        '401':
          description: Not Authorized
  /nats/accounts/{appName}:
    get:
      tags:
        - NATS
      summary: Gets NATS account for application
      operationId: getNatsAccountByApp
      parameters:
        - in: path
          name: appName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsAccountResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
    post:
      tags:
        - NATS
      summary: Ensures NATS account for application
      operationId: ensureNatsAccountByApp
      parameters:
        - in: path
          name: appName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NatsAccountEnsureRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsAccountResponse'
        '400':
          description: >-
            Bad Request (e.g. application already has NATS enabled or unknown
            rule name)
        '401':
          description: Not Authorized
        '404':
          description: Not Found
  /nats/accounts/{appName}/users:
    get:
      tags:
        - NATS
      summary: Lists NATS users for application account
      operationId: listNatsUsersByApp
      parameters:
        - in: path
          name: appName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsUsersListResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
    post:
      tags:
        - NATS
      summary: Creates NATS user for application account
      operationId: createNatsUserByApp
      parameters:
        - in: path
          name: appName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NatsUserCreateRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsUserResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
  /nats/accounts/{appName}/users/{userName}/creds:
    get:
      tags:
        - NATS
      summary: Gets NATS creds for specific account user
      description: >
        Returns base64-encoded `.creds` file content for the user.


        Path `{appName}` is an **application name** for app-linked accounts, or
        a **NATS account name** for platform/system accounts (`SYS`, leaf
        accounts, **`controller`**).
      operationId: getNatsUserCreds
      parameters:
        - in: path
          name: appName
          required: true
          description: Application name or NATS account name (e.g. `SYS`, `controller`)
          schema:
            type: string
        - in: path
          name: userName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsCredsResponse'
        '401':
          description: Not Authorized
        '404':
          description: Not Found
  /nats/accounts/{appName}/users/{userName}:
    delete:
      tags:
        - NATS
      summary: Deletes NATS account user
      operationId: deleteNatsUserByApp
      parameters:
        - in: path
          name: appName
          required: true
          schema:
            type: string
        - in: path
          name: userName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request (e.g. user linked to existing microservice)
        '401':
          description: Not Authorized
        '404':
          description: Not Found
  /nats/accounts/{appName}/mqtt-bearer:
    post:
      tags:
        - NATS
      summary: Creates MQTT bearer NATS user JWT
      operationId: createNatsMqttBearer
      parameters:
        - in: path
          name: appName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NatsUserCreateRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsUserResponse'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
  /nats/accounts/{appName}/mqtt-bearer/{userName}:
    delete:
      tags:
        - NATS
      summary: Deletes MQTT bearer NATS user
      operationId: deleteNatsMqttBearer
      parameters:
        - in: path
          name: appName
          required: true
          schema:
            type: string
        - in: path
          name: userName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request (e.g. not a bearer user or user linked to microservice)
        '401':
          description: Not Authorized
        '404':
          description: Not Found
  /nats/account-rules:
    get:
      tags:
        - NATS
      summary: Lists NATS account rules
      operationId: listNatsAccountRules
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsAccountRuleListResponse'
        '401':
          description: Not Authorized
    post:
      tags:
        - NATS
      summary: Creates NATS account rule
      operationId: createNatsAccountRule
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NatsAccountRulePayload'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsAccountRulePayload'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
  /nats/account-rules/yaml:
    post:
      tags:
        - NATS
      summary: Creates NATS account rule from YAML
      operationId: createNatsAccountRuleYaml
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                natsAccountRule:
                  type: string
                  format: binary
      responses:
        '201':
          description: Created
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
  /nats/account-rules/{ruleName}:
    patch:
      tags:
        - NATS
      summary: Updates NATS account rule
      description: >-
        Returns updated rule immediately and schedules downstream account JWT
        reissue/reconciliation in background.
      operationId: updateNatsAccountRule
      parameters:
        - in: path
          name: ruleName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NatsAccountRulePayload'
      responses:
        '200':
          description: Success
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
    delete:
      tags:
        - NATS
      summary: Deletes NATS account rule
      description: >-
        Rebinds applications using this rule to default rule and schedules
        account JWT reissue/reconciliation in background.
      operationId: deleteNatsAccountRule
      parameters:
        - in: path
          name: ruleName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Deleted
        '401':
          description: Not Authorized
        '404':
          description: Not Found
  /nats/account-rules/yaml/{ruleName}:
    patch:
      tags:
        - NATS
      summary: Updates NATS account rule from YAML
      description: >-
        Returns updated rule immediately and schedules downstream account JWT
        reissue/reconciliation in background.
      operationId: updateNatsAccountRuleYaml
      parameters:
        - in: path
          name: ruleName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                natsAccountRule:
                  type: string
                  format: binary
      responses:
        '200':
          description: Updated
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
  /nats/user-rules:
    get:
      tags:
        - NATS
      summary: Lists NATS user rules
      operationId: listNatsUserRules
      security:
        - authToken: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsUserRuleListResponse'
        '401':
          description: Not Authorized
    post:
      tags:
        - NATS
      summary: Creates NATS user rule
      operationId: createNatsUserRule
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NatsUserRulePayload'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NatsUserRulePayload'
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
  /nats/user-rules/yaml:
    post:
      tags:
        - NATS
      summary: Creates NATS user rule from YAML
      operationId: createNatsUserRuleYaml
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                natsUserRule:
                  type: string
                  format: binary
      responses:
        '201':
          description: Created
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
  /nats/user-rules/{ruleName}:
    patch:
      tags:
        - NATS
      summary: Updates NATS user rule
      description: >-
        Returns updated rule immediately and schedules bound user JWT+creds
        reissue/reconciliation in background.
      operationId: updateNatsUserRule
      parameters:
        - in: path
          name: ruleName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NatsUserRulePayload'
      responses:
        '200':
          description: Updated
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
    delete:
      tags:
        - NATS
      summary: Deletes NATS user rule
      description: >-
        Rebinds microservices using this rule to default rule and schedules user
        JWT+creds reissue/reconciliation in background.
      operationId: deleteNatsUserRule
      parameters:
        - in: path
          name: ruleName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      responses:
        '204':
          description: Deleted
        '401':
          description: Not Authorized
        '404':
          description: Not Found
  /nats/user-rules/yaml/{ruleName}:
    patch:
      tags:
        - NATS
      summary: Updates NATS user rule from YAML
      description: >-
        Returns updated rule immediately and schedules bound user JWT+creds
        reissue/reconciliation in background.
      operationId: updateNatsUserRuleYaml
      parameters:
        - in: path
          name: ruleName
          required: true
          schema:
            type: string
      security:
        - authToken: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                natsUserRule:
                  type: string
                  format: binary
      responses:
        '200':
          description: Updated
        '400':
          description: Bad Request
        '401':
          description: Not Authorized
        '404':
          description: Not Found
tags:
  - name: Controller
    description: Manage your controller
  - name: ioFog
    description: Manage your agents
  - name: Application
    description: Manage your applications
  - name: Application Template
    description: Manage your application templates
  - name: Catalog
    description: Manage your catalog
  - name: Registries
    description: Manage your registries
  - name: Microservices
    description: Manage your microservices
  - name: NATS
    description: Manage NATS operator, hub, accounts, users, and rules
  - name: Tunnel
    description: Manage ssh tunnels
  - name: Agent
    description: Used by your agents to communicate with your controller
  - name: WebSocketSessions
    description: >
      Interactive exec and log streaming WebSocket endpoints (MessagePack
      binary).

      Multi-replica HA requires a relay backend per **`nats.enabled`** (AMQP
      when `false`, NATS Core when `true`) - see operations/ws-sessions.md.
  - name: User
    description: Manage your users
  - name: Secrets
    description: Manage your secrets
  - name: Certificates
    description: Manage your certificates
  - name: Services
    description: Manage your services
  - name: VolumeMounts
    description: Manage your volume mounts
  - name: ConfigMap
    description: Manage your config maps
  - name: Events
    description: Manage audit events
  - name: Roles
    description: Manage RBAC roles
  - name: RoleBindings
    description: Manage RBAC role bindings
  - name: Router
    description: Manage the default router configuration
  - name: NetworkTopology
    description: Read-only router and NATS network topology for visualization
  - name: ServiceAccounts
    description: Manage RBAC service accounts
servers:
  - url: http://localhost:51121/api/v3
components:
  securitySchemes:
    authToken:
      type: http
      scheme: bearer
      bearerFormat: JWT
    fogToken:
      type: http
      scheme: bearer
      description: Edgelet fog provisioning token (agent routes)
  parameters:
    NetworkTopologyLimitParam:
      in: query
      name: limit
      required: false
      schema:
        type: integer
        minimum: 1
        maximum: 500
        default: 100
    NetworkTopologyOffsetParam:
      in: query
      name: offset
      required: false
      schema:
        type: integer
        minimum: 0
        default: 0
    NetworkTopologyDeploymentTargetParam:
      in: query
      name: deploymentTarget
      required: false
      schema:
        type: string
        enum:
          - kubernetes
          - remote
          - edgelet
    NetworkTopologySearchParam:
      in: query
      name: search
      required: false
      schema:
        type: string
    NetworkTopologyRouterRoleParam:
      in: query
      name: role
      required: false
      schema:
        type: string
        enum:
          - default
          - edge
          - interior
    NetworkTopologyNatsRoleParam:
      in: query
      name: role
      required: false
      schema:
        type: string
        enum:
          - hub
          - leaf
          - server
  responses:
    AuthRateLimitExceeded:
      description: Too many authentication requests from this IP address
      headers:
        Retry-After:
          description: Seconds until the current rate-limit window resets
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RateLimitExceededResponse'
  requestBodies:
    UpdateIOFogNodeRequestBody:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/UpdateIOFogNodeRequestBody'
      required: true
    CreateUpdateCatalogItemRequestBody:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/CreateUpdateCatalogItemRequestBody'
      description: Microservice Catalog Item Info
      required: true
    HalInfo:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/HalInfo'
      required: true
    ApplicationTemplateCreateRequest:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApplicationTemplateCreateRequest'
      required: true
  schemas:
    WsExecMessageTypes:
      type: object
      description: MessagePack frame types for exec sessions
      properties:
        types:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              value:
                type: integer
              direction:
                type: string
      example:
        types:
          - name: STDIN
            value: 0
            direction: user → agent
          - name: STDOUT
            value: 1
            direction: agent → user
          - name: STDERR
            value: 2
            direction: agent → user
          - name: CONTROL
            value: 3
            direction: both
          - name: CLOSE
            value: 4
            direction: both
          - name: ACTIVATION
            value: 5
            direction: controller → user (session announce); controller → agent (optional
            shell live): null
    WsLogMessageTypes:
      type: object
      description: MessagePack frame types for log sessions (R82)
      example:
        types:
          - name: LOG_LINE
            value: 6
            direction: agent → user
          - name: LOG_START
            value: 7
            direction: both
          - name: LOG_STOP
            value: 8
            direction: agent → user
          - name: LOG_ERROR
            value: 9
            direction: agent → user
    WsCloseCodes:
      type: object
      description: WebSocket close codes used by Controller exec/log sessions
      properties:
        codes:
          type: array
          items:
            type: object
            properties:
              code:
                type: integer
              reason:
                type: string
              when:
                type: string
      example:
        codes:
          - code: 1000
            reason: Normal closure
            when: Session ended cleanly
          - code: 1001
            reason: Server draining
            when: SIGTERM / k8s preStop (R85)
          - code: 1008
            reason: Policy violation
            when: RBAC deny
            exec/log quota (5 per MS): null
            invalid tail params: null
            pending timeout: null
            sessionId mismatch: null
          - code: 1013
            reason: Router unavailable for cross-replica session
            when: AMQP router down (R84)
    EventRecord:
      type: object
      properties:
        id:
          type: integer
        timestamp:
          type: integer
          format: int64
        eventType:
          type: string
        endpointType:
          type: string
        actorId:
          type: string
          nullable: true
        method:
          type: string
          nullable: true
        resourceType:
          type: string
          nullable: true
        resourceId:
          type: string
          nullable: true
        endpointPath:
          type: string
        ipAddress:
          type: string
          nullable: true
        status:
          type: string
        statusCode:
          type: integer
          nullable: true
        statusMessage:
          type: string
          nullable: true
        requestId:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - timestamp
        - eventType
        - endpointType
        - endpointPath
        - status
        - createdAt
        - updatedAt
    EventListResponse:
      type: object
      properties:
        events:
          type: array
          items:
            $ref: '#/components/schemas/EventRecord'
        total:
          type: integer
        limit:
          type: integer
        offset:
          type: integer
      required:
        - events
        - total
        - limit
        - offset
    EventDeleteRequest:
      type: object
      properties:
        days:
          type: integer
          minimum: 0
          maximum: 365
      required:
        - days
    EventDeleteResponse:
      type: object
      properties:
        deletedCount:
          type: integer
        deletedBefore:
          type: string
          format: date-time
          nullable: true
        deletedAt:
          type: string
          format: date-time
        deletedAll:
          type: boolean
      required:
        - deletedCount
        - deletedAt
        - deletedAll
    ApplicationCreateFromTemplateRequest:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
        isActivated:
          type: boolean
        template:
          type: object
          properties:
            name:
              type: string
            variables:
              type: array
              items:
                type: object
                properties:
                  key:
                    type: string
                  value:
                    type: string
    ApplicationCreateRequest:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
        isActivated:
          type: boolean
        microservices:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              config:
                type: string
              annotations:
                type: string
              catalogItemId:
                type: integer
              registryId:
                type: integer
              images:
                type: array
                items:
                  properties:
                    containerImage:
                      type: string
                    archId:
                      type: string
              iofogUuid:
                type: string
              hostNetworkMode:
                type: boolean
              isPrivileged:
                type: boolean
              logSize:
                type: number
              rebuild:
                type: boolean
              volumeMappings:
                type: array
                items:
                  $ref: '#/components/schemas/VolumeMapping'
              envs:
                type: array
                items:
                  type: object
                  properties:
                    key:
                      type: string
                    value:
                      type: string
              runAsUser:
                type: string
              platform:
                type: string
              runtime:
                type: string
              cdiDevices:
                type: array
                items:
                  type: string
              capAdd:
                type: array
                items:
                  type: string
              capDrop:
                type: array
                items:
                  type: string
              cmd:
                type: array
                items:
                  type: string
              ports:
                type: array
                items:
                  $ref: '#/components/schemas/PortMappingsRequest'
              natsConfig:
                $ref: '#/components/schemas/NatsConfigObject'
        natsConfig:
          $ref: '#/components/schemas/NatsConfigObject'
    ApplicationCreateResponse:
      type: object
      properties:
        id:
          type: number
        name:
          type: string
    ApplicationGetResponse:
      type: object
      properties:
        id:
          type: number
        name:
          type: string
        description:
          type: string
        isActivated:
          type: boolean
        natsConfig:
          $ref: '#/components/schemas/NatsConfigObject'
        microservices:
          type: array
          items:
            $ref: '#/components/schemas/GetMicroservicesResponse'
    ApplicationListResponse:
      type: object
      properties:
        applications:
          type: array
          items:
            $ref: '#/components/schemas/ApplicationGetResponse'
    ApplicationTemplateCreateRequest:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
        variables:
          type: array
          items:
            type: object
            properties:
              key:
                type: string
              description:
                type: string
              defaultValue:
                type: string
        application:
          type: object
          properties:
            microservices:
              type: array
              items:
                type: object
                properties:
                  name:
                    type: string
                  config:
                    type: string
                  annotations:
                    type: string
                  catalogItemId:
                    type: integer
                  registryId:
                    type: integer
                  images:
                    type: array
                    items:
                      properties:
                        containerImage:
                          type: string
                        archId:
                          type: string
                  iofogUuid:
                    type: string
                  agentName:
                    type: string
                  hostNetworkMode:
                    type: boolean
                  isPrivileged:
                    type: boolean
                  logSize:
                    type: number
                  rebuild:
                    type: boolean
                  volumeMappings:
                    type: array
                    items:
                      $ref: '#/components/schemas/VolumeMapping'
                  envs:
                    type: array
                    items:
                      type: object
                      properties:
                        key:
                          type: string
                        value:
                          type: string
                  runAsUser:
                    type: number
                  platform:
                    type: string
                  runtime:
                    type: string
                  cdiDevices:
                    type: array
                    items:
                      type: string
                  capAdd:
                    type: array
                    items:
                      type: string
                  capDrop:
                    type: array
                    items:
                      type: string
                  cmd:
                    type: array
                    items:
                      type: string
                  ports:
                    type: array
                    items:
                      $ref: '#/components/schemas/PortMappingsRequest'
                  natsConfig:
                    $ref: '#/components/schemas/NatsConfigObject'
            natsConfig:
              $ref: '#/components/schemas/NatsConfigObject'
    ApplicationTemplateCreateResponse:
      type: object
      properties:
        id:
          type: number
        name:
          type: string
    ApplicationTemplatePatchRequest:
      type: object
      properties:
        description:
          type: number
        name:
          type: string
    ApplicationTemplateGetResponse:
      type: object
      properties:
        id:
          type: number
        name:
          type: string
        description:
          type: string
        application:
          type: object
          properties:
            microservices:
              type: array
              items:
                $ref: '#/components/schemas/GetMicroservicesResponse'
            natsConfig:
              $ref: '#/components/schemas/NatsConfigObject'
    ApplicationTemplateListResponse:
      type: object
      properties:
        applicationTemplates:
          type: array
          items:
            $ref: '#/components/schemas/ApplicationTemplateGetResponse'
    ServiceStatusResponse:
      type: object
      properties:
        status:
          type: string
          example: ok
        timestamp:
          type: number
    ArchitecturesResponse:
      type: object
      properties:
        architectures:
          type: array
          items:
            $ref: '#/components/schemas/Architecture'
    Architecture:
      type: object
      properties:
        id:
          type: number
        name:
          type: string
        image:
          type: string
        description:
          type: string
    IOFogNodesListFilters:
      type: array
      items:
        type: object
        properties:
          key:
            type: string
          value:
            type: string
          condition:
            type: string
    IOFogNodesListResponse:
      type: object
      properties:
        fogs:
          type: array
          items:
            $ref: '#/components/schemas/IOFogNodeInfoResponse'
    IOFogNodeInfoResponse:
      type: object
      properties:
        lastActive:
          type: number
        daemonOperatingDuration:
          type: number
        daemonLastStart:
          type: number
        repositoryCount:
          type: number
        systemTime:
          type: number
        lastStatusTime:
          type: number
        lastCommandTime:
          type: number
        logFileCount:
          type: number
        uuid:
          type: string
        name:
          type: string
        location:
          type: string
        gpsMode:
          type: string
        latitude:
          type: number
        longitude:
          type: number
        description:
          type: string
        daemonStatus:
          type: string
        memoryUsage:
          type: number
        diskUsage:
          type: number
        cpuUsage:
          type: number
        memoryViolation:
          type: boolean
        diskViolation:
          type: boolean
        cpuViolation:
          type: boolean
        systemTotalCpu:
          type: number
        catalogItemStatus:
          type: string
        repositoryStatus:
          type: string
        ipAddress:
          type: string
        ipAddressExternal:
          type: string
        networkInterface:
          type: string
        containerEngineUrl:
          type: string
        containerEngine:
          type: string
          enum:
            - edgelet
            - docker
            - podman
        deploymentType:
          type: string
        diskLimit:
          type: number
        diskDirectory:
          type: string
        memoryLimit:
          type: number
        cpuLimit:
          type: number
        logLimit:
          type: number
        logDirectory:
          type: string
        bluetoothEnabled:
          type: boolean
        abstractedHardwareEnabled:
          type: boolean
        version:
          type: string
        isReadyToUpgrade:
          type: boolean
        isReadyToRollback:
          type: boolean
        statusFrequency:
          type: number
        changeFrequency:
          type: number
        deviceScanFrequency:
          type: number
        tunnel:
          type: string
        watchdogEnabled:
          type: boolean
        pruningFrequency:
          type: number
        availableDiskThreshold:
          type: number
        logLevel:
          type: string
        isSystem:
          type: boolean
        routerId:
          type: number
        createAt:
          type: number
        updatedAt:
          type: number
        archId:
          type: number
        arch:
          $ref: '#/components/schemas/Architecture'
        availableRuntimes:
          type: array
          items:
            type: string
        routerMode:
          type: string
          enum:
            - none
            - edge
            - interior
        messagingPort:
          type: number
        upstreamRouters:
          type: array
          items:
            type: string
        natsMode:
          type: string
          enum:
            - none
            - leaf
            - server
        natsServerPort:
          type: number
        natsLeafPort:
          type: number
        natsClusterPort:
          type: number
        natsMqttPort:
          type: number
        natsHttpPort:
          type: number
        jsStorageSize:
          type: string
          description: JetStream max file store (e.g. 10g). Units m, mb, g, gb, t, tb.
        jsMemoryStoreSize:
          type: string
          description: JetStream max memory store (e.g. 1g). Units m, mb, g, gb, t, tb.
        upstreamNatsServers:
          type: array
          items:
            type: string
        platformStatus:
          description: Present on GET single fog only; omitted on list responses
          allOf:
            - $ref: '#/components/schemas/PlatformStatus'
    PlatformStatus:
      type: object
      properties:
        phase:
          type: string
          enum:
            - Pending
            - Progressing
            - Ready
            - Failed
            - Deleting
        generation:
          type: integer
          description: Desired spec generation from FogPlatformSpecs
        observedGeneration:
          type: integer
          description: Generation last reconciled successfully
        lastError:
          type: string
          nullable: true
        lastTransitionAt:
          type: string
          format: date-time
        conditions:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
              status:
                type: string
              reason:
                type: string
              message:
                type: string
    UpdateIOFogNodeRequestBody:
      type: object
      properties:
        name:
          type: string
        location:
          type: string
        latitude:
          type: number
        longitude:
          type: number
        description:
          type: string
        containerEngineUrl:
          type: string
          default: unix:///run/edgelet/contaienrd.sock
        containerEngine:
          type: string
          enum:
            - edgelet
            - docker
            - podman
          default: docker
        deploymentType:
          type: string
          default: native
        diskLimit:
          type: number
          default: 50
        diskDirectory:
          type: string
          default: /var/lib/edgelet/
        memoryLimit:
          type: number
          default: 4096
          format: MB
        cpuLimit:
          type: number
          default: 80
          format: percent
        logLimit:
          type: number
          default: 10
          format: GB
        logDirectory:
          type: string
          default: /var/log/iofog
        logFileCount:
          type: number
          default: 10
        statusFrequency:
          type: number
          default: 10
          format: seconds
        changeFrequency:
          type: number
          default: 20
          format: seconds
        deviceScanFrequency:
          type: number
          default: 20
          format: seconds
        bluetoothEnabled:
          type: boolean
          default: false
        watchdogEnabled:
          type: boolean
          default: true
        abstractedHardwareEnabled:
          type: boolean
          default: false
        archId:
          type: number
          minimum: 0
          maximum: 4
        pruningFrequency:
          type: number
        availableDiskThreshold:
          type: number
        logLevel:
          type: string
          default: info
        isSystem:
          type: boolean
        routerMode:
          type: string
          default: edge
          enum:
            - none
            - edge
            - interior
        messagingPort:
          type: number
        interRouterPort:
          type: number
        edgeRouterPort:
          type: number
        natsMode:
          type: string
          enum:
            - none
            - leaf
            - server
        natsServerPort:
          type: number
        natsLeafPort:
          type: number
        natsClusterPort:
          type: number
        natsMqttPort:
          type: number
        natsHttpPort:
          type: number
        jsStorageSize:
          type: string
          description: JetStream max file store (e.g. 10g). Units m, mb, g, gb, t, tb.
        jsMemoryStoreSize:
          type: string
          description: JetStream max memory store (e.g. 1g). Units m, mb, g, gb, t, tb.
        upstreamNatsServers:
          type: array
          items:
            type: string
        host:
          type: string
        tags:
          type: array
          items:
            type: string
        upstreamRouters:
          type: array
          items:
            type: string
        networkRouter:
          type: string
    NewIOFogNodeResponse:
      type: object
      properties:
        id:
          type: string
    IOFogUuidResponse:
      type: object
      properties:
        uuid:
          type: string
          description: ioFog node id
    ProvisioningKeyResponse:
      type: object
      properties:
        key:
          type: string
        expirationTime:
          type: number
        caCert:
          type: string
          description: >-
            Base64-encoded PEM of the controller CA for Edgelet trust store;
            empty when a public CA is used
    AgentProvisioningRequest:
      type: object
      required:
        - type
        - key
      properties:
        type:
          type: number
          minimum: 0
          maximum: 4
          description: |
            Architecture code
             * '0': auto
             * '1': amd64
             * '2': arm64
             * '3': riscv64
             * '4': arm
        engine:
          type: string
          enum:
            - edgelet
            - docker
            - podman
          description: Container engine selected at provision time
        key:
          type: string
          description: provisioning key
    AgentProvisioningResponse:
      type: object
      properties:
        id:
          type: string
          description: ioFog Node Id
        token:
          type: string
          description: Agent token
    AgentDeprovisioningRequest:
      type: object
      properties:
        microserviceUuids:
          type: array
          items:
            type: string
    IOFogNodeConfigChanges:
      type: object
      properties:
        config:
          type: boolean
        version:
          type: boolean
        reboot:
          type: boolean
        deleteNode:
          type: boolean
        microservicesList:
          type: boolean
        microservicesConfig:
          type: boolean
        registries:
          type: boolean
        tunnel:
          type: boolean
        prune:
          type: boolean
        routerChanged:
          type: boolean
    IOFogNodeConfig:
      type: object
      properties:
        networkInterface:
          type: string
        containerEngineUrl:
          type: string
        containerEngine:
          type: string
          enum:
            - edgelet
            - docker
            - podman
        deploymentType:
          type: string
        diskLimit:
          type: number
        diskDirectory:
          type: string
        memoryLimit:
          type: number
        cpuLimit:
          type: number
        logLimit:
          type: number
        logDirectory:
          type: string
        logFileCount:
          type: number
        statusFrequency:
          type: number
        changeFrequency:
          type: number
        deviceScanFrequency:
          type: number
        watchdogEnabled:
          type: boolean
        latitude:
          type: number
        longitude:
          type: number
        logLevel:
          type: string
        availableDiskThreshold:
          type: number
        pruningFrequency:
          type: number
        routerHost:
          type: string
        routerPort:
          type: number
    IOFogNodeConfigRequest:
      type: object
      properties:
        networkInterface:
          type: string
        containerEngineUrl:
          type: string
        containerEngine:
          type: string
          enum:
            - edgelet
            - docker
            - podman
        deploymentType:
          type: string
        diskLimit:
          type: number
        diskDirectory:
          type: string
        memoryLimit:
          type: number
        cpuLimit:
          type: number
        logLimit:
          type: number
        logDirectory:
          type: string
        logFileCount:
          type: number
        statusFrequency:
          type: number
        changeFrequency:
          type: number
        deviceScanFrequency:
          type: number
        watchdogEnabled:
          type: boolean
        latitude:
          type: number
        longitude:
          type: number
        gpsMode:
          type: string
        logLevel:
          type: string
        availableDiskThreshold:
          type: number
        pruningFrequency:
          type: number
    IOFogNodeGpsRequest:
      type: object
      properties:
        latitude:
          type: number
        longitude:
          type: number
    AgentStatus:
      type: object
      properties:
        daemonStatus:
          type: string
        warningMessage:
          type: string
        daemonOperatingDuration:
          type: number
        daemonLastStart:
          type: number
        memoryUsage:
          type: number
        diskUsage:
          type: number
        cpuUsage:
          type: number
        memoryViolation:
          type: boolean
        diskViolation:
          type: boolean
        cpuViolation:
          type: boolean
        systemAvailableDisk:
          type: integer
        systemAvailableMemory:
          type: integer
        systemTotalCpu:
          type: number
        securityStatus:
          type: string
        securityViolationInfo:
          type: string
        microserviceStatus:
          type: string
        repositoryCount:
          type: number
        repositoryStatus:
          type: string
        systemTime:
          type: number
        lastStatusTime:
          type: number
        ipAddress:
          type: string
        ipAddressExternal:
          type: string
        lastCommandTime:
          type: number
        availableRuntimes:
          type: array
          items:
            type: string
        runtimeAgentPhase:
          type: string
        controlPlaneQuiesced:
          type: boolean
        tunnelStatus:
          type: string
        version:
          type: string
        isReadyToUpgrade:
          type: boolean
        isReadyToRollback:
          type: boolean
        activeVolumeMounts:
          type: number
        volumeMountLastUpdate:
          type: number
        gpsStatus:
          type: string
    IOFogNodeTunnelConfigResponse:
      type: object
      properties:
        username:
          type: string
        password:
          type: string
        host:
          type: string
        remotePort:
          type: number
        localPort:
          type: number
        rsaKey:
          type: string
        closed:
          type: boolean
    AgentMicroservicesListResponse:
      type: object
      properties:
        microservices:
          type: array
          items:
            $ref: '#/components/schemas/AgentMicroservicesInfoResponse'
    AgentMicroservicesInfoResponse:
      type: object
      properties:
        uuid:
          type: string
        imageId:
          type: string
        config:
          type: string
        annotations:
          type: string
        rebuild:
          type: boolean
        hostNetworkMode:
          type: boolean
        isPrivileged:
          type: boolean
        logSize:
          type: number
        registryId:
          type: number
        portMappings:
          type: array
          items:
            $ref: '#/components/schemas/PortMappingAgentRequest'
        volumeMappings:
          type: array
          items:
            $ref: '#/components/schemas/VolumeMapping'
        delete:
          type: boolean
        deleteWithCleanUp:
          type: boolean
        env:
          type: array
          items:
            $ref: '#/components/schemas/AgentEnvRequest'
        runAsUser:
          type: string
        platform:
          type: string
        runtime:
          type: string
        cdiDevices:
          type: array
          items:
            type: string
        capAdd:
          type: array
          items:
            type: string
        capDrop:
          type: array
          items:
            type: string
        cmd:
          type: array
          items:
            type: string
        idConsumer:
          type: boolean
        isRouter:
          type: boolean
          description: True when microservice is the system router
        isNats:
          type: boolean
          description: True when microservice is the system NATS broker
        isController:
          type: boolean
          description: >-
            True when microservice is the ControlPlane controller workload (DB
            column)
    ControllerRegisterRequest:
      type: object
      description: >-
        Edgelet ControlPlane controller workload register body. Accepts the same
        container/workload fields as user microservice deploy (excluding
        application, serviceAccount, and natsConfig). Ownership fields
        (iofogUuid, application) are derived from the authenticated system fog.
      required:
        - uuid
        - images
        - registryId
      properties:
        uuid:
          type: string
          description: Edgelet-generated stable uuid for the controller microservice
        name:
          type: string
          enum:
            - controller
          description: Must be controller (default controller if omitted)
        images:
          type: array
          minItems: 1
          maxItems: 4
          items:
            $ref: '#/components/schemas/MicroserviceContainerImage'
        registryId:
          type: integer
        config:
          type: string
        annotations:
          type: string
        hostNetworkMode:
          type: boolean
        isPrivileged:
          type: boolean
        logSize:
          type: integer
          minimum: 0
        runtime:
          type: string
        pidMode:
          type: string
        ipcMode:
          type: string
        runAsUser:
          type: string
        platform:
          type: string
        cpuSetCpus:
          type: string
        memoryLimit:
          type: integer
        ports:
          type: array
          items:
            $ref: '#/components/schemas/PortMappingsResponse'
        volumeMappings:
          type: array
          items:
            $ref: '#/components/schemas/VolumeMappingRequest'
        extraHosts:
          type: array
          items:
            type: object
            required:
              - name
              - address
            properties:
              name:
                type: string
              address:
                type: string
        env:
          type: array
          items:
            $ref: '#/components/schemas/AgentEnvRequest'
        cmd:
          type: array
          items:
            type: string
        cdiDevices:
          type: array
          items:
            type: string
        capAdd:
          type: array
          items:
            type: string
        capDrop:
          type: array
          items:
            type: string
        healthCheck:
          type: object
          required:
            - test
          properties:
            test:
              type: array
              items:
                type: string
            interval:
              type: integer
            timeout:
              type: integer
            startPeriod:
              type: integer
            startInterval:
              type: integer
            retries:
              type: integer
        schedule:
          type: integer
          enum:
            - 0
          description: Optional; controller workload schedule is always 0 (server-enforced)
    ControllerRegisterResponse:
      type: object
      properties:
        uuid:
          type: string
          description: Same uuid as the register request
    AgentEnvRequest:
      type: object
      properties:
        key:
          type: string
        value:
          type: string
    ReceiverMicroservices:
      type: array
      items:
        type: string
    VolumeMapping:
      type: object
      properties:
        hostDestination:
          type: string
          example: /var/dest
        containerDestination:
          type: string
          example: /var/dest
        accessMode:
          type: string
          example: rw
    VolumeMappingResponse:
      type: object
      properties:
        volumeMappings:
          type: array
          items:
            $ref: '#/components/schemas/VolumeMappingRequest'
    VolumeMappingRequest:
      type: object
      properties:
        id:
          type: number
        hostDestination:
          type: string
          example: /var/dest
        containerDestination:
          type: string
          example: /var/dest
        accessMode:
          type: string
          example: rw
        type:
          type: string
          example: bind
    PortMappingsResponse:
      type: object
      properties:
        internal:
          type: number
        external:
          type: number
        protocol:
          type: string
          enum:
            - tcp
            - udp
      required:
        - internal
        - external
        - protocol
    PortMappingsRequest:
      type: object
      properties:
        internal:
          type: number
        external:
          type: number
        protocol:
          type: string
          enum:
            - tcp
            - udp
      required:
        - internal
        - external
    PortMappingsPublicResponse:
      type: object
      properties:
        internal:
          type: number
        external:
          type: number
        protocol:
          type: string
          enum:
            - tcp
            - udp
      required:
        - internal
        - external
        - protocol
    PortMappingsListResponse:
      type: object
      properties:
        ports:
          type: array
          items:
            $ref: '#/components/schemas/PortMappingsItemResponse'
    PortMappingsItemResponse:
      type: object
      properties:
        internal:
          type: number
        external:
          type: number
        protocol:
          type: string
          enum:
            - tcp
            - udp
      required:
        - internal
        - external
        - protocol
    PortMappingAgentRequest:
      type: object
      properties:
        portInternal:
          type: string
          example: 80
        portExternal:
          type: string
          example: 80
    microservicesConfig:
      type: string
    RegistriesListResponse:
      type: object
      properties:
        registries:
          type: array
          items:
            $ref: '#/components/schemas/RegistryResponse'
    RegistryResponse:
      type: object
      properties:
        id:
          type: number
        url:
          type: string
        isPublic:
          type: boolean
        username:
          type: string
        password:
          type: string
        userEmail:
          type: string
    RegistryBody:
      type: object
      properties:
        url:
          type: string
        isPublic:
          type: boolean
        username:
          type: string
        password:
          type: string
        email:
          type: string
    ActionBody:
      type: object
      properties:
        action:
          type: string
          enum:
            - open
            - close
    MicroservicesCatalogResponse:
      type: object
      properties:
        catalogItems:
          type: array
          items:
            $ref: '#/components/schemas/CatalogItemInfoResponse'
    CatalogItemInfoResponse:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
        category:
          type: string
        publisher:
          type: string
        diskRequired:
          type: number
        ramRequired:
          type: number
        picture:
          type: string
        isPublic:
          type: boolean
        registryId:
          type: number
        inputType:
          $ref: '#/components/schemas/InfoTypeResponse'
        outputType:
          $ref: '#/components/schemas/InfoTypeResponse'
        configExample:
          type: string
        images:
          $ref: '#/components/schemas/MicroserviceContainerImages'
    InfoTypeResponse:
      type: object
      properties:
        infoType:
          type: string
        infoFormat:
          type: string
    MicroserviceContainerImages:
      type: array
      items:
        $ref: '#/components/schemas/MicroserviceContainerImage'
    MicroserviceContainerImage:
      type: object
      properties:
        containerImage:
          type: string
        archId:
          type: number
          enum:
            - 1
            - 2
            - 3
            - 4
    CreateUpdateCatalogItemRequestBody:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
        category:
          type: string
        images:
          $ref: '#/components/schemas/MicroserviceContainerImages'
        publisher:
          type: string
        diskRequired:
          type: number
        ramRequired:
          type: number
        picture:
          type: string
        isPublic:
          type: boolean
        registryId:
          type: number
        inputType:
          $ref: '#/components/schemas/InfoTypeResponse'
        outputType:
          $ref: '#/components/schemas/InfoTypeResponse'
        configExample:
          type: string
    GetMicroservicesResponse:
      type: object
      properties:
        microservices:
          type: array
          items:
            $ref: '#/components/schemas/MicroserviceInfoResponse'
    MicroserviceInfoResponse:
      type: object
      properties:
        uuid:
          type: string
        name:
          type: string
        config:
          type: string
        annotations:
          type: string
        hostNetworkMode:
          type: boolean
        isPrivileged:
          type: boolean
        logLimit:
          type: number
        images:
          type: array
          items:
            properties:
              containerImage:
                type: string
              archId:
                type: string
        iofogUuid:
          type: string
        envs:
          type: array
          items:
            type: object
            properties:
              key:
                type: string
              value:
                type: string
        runAsUser:
          type: string
        platform:
          type: string
        runtime:
          type: string
        cdiDevices:
          type: array
          items:
            type: string
        capAdd:
          type: array
          items:
            type: string
        capDrop:
          type: array
          items:
            type: string
        cmd:
          type: array
          items:
            type: string
        volumeMappings:
          type: array
          items:
            $ref: '#/components/schemas/VolumeMappingRequest'
        ports:
          type: array
          items:
            $ref: '#/components/schemas/PortMappingsResponse'
        natsAccess:
          type: boolean
        natsConfig:
          $ref: '#/components/schemas/NatsConfigObject'
        status:
          type: object
          properties:
            status:
              type: string
            operatingDuration:
              type: number
            startTime:
              type: number
            cpuUsage:
              type: number
            memoryUsage:
              type: number
            containerId:
              type: string
    NewMicroserviceRequest:
      type: object
      properties:
        name:
          type: string
        config:
          type: string
        annotations:
          type: string
        catalogItemId:
          type: integer
        images:
          type: array
          items:
            properties:
              containerImage:
                type: string
              archId:
                type: string
        application:
          type: string
        iofogUuid:
          type: string
        agentName:
          type: string
        hostNetworkMode:
          type: boolean
        isPrivileged:
          type: boolean
        logSize:
          type: number
        volumeMappings:
          type: array
          items:
            $ref: '#/components/schemas/VolumeMapping'
        ports:
          type: array
          items:
            $ref: '#/components/schemas/PortMappingsRequest'
        runAsUser:
          type: string
        platform:
          type: string
        runtime:
          type: string
        cdiDevices:
          type: array
          items:
            type: string
        capAdd:
          type: array
          items:
            type: string
        capDrop:
          type: array
          items:
            type: string
        cmd:
          type: array
          items:
            type: string
        natsConfig:
          $ref: '#/components/schemas/NatsConfigObject'
        serviceAccount:
          type: object
          properties:
            roleRef:
              $ref: '#/components/schemas/RoleRef'
          additionalProperties: false
    UpdateMicroserviceRequest:
      type: object
      properties:
        name:
          type: string
        config:
          type: string
        annotations:
          type: string
        rebuild:
          type: boolean
        iofogUuid:
          type: string
        agentName:
          type: string
        hostNetworkMode:
          type: boolean
        isPrivileged:
          type: boolean
        logLimit:
          type: number
        volumeMappings:
          type: array
          items:
            $ref: '#/components/schemas/VolumeMapping'
        images:
          type: array
          items:
            properties:
              containerImage:
                type: string
              archId:
                type: string
        runAsUser:
          type: string
        platform:
          type: string
        runtime:
          type: string
        cdiDevices:
          type: array
          items:
            type: string
        capAdd:
          type: array
          items:
            type: string
        capDrop:
          type: array
          items:
            type: string
        cmd:
          type: array
          items:
            type: string
        natsConfig:
          $ref: '#/components/schemas/NatsConfigObject'
        serviceAccount:
          type: object
          properties:
            roleRef:
              $ref: '#/components/schemas/RoleRef'
          additionalProperties: false
    NatsConfigObject:
      type: object
      properties:
        natsAccess:
          type: boolean
        natsRule:
          type: string
      additionalProperties: false
    NatsHubRequest:
      type: object
      required:
        - host
      properties:
        host:
          type: string
        serverPort:
          type: integer
        clusterPort:
          type: integer
        leafPort:
          type: integer
        mqttPort:
          type: integer
        httpPort:
          type: integer
        jsStorageSize:
          type: string
          description: JetStream max file store (e.g. 10g, 1t). Units m, mb, g, gb, t, tb.
        jsMemoryStoreSize:
          type: string
          description: JetStream max memory store (e.g. 1g). Units m, mb, g, gb, t, tb.
    NatsHubResponse:
      $ref: '#/components/schemas/NatsHubRequest'
    NatsOperatorResponse:
      type: object
      properties:
        name:
          type: string
        publicKey:
          type: string
        jwt:
          type: string
    NatsBootstrapResponse:
      type: object
      properties:
        operatorJwt:
          type: string
        operatorPublicKey:
          type: string
        operatorSeed:
          type: string
        systemAccountJwt:
          type: string
        systemAccountPublicKey:
          type: string
        sysUserCredsBase64:
          type: string
    NatsAccountResponse:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        publicKey:
          type: string
        jwt:
          type: string
        isSystem:
          type: boolean
        applicationId:
          type: integer
    NatsAccountsListResponse:
      type: object
      properties:
        accounts:
          type: array
          items:
            $ref: '#/components/schemas/NatsAccountResponse'
    NatsUserCreateRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
        expiresIn:
          type: string
          pattern: ^[0-9]+[hdm]$
          example: 7d
        natsRule:
          type: string
    NatsUserResponse:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        publicKey:
          type: string
        jwt:
          type: string
        isBearer:
          type: boolean
    NatsUserWithContextResponse:
      type: object
      description: NATS user with account and application context (for list-all response)
      properties:
        id:
          type: integer
        name:
          type: string
        publicKey:
          type: string
        jwt:
          type: string
        isBearer:
          type: boolean
        accountId:
          type: integer
        accountName:
          type: string
        applicationId:
          type: integer
        applicationName:
          type: string
        microserviceUuid:
          type: string
          format: uuid
    NatsUsersListResponse:
      type: object
      properties:
        users:
          type: array
          items:
            $ref: '#/components/schemas/NatsUserResponse'
    NatsAllUsersListResponse:
      type: object
      properties:
        users:
          type: array
          items:
            $ref: '#/components/schemas/NatsUserWithContextResponse'
    NatsAccountEnsureRequest:
      type: object
      properties:
        natsRule:
          type: string
          description: Account rule name (defaults to default-account if omitted)
    NatsCredsResponse:
      type: object
      properties:
        credsBase64:
          type: string
          description: NATS credentials file content encoded as base64
    NatsAccountRulePayload:
      type: object
      description: NATS account rule (authorization policy for an account)
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 255
        description:
          type: string
        infoUrl:
          type: string
        maxConnections:
          type: integer
          minimum: -1
        maxLeafNodeConnections:
          type: integer
          minimum: -1
        maxData:
          type: integer
          minimum: -1
        maxExports:
          type: integer
          minimum: -1
        maxImports:
          type: integer
          minimum: -1
        maxMsgPayload:
          type: integer
          minimum: -1
        maxSubscriptions:
          type: integer
          minimum: -1
        exportsAllowWildcards:
          type: boolean
        disallowBearer:
          type: boolean
        responsePermissions:
          type: object
          properties:
            maxMsgs:
              type: integer
              minimum: 0
            expires:
              type: integer
              minimum: 0
        respMax:
          type: integer
          minimum: 0
        respTtl:
          type: integer
          minimum: 0
        imports:
          type: array
          description: Stream/service imports (NATS account policy)
          items:
            type: object
            properties:
              name:
                type: string
              subject:
                type: string
              type:
                type: string
                enum:
                  - stream
                  - service
              account:
                type: string
              token:
                type: string
              to:
                type: string
              local_subject:
                type: string
              share:
                type: boolean
        exports:
          type: array
          description: Stream/service exports (NATS account policy)
          items:
            type: object
            properties:
              name:
                type: string
              subject:
                type: string
              type:
                type: string
                enum:
                  - stream
                  - service
              description:
                type: string
              info_url:
                type: string
              token_req:
                type: boolean
              response_type:
                type: string
                enum:
                  - Singleton
                  - Stream
                  - Chunked
              account_token_position:
                type: integer
        memStorage:
          type: integer
          minimum: -1
          description: JetStream memory storage limit in bytes
        diskStorage:
          type: integer
          minimum: -1
          description: JetStream disk storage limit in bytes
        streams:
          type: integer
          minimum: -1
          description: JetStream max streams
        consumer:
          type: integer
          minimum: -1
          description: JetStream max consumers
        maxAckPending:
          type: integer
          minimum: -1
        memMaxStreamBytes:
          type: integer
          minimum: -1
        diskMaxStreamBytes:
          type: integer
          minimum: -1
        maxBytesRequired:
          type: boolean
        tieredLimits:
          type: object
          additionalProperties: true
        pubAllow:
          type: array
          items:
            type: string
        pubDeny:
          type: array
          items:
            type: string
        subAllow:
          type: array
          items:
            type: string
        subDeny:
          type: array
          items:
            type: string
    NatsAccountRuleListResponse:
      type: object
      properties:
        rules:
          type: array
          items:
            $ref: '#/components/schemas/NatsAccountRulePayload'
    NatsUserRulePayload:
      type: object
      description: NATS user rule (authorization policy for a user)
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 255
        description:
          type: string
        maxSubscriptions:
          type: integer
          minimum: -1
        maxPayload:
          type: integer
          minimum: -1
        maxData:
          type: integer
          minimum: -1
        bearerToken:
          type: boolean
        proxyRequired:
          type: boolean
        allowedConnectionTypes:
          type: array
          items:
            type: string
            enum:
              - STANDARD
              - WEBSOCKET
              - LEAFNODE
              - LEAFNODE_WS
              - MQTT
              - MQTT_WS
              - IN_PROCESS
        src:
          type: array
          items:
            type: string
          description: Allowed client connection source IP/CIDR
        times:
          type: array
          items:
            type: object
            properties:
              start:
                type: string
              end:
                type: string
          description: Allowed time windows for connections
        timesLocation:
          type: string
        respMax:
          type: integer
          minimum: 0
        respTtl:
          type: integer
          minimum: 0
        pubAllow:
          type: array
          items:
            type: string
        pubDeny:
          type: array
          items:
            type: string
        subAllow:
          type: array
          items:
            type: string
        subDeny:
          type: array
          items:
            type: string
        tags:
          type: array
          items:
            type: string
    NatsUserRuleListResponse:
      type: object
      properties:
        rules:
          type: array
          items:
            $ref: '#/components/schemas/NatsUserRulePayload'
    IOFogNodeTunnelStatusInfoResponse:
      type: object
      properties:
        username:
          type: string
        host:
          type: string
        remotePort:
          type: number
        localPort:
          type: number
        status:
          type: string
    LoginRequest:
      type: object
      required:
        - email
        - password
      properties:
        email:
          type: string
          minLength: 1
          description: >-
            Login identifier (email for normal users; bootstrap admin may use a
            non-email username)
        password:
          type: string
        totp:
          type: string
          description: >-
            TOTP or recovery code when MFA is enabled (optional otherwise; CLI
            may send empty string)
    MfaEnrollResponse:
      type: object
      properties:
        secret:
          type: string
        otpauthUrl:
          type: string
    MfaConfirmRequest:
      type: object
      required:
        - code
      properties:
        code:
          type: string
    MfaDisableRequest:
      type: object
      required:
        - password
      properties:
        password:
          type: string
        code:
          type: string
    RefreshRequest:
      type: object
      required:
        - refreshToken
      properties:
        refreshToken:
          type: string
    LoginSuccessResponse:
      type: object
      required:
        - accessToken
        - refreshToken
      properties:
        accessToken:
          type: string
          description: >
            JWT access token (`token_use=access`). Includes
            `password_change_required: true` when the account must change its
            password before full API access.
        refreshToken:
          type: string
          description: >-
            JWT refresh token (`token_use=refresh`). Use only with POST
            /user/refresh.
    InteractionStepResponse:
      type: object
      required:
        - step
      properties:
        step:
          type: string
          enum:
            - login
            - mfa
            - enroll
            - confirm-enroll
            - change-password
            - complete
    InteractionLoginRequest:
      type: object
      required:
        - email
        - password
      properties:
        email:
          type: string
          description: Login identifier (not required to be an email address)
        password:
          type: string
    InteractionMfaRequest:
      type: object
      required:
        - code
      properties:
        code:
          type: string
    InteractionEnrollResponse:
      type: object
      required:
        - step
        - secret
        - otpauthUrl
      properties:
        step:
          type: string
        secret:
          type: string
        otpauthUrl:
          type: string
    InteractionConfirmEnrollResponse:
      type: object
      required:
        - step
        - recoveryCodes
      properties:
        step:
          type: string
        recoveryCodes:
          type: array
          items:
            type: string
    InteractionCompleteResponse:
      type: object
      required:
        - redirectTo
        - step
      properties:
        redirectTo:
          type: string
          description: OAuth resume URL; navigate browser here after all steps complete
        step:
          type: string
          enum:
            - complete
    RefreshSuccessResponse:
      type: object
      required:
        - accessToken
        - refreshToken
      properties:
        accessToken:
          type: string
        refreshToken:
          type: string
    UserProfileDetailsResponse:
      type: object
      description: >
        Embedded auth mode response. External auth mode returns the IdP UserInfo
        object instead

        (may include different fields; `mfaEnabled` is not supplied by
        Controller in external mode).
      properties:
        sub:
          type: string
        email:
          type: string
          description: >-
            Omitted when the login identifier has no `@` (e.g. bootstrap
            username).
        preferred_username:
          type: string
        groups:
          type: array
          items:
            type: string
        password_change_required:
          type: boolean
          description: Present when JWT claim `password_change_required` is true
        mfaEnabled:
          type: boolean
          description: >-
            Embedded auth only - whether the user has enrolled TOTP MFA (login
            requires TOTP when true, except bootstrap)
    ChangePasswordRequest:
      type: object
      required:
        - newPassword
      properties:
        currentPassword:
          type: string
        newPassword:
          type: string
        resetToken:
          type: string
    StatusResponse:
      type: object
      properties:
        status:
          type: string
    RateLimitExceededResponse:
      type: object
      required:
        - name
        - message
      properties:
        name:
          type: string
          example: RateLimitExceededError
        message:
          type: string
          example: Too many authentication requests from this IP address
    AuthUserCreateRequest:
      type: object
      required:
        - email
        - password
      properties:
        email:
          type: string
        password:
          type: string
        groups:
          type: array
          items:
            type: string
    AuthUserUpdateRequest:
      type: object
      properties:
        email:
          type: string
        groups:
          type: array
          items:
            type: string
    AuthUserResponse:
      type: object
      properties:
        id:
          type: string
        email:
          type: string
        groups:
          type: array
          items:
            type: string
        mustChangePassword:
          type: boolean
        mfaEnabled:
          type: boolean
        isBootstrap:
          type: boolean
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    AuthUserResetPasswordResponse:
      type: object
      properties:
        temporaryPassword:
          type: string
        mustChangePassword:
          type: boolean
    AuthUserResetTokenResponse:
      type: object
      properties:
        resetToken:
          type: string
        expiresIn:
          type: integer
    AuthGroupCreateRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
        mfaRequired:
          type: boolean
          default: false
          description: >-
            When true, members of this group must enroll and use TOTP MFA at
            login
    AuthGroupUpdateRequest:
      type: object
      description: At least one of `name` or `mfaRequired` is required
      properties:
        name:
          type: string
        mfaRequired:
          type: boolean
          description: >-
            When true, members of this group must enroll and use TOTP MFA at
            login
    AuthGroupResponse:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        isSystem:
          type: boolean
        mfaRequired:
          type: boolean
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    AuthMigrationExportResponse:
      type: object
      properties:
        exportedAt:
          type: string
          format: date-time
        authMode:
          type: string
          enum:
            - embedded
        users:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              email:
                type: string
              groups:
                type: array
                items:
                  type: string
        groups:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
              name:
                type: string
              isSystem:
                type: boolean
    AuthJwksRotateResponse:
      type: object
      properties:
        kid:
          type: string
        rotatedAt:
          type: string
          format: date-time
        restartRequired:
          type: boolean
    VersionCommandResponse:
      type: object
      required:
        - versionCommand
        - provisionKey
        - expirationTime
      properties:
        versionCommand:
          type: string
        provisionKey:
          type: string
        expirationTime:
          type: string
        semver:
          type: string
          description: Target semver for upgrade or rollback
          pattern: >-
            ^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:[+]([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
    HalInfo:
      type: object
      required:
        - info
      properties:
        info:
          type: string
    PostTrackingRequest:
      type: array
      items:
        $ref: '#/components/schemas/TrackingEvent'
    TrackingEvent:
      type: object
      required:
        - uuid
      properties:
        uuid:
          type: string
        sourceType:
          type: string
        timestamp:
          type: number
        type:
          type: string
        data:
          type: object
    SecretCreate:
      type: object
      required:
        - name
        - type
        - data
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 255
        type:
          type: string
          enum:
            - Opaque
            - tls
        data:
          type: object
    SecretUpdate:
      type: object
      required:
        - data
      properties:
        data:
          type: object
    SecretResponse:
      type: object
      required:
        - id
        - name
        - type
        - data
        - created_at
        - updated_at
      properties:
        id:
          type: integer
        name:
          type: string
        type:
          type: string
          enum:
            - Opaque
            - tls
        data:
          type: object
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    SecretListResponse:
      type: object
      required:
        - secrets
      properties:
        secrets:
          type: array
          items:
            type: object
            required:
              - id
              - name
              - type
              - created_at
              - updated_at
            properties:
              id:
                type: integer
              name:
                type: string
              type:
                type: string
                enum:
                  - Opaque
                  - tls
              created_at:
                type: string
                format: date-time
              updated_at:
                type: string
                format: date-time
    CACreateRequest:
      type: object
      required:
        - name
        - subject
        - type
      properties:
        name:
          type: string
          description: Name of the CA
        subject:
          type: string
          description: Subject of the CA (CN)
        expiration:
          type: integer
          description: Expiration time in milliseconds
        type:
          type: string
          enum:
            - k8s-secret
            - direct
            - self-signed
          description: Type of CA
        secretName:
          type: string
          description: Name of the secret (required for direct type)
    CAResponse:
      type: object
      properties:
        name:
          type: string
          description: Name of the CA
        subject:
          type: string
          description: Subject of the CA
        is_ca:
          type: boolean
          description: True if this is a CA
        valid_from:
          type: string
          format: date-time
          description: Validity start date
        valid_to:
          type: string
          format: date-time
          description: Validity end date
        serial_number:
          type: string
          description: Certificate serial number
        data:
          type: object
          properties:
            certificate:
              type: string
              description: PEM encoded certificate
            private_key:
              type: string
              description: PEM encoded private key
    CAListResponse:
      type: object
      properties:
        cas:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
                description: Name of the CA
              subject:
                type: string
                description: Subject of the CA
              valid_from:
                type: string
                format: date-time
                description: Validity start date
              valid_to:
                type: string
                format: date-time
                description: Validity end date
              days_remaining:
                type: integer
                description: Days until expiration
              is_expired:
                type: boolean
                description: True if certificate is expired
    CertificateCreateRequest:
      type: object
      required:
        - name
        - subject
        - hosts
      properties:
        name:
          type: string
          description: Name of the certificate
        subject:
          type: string
          description: Subject of the certificate (CN)
        hosts:
          type: string
          description: Comma-separated list of hosts
        expiration:
          type: integer
          description: Expiration time in milliseconds
        ca:
          type: object
          properties:
            type:
              type: string
              enum:
                - k8s-secret
                - direct
                - self-signed
              description: Type of CA
            secretName:
              type: string
              description: Name of the CA secret
            cert:
              type: string
              description: PEM encoded certificate (for direct type)
            key:
              type: string
              description: PEM encoded private key (for direct type)
    CertificateResponse:
      type: object
      properties:
        name:
          type: string
          description: Name of the certificate
        subject:
          type: string
          description: Subject of the certificate
        hosts:
          type: string
          description: Comma-separated list of hosts
        is_ca:
          type: boolean
          description: True if this is a CA
        valid_from:
          type: string
          format: date-time
          description: Validity start date
        valid_to:
          type: string
          format: date-time
          description: Validity end date
        serial_number:
          type: string
          description: Certificate serial number
        ca_name:
          type: string
          description: Name of the signing CA
        certificate_chain:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              subject:
                type: string
        days_remaining:
          type: integer
          description: Days until expiration
        is_expired:
          type: boolean
          description: True if certificate is expired
        data:
          type: object
          properties:
            certificate:
              type: string
              description: PEM encoded certificate
            private_key:
              type: string
              description: PEM encoded private key
    CertificateListResponse:
      type: object
      properties:
        certificates:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
                description: Name of the certificate
              subject:
                type: string
                description: Subject of the certificate
              hosts:
                type: string
                description: Comma-separated list of hosts
              is_ca:
                type: boolean
                description: True if this is a CA
              valid_from:
                type: string
                format: date-time
                description: Validity start date
              valid_to:
                type: string
                format: date-time
                description: Validity end date
              days_remaining:
                type: integer
                description: Days until expiration
              is_expired:
                type: boolean
                description: True if certificate is expired
              ca_name:
                type: string
                description: Name of the signing CA
    CertificateRenewResponse:
      type: object
      properties:
        name:
          type: string
          description: Name of the certificate
        subject:
          type: string
          description: Subject of the certificate
        hosts:
          type: string
          description: Comma-separated list of hosts
        valid_from:
          type: string
          format: date-time
          description: New validity start date
        valid_to:
          type: string
          format: date-time
          description: New validity end date
        renewed:
          type: boolean
          description: True if certificate was successfully renewed
    Service:
      type: object
      properties:
        name:
          type: string
        type:
          type: string
        resource:
          type: string
        defaultBridge:
          type: string
        bridgePort:
          type: number
        targetPort:
          type: number
        servicePort:
          type: number
        k8sType:
          type: string
          description: >-
            K8s Service type when running on a Kubernetes control plane (e.g.
            LoadBalancer)
        serviceEndpoint:
          type: string
          description: Hub-facing endpoint hostname or LoadBalancer IP after reconcile
        provisioningStatus:
          type: string
          enum:
            - pending
            - ready
            - failed
          description: >-
            Hub provisioning lifecycle. `pending` after create/update/delete
            enqueue or manual retry; `ready` after hub connector/listener and
            K8s Service reconcile succeed; `failed` after max worker attempts
            (use POST reconcile to retry). Edge fog bridge updates are tracked
            separately via fog platform reconcile.
        provisioningError:
          type: string
          nullable: true
          description: Last hub reconcile error when `provisioningStatus` is `failed`
        tags:
          type: array
          items:
            type: string
    ConfigMapCreate:
      type: object
      required:
        - name
        - data
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 255
        data:
          type: object
    ConfigMapUpdate:
      type: object
      required:
        - data
      properties:
        data:
          type: object
    ConfigMapResponse:
      type: object
      required:
        - id
        - name
        - data
        - created_at
        - updated_at
      properties:
        id:
          type: integer
        name:
          type: string
        data:
          type: object
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    ConfigMapListResponse:
      type: object
      required:
        - configMaps
      properties:
        configMaps:
          type: array
          items:
            type: object
            required:
              - id
              - name
              - created_at
              - updated_at
            properties:
              id:
                type: integer
              name:
                type: string
              created_at:
                type: string
                format: date-time
              updated_at:
                type: string
                format: date-time
    VolumeMount:
      type: object
      properties:
        uuid:
          type: string
        name:
          type: string
        secretName:
          type: string
        configMapName:
          type: string
        version:
          type: integer
      required:
        - uuid
        - name
        - version
    VolumeMountCreate:
      type: object
      properties:
        name:
          type: string
        secretName:
          type: string
        configMapName:
          type: string
      required:
        - name
      oneOf:
        - required:
            - secretName
        - required:
            - configMapName
    VolumeMountUpdate:
      type: object
      properties:
        name:
          type: string
        secretName:
          type: string
        configMapName:
          type: string
      oneOf:
        - required:
            - secretName
        - required:
            - configMapName
    VolumeMountLink:
      type: object
      properties:
        fogUuids:
          type: array
          items:
            type: string
          minItems: 1
      required:
        - fogUuids
    VolumeMountUnlink:
      type: object
      properties:
        fogUuids:
          type: array
          items:
            type: string
          minItems: 1
      required:
        - fogUuids
    RbacRule:
      type: object
      properties:
        apiGroups:
          type: array
          items:
            type: string
        resources:
          type: array
          items:
            type: string
        verbs:
          type: array
          items:
            type: string
        resourceNames:
          type: array
          items:
            type: string
          nullable: true
      required:
        - apiGroups
        - resources
        - verbs
    RoleRef:
      type: object
      required:
        - kind
        - name
      properties:
        kind:
          type: string
        name:
          type: string
        apiGroup:
          type: string
    Subject:
      type: object
      required:
        - kind
        - name
      properties:
        kind:
          type: string
        name:
          type: string
        apiGroup:
          type: string
    Role:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        apiVersion:
          type: string
        kind:
          type: string
        rules:
          type: array
          items:
            $ref: '#/components/schemas/RbacRule'
      required:
        - name
        - apiVersion
        - kind
        - rules
    RoleCreateRequest:
      type: object
      properties:
        name:
          type: string
        apiVersion:
          type: string
        kind:
          type: string
        rules:
          type: array
          items:
            $ref: '#/components/schemas/RbacRule'
      required:
        - name
        - rules
    RoleResponse:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        apiVersion:
          type: string
        kind:
          type: string
        rules:
          type: array
          items:
            $ref: '#/components/schemas/RbacRule'
      required:
        - name
        - apiVersion
        - kind
        - rules
    RoleListResponse:
      type: array
      items:
        $ref: '#/components/schemas/RoleResponse'
    RoleBinding:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        apiVersion:
          type: string
        kind:
          type: string
        roleRef:
          $ref: '#/components/schemas/RoleRef'
        subjects:
          type: array
          items:
            $ref: '#/components/schemas/Subject'
      required:
        - name
        - apiVersion
        - kind
        - roleRef
        - subjects
    RoleBindingCreateRequest:
      type: object
      properties:
        name:
          type: string
        apiVersion:
          type: string
        kind:
          type: string
        roleRef:
          $ref: '#/components/schemas/RoleRef'
        subjects:
          type: array
          items:
            $ref: '#/components/schemas/Subject'
      required:
        - name
        - roleRef
        - subjects
    RoleBindingResponse:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        apiVersion:
          type: string
        kind:
          type: string
        roleRef:
          $ref: '#/components/schemas/RoleRef'
        subjects:
          type: array
          items:
            $ref: '#/components/schemas/Subject'
      required:
        - name
        - apiVersion
        - kind
        - roleRef
        - subjects
    RoleBindingListResponse:
      type: array
      items:
        $ref: '#/components/schemas/RoleBindingResponse'
    ServiceAccount:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        applicationName:
          type: string
          description: Application name this service account belongs to
        roleRef:
          $ref: '#/components/schemas/RoleRef'
      required:
        - name
        - roleRef
    ServiceAccountCreateRequest:
      type: object
      properties:
        name:
          type: string
        applicationName:
          type: string
          description: Application name this service account belongs to
        roleRef:
          $ref: '#/components/schemas/RoleRef'
      required:
        - name
        - applicationName
        - roleRef
    ServiceAccountResponse:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        applicationName:
          type: string
          description: Application name this service account belongs to
        roleRef:
          $ref: '#/components/schemas/RoleRef'
      required:
        - name
        - roleRef
    ServiceAccountListResponse:
      type: array
      items:
        $ref: '#/components/schemas/ServiceAccountResponse'
    ClusterControllerResponse:
      type: object
      properties:
        uuid:
          type: string
        host:
          type: string
          nullable: true
        processId:
          type: integer
          nullable: true
        lastHeartbeat:
          type: string
          format: date-time
          nullable: true
        isActive:
          type: boolean
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - uuid
        - isActive
    ClusterControllerListResponse:
      type: array
      items:
        $ref: '#/components/schemas/ClusterControllerResponse'
    ClusterControllerUpdateRequest:
      type: object
      properties:
        host:
          type: string
      additionalProperties: false
    DefaultRouterResponse:
      type: object
      properties:
        host:
          type: string
        messagingPort:
          type: integer
        edgeRouterPort:
          type: integer
          nullable: true
        interRouterPort:
          type: integer
          nullable: true
      required:
        - host
        - messagingPort
    DefaultRouterUpsertRequest:
      type: object
      required:
        - host
      properties:
        host:
          type: string
        messagingPort:
          type: integer
          minimum: 1
          maximum: 65535
          description: Defaults to 5671 when omitted
        edgeRouterPort:
          type: integer
          minimum: 1
          maximum: 65535
          description: Defaults to 45671 when omitted
        interRouterPort:
          type: integer
          minimum: 1
          maximum: 65535
          description: Defaults to 55671 when omitted
      additionalProperties: true
    DefaultRouterRecordResponse:
      type: object
      properties:
        id:
          type: integer
        isEdge:
          type: boolean
        messagingPort:
          type: integer
        edgeRouterPort:
          type: integer
          nullable: true
        interRouterPort:
          type: integer
          nullable: true
        host:
          type: string
        isDefault:
          type: boolean
        iofogUuid:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - isEdge
        - messagingPort
        - host
        - isDefault
    NetworkTopologyDeploymentTarget:
      type: string
      enum:
        - kubernetes
        - remote
        - edgelet
    NetworkTopologyConnection:
      type: object
      properties:
        id:
          type: integer
        source:
          type: string
        dest:
          type: string
      required:
        - id
        - source
        - dest
    NetworkTopologyNodeBase:
      type: object
      properties:
        id:
          type: string
        iofogUuid:
          type: string
          nullable: true
        fogName:
          type: string
          nullable: true
        host:
          type: string
          nullable: true
        deploymentTarget:
          $ref: '#/components/schemas/NetworkTopologyDeploymentTarget'
        displayName:
          type: string
        role:
          type: string
        mode:
          type: string
      required:
        - id
        - deploymentTarget
        - displayName
        - role
        - mode
    RouterTopologyNode:
      allOf:
        - $ref: '#/components/schemas/NetworkTopologyNodeBase'
    NatsTopologyNode:
      allOf:
        - $ref: '#/components/schemas/NetworkTopologyNodeBase'
    RouterTopologyNodeDetail:
      allOf:
        - $ref: '#/components/schemas/RouterTopologyNode'
        - type: object
          properties:
            messagingPort:
              type: integer
            edgeRouterPort:
              type: integer
              nullable: true
            interRouterPort:
              type: integer
              nullable: true
            isDefault:
              type: boolean
    NatsTopologyNodeDetail:
      allOf:
        - $ref: '#/components/schemas/NatsTopologyNode'
        - type: object
          properties:
            serverPort:
              type: integer
              nullable: true
            leafPort:
              type: integer
              nullable: true
            clusterPort:
              type: integer
              nullable: true
            mqttPort:
              type: integer
              nullable: true
            httpPort:
              type: integer
              nullable: true
            jsStorageSize:
              type: string
              nullable: true
            jsMemoryStoreSize:
              type: string
              nullable: true
            isHub:
              type: boolean
    NetworkTopologySummaryResponse:
      type: object
      properties:
        controlPlane:
          type: string
          enum:
            - kubernetes
            - remote
        router:
          type: object
          properties:
            totalNodes:
              type: integer
            totalConnections:
              type: integer
            byRole:
              type: object
              additionalProperties:
                type: integer
        nats:
          type: object
          properties:
            totalNodes:
              type: integer
            totalConnections:
              type: integer
            byRole:
              type: object
              additionalProperties:
                type: integer
    TopologySpokeGroup:
      type: object
      properties:
        upstreamOf:
          type: string
        role:
          type: string
        count:
          type: integer
      required:
        - upstreamOf
        - role
        - count
    RouterTopologyOverviewResponse:
      type: object
      properties:
        defaultNode:
          $ref: '#/components/schemas/RouterTopologyNode'
          nullable: true
        interiorNodes:
          type: array
          items:
            $ref: '#/components/schemas/RouterTopologyNode'
        spokeGroups:
          type: array
          items:
            $ref: '#/components/schemas/TopologySpokeGroup'
    NatsTopologyOverviewResponse:
      type: object
      properties:
        defaultNode:
          $ref: '#/components/schemas/NatsTopologyNode'
          nullable: true
        serverNodes:
          type: array
          items:
            $ref: '#/components/schemas/NatsTopologyNode'
        spokeGroups:
          type: array
          items:
            $ref: '#/components/schemas/TopologySpokeGroup'
    PaginatedListMeta:
      type: object
      properties:
        total:
          type: integer
        limit:
          type: integer
        offset:
          type: integer
      required:
        - total
        - limit
        - offset
    RouterTopologyNodeListResponse:
      allOf:
        - $ref: '#/components/schemas/PaginatedListMeta'
        - type: object
          properties:
            nodes:
              type: array
              items:
                $ref: '#/components/schemas/RouterTopologyNode'
    NatsTopologyNodeListResponse:
      allOf:
        - $ref: '#/components/schemas/PaginatedListMeta'
        - type: object
          properties:
            nodes:
              type: array
              items:
                $ref: '#/components/schemas/NatsTopologyNode'
    RouterTopologyConnectionListResponse:
      allOf:
        - $ref: '#/components/schemas/PaginatedListMeta'
        - type: object
          properties:
            connections:
              type: array
              items:
                $ref: '#/components/schemas/NetworkTopologyConnection'
    NatsTopologyConnectionListResponse:
      allOf:
        - $ref: '#/components/schemas/PaginatedListMeta'
        - type: object
          properties:
            connections:
              type: array
              items:
                $ref: '#/components/schemas/NetworkTopologyConnection'
    TopologyNodeConnectionsResponse:
      type: object
      properties:
        upstream:
          type: array
          items:
            $ref: '#/components/schemas/NetworkTopologyConnection'
        downstream:
          type: array
          items:
            $ref: '#/components/schemas/NetworkTopologyConnection'
    TopologySubgraphResponse:
      type: object
      properties:
        nodes:
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/RouterTopologyNode'
              - $ref: '#/components/schemas/NatsTopologyNode'
        connections:
          type: array
          items:
            $ref: '#/components/schemas/NetworkTopologyConnection'
