openapi: 3.1.0
info:
  title: TenantPilot Provider Identity Standardization Contract
  version: 0.1.0
  summary: Internal contract for platform-default Microsoft provider connection flows.
  description: Logical internal action contract for existing authorized provider-connection surfaces. Operations may be implemented by existing Filament or Livewire action handlers and controller endpoints without introducing new standalone public routes, provided the documented authorization, confirmation, audit, and payload semantics are preserved.
servers:
  - url: /admin
paths:
  /tenants/{tenant}/provider-connections:
    post:
      summary: Create a provider connection for a tenant
      description: Creates a platform connection by default. Dedicated mode requires explicit opt-in and stronger authorization.
      parameters:
        - in: path
          name: tenant
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProviderConnectionCreateRequest'
      responses:
        '201':
          description: Provider connection created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProviderConnectionResponse'
        '403':
          description: Member lacks the required capability
        '404':
          description: Workspace or tenant scope not accessible
  /provider-connections/{connection}/admin-consent-link:
    post:
      summary: Generate canonical admin consent link
      parameters:
        - in: path
          name: connection
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Consent link generated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminConsentLinkResponse'
        '403':
          description: Member lacks the required capability
        '404':
          description: Connection not accessible in tenant scope
  /consent/callback:
    get:
      summary: Handle Microsoft admin consent callback
      parameters:
        - in: query
          name: state
          required: false
          schema:
            type: string
        - in: query
          name: tenant
          required: false
          schema:
            type: string
        - in: query
          name: admin_consent
          required: false
          schema:
            type: boolean
        - in: query
          name: error
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Consent callback rendered and connection updated
        '403':
          description: Invalid callback state
        '404':
          description: Tenant or workspace context unavailable
  /provider-connections/{connection}/verification:
    post:
      summary: Start provider connection verification
      parameters:
        - in: path
          name: connection
          required: true
          schema:
            type: integer
      responses:
        '202':
          description: Verification run queued or deduped
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationStartResponse'
        '403':
          description: Member lacks the provider run capability
        '404':
          description: Tenant scope not accessible
  /provider-connections/{connection}/connection-type:
    put:
      summary: Change the connection type explicitly
      description: Switching to or from dedicated requires stronger authorization and confirmation.
      parameters:
        - in: path
          name: connection
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - connection_type
              properties:
                connection_type:
                  type: string
                  enum: [platform, dedicated]
      responses:
        '200':
          description: Connection type changed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProviderConnectionResponse'
        '403':
          description: Member lacks dedicated-management capability
        '404':
          description: Connection not accessible in tenant scope
  /provider-connections/{connection}/dedicated-credential:
    put:
      summary: Create or rotate dedicated credential
      parameters:
        - in: path
          name: connection
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DedicatedCredentialRequest'
      responses:
        '200':
          description: Dedicated credential stored or rotated
        '403':
          description: Member lacks dedicated-management capability
        '404':
          description: Connection not accessible in tenant scope
    delete:
      summary: Delete dedicated credential
      description: Destructive operation that requires stronger authorization and confirmation.
      parameters:
        - in: path
          name: connection
          required: true
          schema:
            type: integer
      responses:
        '204':
          description: Dedicated credential deleted
        '403':
          description: Member lacks dedicated-management capability
        '404':
          description: Connection not accessible in tenant scope
components:
  schemas:
    ProviderConnectionCreateRequest:
      type: object
      required:
        - provider
        - entra_tenant_id
        - display_name
      properties:
        provider:
          type: string
          enum: [microsoft]
        entra_tenant_id:
          type: string
        display_name:
          type: string
        is_default:
          type: boolean
          default: true
        connection_type:
          type: string
          enum: [platform, dedicated]
          default: platform
        dedicated_credential:
          $ref: '#/components/schemas/DedicatedCredentialRequest'
          nullable: true
    DedicatedCredentialRequest:
      type: object
      required:
        - credential_kind
        - client_id
        - client_secret
      properties:
        credential_kind:
          type: string
          enum: [client_secret]
        source:
          type: string
          enum: [dedicated_manual, dedicated_imported, legacy_migrated]
        client_id:
          type: string
        client_secret:
          type: string
          writeOnly: true
    ProviderConnectionResponse:
      type: object
      required:
        - id
        - provider
        - entra_tenant_id
        - display_name
        - connection_type
        - consent_status
        - verification_status
        - health_status
      properties:
        id:
          type: integer
        provider:
          type: string
        entra_tenant_id:
          type: string
        display_name:
          type: string
        connection_type:
          type: string
          enum: [platform, dedicated]
        consent_status:
          type: string
          enum: [unknown, required, granted, failed, revoked]
        verification_status:
          type: string
          enum: [unknown, pending, healthy, degraded, blocked, error]
        health_status:
          type: string
        effective_app_id:
          type: string
        credential_source:
          type: string
        migration_review_required:
          type: boolean
          default: false
    AdminConsentLinkResponse:
      type: object
      required:
        - url
        - client_id
        - connection_type
      properties:
        url:
          type: string
          format: uri
        client_id:
          type: string
        connection_type:
          type: string
          enum: [platform, dedicated]
    VerificationStartResponse:
      type: object
      required:
        - status
        - operation_run_id
      properties:
        status:
          type: string
          enum: [started, deduped, scope_busy, blocked]
        operation_run_id:
          type: integer