"/admin/oauth/lookup_client":
    get:
        tags: [OAuth]
        operationId: oauthLookupClient
        summary: Look up an OAuth client by public client_id
        description: |
            Returns a client by its public `client_id`. Used by arda's `/oauth/authorize`
            consent UI to render the application name, logo, and requested scopes before
            the user approves access.
        responses:
            "200":
                description: Public client info.
                content:
                    application/json:
                        schema: { $ref: "../components/schemas/OAuthClient.yaml" }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
            "404":
                description: No client with the supplied `client_id`.
                content:
                    application/json:
                        schema: { $ref: "../admin-api.yaml#/components/schemas/Error" }
        x-access-policies: [BigscreenDefault]

"/admin/oauth/my_grant":
    get:
        tags: [OAuth]
        operationId: oauthGetMyGrant
        summary: Get the caller's existing grant for a client
        description: Returns the grant (set of approved scopes) the calling user has previously given to a specified client. Empty when none exists.
        responses:
            "200":
                description: Grant record (or empty).
                content:
                    application/json:
                        schema: { $ref: "../components/schemas/OAuthGrant.yaml" }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [BigscreenDefault]
    post:
        tags: [OAuth]
        operationId: oauthUpsertMyGrant
        summary: Create or update the caller's grant
        description: Records the scopes the caller has just approved during the consent flow. Idempotent.
        requestBody:
            required: true
            content:
                application/json:
                    schema:
                        type: object
                        required: [clientId, scopes]
                        properties:
                            clientId: { type: string, description: OAuth client the user is approving. }
                            scopes:
                                type: array
                                items: { type: string }
                                description: Scopes the user agreed to.
        responses:
            "200":
                description: Grant stored.
                content:
                    application/json:
                        schema: { $ref: "../components/schemas/OAuthGrant.yaml" }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [BigscreenDefault]

"/admin/oauth/codes":
    post:
        tags: [OAuth]
        operationId: oauthMintCode
        summary: Mint an authorization code (arda only)
        description: |
            Mints an OAuth authorization code that arda redirects the caller back to the
            requesting client with. Only arda is expected to call this endpoint, after the
            user has consented.
        requestBody:
            required: true
            content:
                application/json:
                    schema:
                        type: object
                        required: [clientId, redirectUri, scopes]
                        properties:
                            clientId: { type: string }
                            redirectUri: { type: string, format: uri }
                            scopes:
                                type: array
                                items: { type: string }
                            state:
                                type: string
                                description: Opaque value the client passed in /authorize, replayed on the callback.
                            codeChallenge:
                                type: string
                                description: PKCE code challenge.
                            codeChallengeMethod:
                                type: string
                                enum: [S256, plain]
        responses:
            "200":
                description: Authorization code.
                content:
                    application/json:
                        schema:
                            type: object
                            required: [code]
                            properties:
                                code:
                                    type: string
                                    description: Short-lived code the client redeems at the OAuth `/token` endpoint.
                                expiresIn:
                                    type: integer
                                    description: Seconds until the code expires.
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [BigscreenDefault]

"/admin/oauth/audit_event":
    post:
        tags: [OAuth]
        operationId: oauthWriteAuditEvent
        summary: Write a consent-flow audit event (arda only)
        description: Appends an event to the OAuth audit log from arda during the consent flow (page views, denies, etc.).
        requestBody:
            required: true
            content:
                application/json:
                    schema:
                        type: object
                        required: [eventType]
                        properties:
                            eventType:
                                type: string
                                description: "Audit event class — e.g. `consent_viewed`, `consent_approved`, `consent_denied`."
                            clientId: { type: string }
                            details:
                                type: object
                                additionalProperties: true
        responses:
            "200":
                description: Event recorded.
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [BigscreenDefault]

"/admin/oauth/clients/scopes":
    get:
        tags: [OAuth]
        operationId: oauthGetScopes
        summary: List available scopes
        description: Returns the catalog of OAuth scopes that clients can request.
        responses:
            "200":
                description: Array of scope definitions.
                content:
                    application/json:
                        schema:
                            type: array
                            items:
                                type: object
                                required: [name]
                                properties:
                                    name:
                                        type: string
                                        description: "Scope identifier (e.g. `openid`, `profile`, `admin:all`)."
                                    description: { type: string }
                                    requiresAdminApproval: { type: boolean }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]

"/admin/oauth/clients":
    get:
        tags: [OAuth]
        operationId: oauthListClients
        summary: List OAuth clients visible to the caller
        description: |
            Returns OAuth clients the caller can see. SuperUser sees every client; other
            staff see all clients but with read-write only on those they own.
        responses:
            "200":
                description: Array of client records.
                content:
                    application/json:
                        schema:
                            type: array
                            items: { $ref: "../components/schemas/OAuthClient.yaml" }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]
    post:
        tags: [OAuth]
        operationId: oauthCreateClient
        summary: Create an OAuth client
        description: Creates a new OAuth client. The caller becomes the owner.
        requestBody:
            required: true
            content:
                application/json:
                    schema:
                        type: object
                        required: [name, redirectUris, allowedScopes, serverIps]
                        properties:
                            name: { type: string }
                            description: { type: string }
                            logoUrl: { type: string, format: uri }
                            homepageUrl: { type: string, format: uri }
                            redirectUris:
                                type: array
                                items: { type: string, format: uri }
                            allowedScopes:
                                type: array
                                items: { type: string }
                            serverIps:
                                type: array
                                items: { type: string }
                                description: IP allowlist (required — clients must call from one of these IPs).
                            clientType:
                                type: string
                                enum: [confidential]
                                description: Only `confidential` is supported in v1.
        responses:
            "200":
                description: Created client (with the secret returned exactly once as `plaintextSecret`).
                content:
                    application/json:
                        schema:
                            allOf:
                                - $ref: "../components/schemas/OAuthClient.yaml"
                                - type: object
                                  required: [plaintextSecret]
                                  properties:
                                      plaintextSecret:
                                          type: string
                                          description: Returned ONCE — capture it now.
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]

"/admin/oauth/clients/{uniqueId}":
    parameters:
        - in: path
          name: uniqueId
          required: true
          schema: { type: string }
    get:
        tags: [OAuth]
        operationId: oauthGetClient
        summary: Fetch one OAuth client
        description: Returns a single OAuth client by its `uniqueId`.
        responses:
            "200":
                description: Client record.
                content:
                    application/json:
                        schema: { $ref: "../components/schemas/OAuthClient.yaml" }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
            "404":
                description: No client with this id.
                content:
                    application/json:
                        schema: { $ref: "../admin-api.yaml#/components/schemas/Error" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]
    put:
        tags: [OAuth]
        operationId: oauthUpdateClient
        summary: Update an OAuth client
        description: |
            Updates an OAuth client. Requires ownership-or-SuperUser **and** a recent
            step-up unlock (see `POST /step-up/challenge` and `/step-up/verify`).
        requestBody:
            required: true
            content:
                application/json:
                    schema:
                        type: object
                        properties:
                            name: { type: string }
                            description: { type: string }
                            logoUrl: { type: string, format: uri }
                            homepageUrl: { type: string, format: uri }
                            redirectUris:
                                type: array
                                items: { type: string, format: uri }
                            allowedScopes:
                                type: array
                                items: { type: string }
                            serverIps:
                                type: array
                                items: { type: string }
        responses:
            "200":
                description: Updated client.
                content:
                    application/json:
                        schema: { $ref: "../components/schemas/OAuthClient.yaml" }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]
    delete:
        tags: [OAuth]
        operationId: oauthDeleteClient
        summary: Soft-delete an OAuth client
        description: |
            Soft-deletes an OAuth client (sets a deletion flag; row remains). Requires
            ownership-or-SuperUser + step-up unlock.
        responses:
            "200":
                description: Client soft-deleted.
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]

"/admin/oauth/clients/{uniqueId}/rotate_secret":
    parameters:
        - in: path
          name: uniqueId
          required: true
          schema: { type: string }
    post:
        tags: [OAuth]
        operationId: oauthRotateSecret
        summary: Rotate the client secret
        description: |
            Rotates the client secret. The new secret is returned once in the response —
            callers must capture it. Requires ownership + step-up unlock.
        responses:
            "200":
                description: Rotation complete; new secret returned exactly once as `plaintextSecret`.
                content:
                    application/json:
                        schema:
                            allOf:
                                - $ref: "../components/schemas/OAuthClient.yaml"
                                - type: object
                                  required: [plaintextSecret]
                                  properties:
                                      plaintextSecret:
                                          type: string
                                          description: Returned ONCE — capture it now.
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]

"/admin/oauth/clients/{uniqueId}/disable":
    parameters:
        - in: path
          name: uniqueId
          required: true
          schema: { type: string }
    post:
        tags: [OAuth]
        operationId: oauthDisableClient
        summary: Disable an OAuth client
        description: Blocks further token issuance for the client without deleting the row.
        responses:
            "200":
                description: Client disabled.
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]

"/admin/oauth/clients/{uniqueId}/enable":
    parameters:
        - in: path
          name: uniqueId
          required: true
          schema: { type: string }
    post:
        tags: [OAuth]
        operationId: oauthEnableClient
        summary: Re-enable a disabled client
        description: Reverses `/disable`, allowing the client to issue tokens again.
        responses:
            "200":
                description: Client enabled.
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]

"/admin/oauth/clients/{uniqueId}/grants":
    parameters:
        - in: path
          name: uniqueId
          required: true
          schema: { type: string }
    get:
        tags: [OAuth]
        operationId: oauthListClientGrants
        summary: List grants for a client
        description: Lists user → client grant records for a specific OAuth client (each row is a Bigscreen account that has approved this client).
        responses:
            "200":
                description: Array of grants.
                content:
                    application/json:
                        schema:
                            type: array
                            items: { $ref: "../components/schemas/OAuthGrant.yaml" }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]

"/admin/oauth/clients/{uniqueId}/audit":
    parameters:
        - in: path
          name: uniqueId
          required: true
          schema: { type: string }
    get:
        tags: [OAuth]
        operationId: oauthClientAudit
        summary: Audit log for a specific client
        description: Returns audit-log entries scoped to a single OAuth client (creates, edits, secret rotations, disables, etc.).
        responses:
            "200":
                description: Audit log entries.
                content:
                    application/json:
                        schema:
                            type: array
                            items:
                                type: object
                                properties:
                                    uniqueId: { type: string }
                                    at:
                                        type: integer
                                        format: int64
                                        description: Unix ms.
                                    eventType: { type: string }
                                    actorAccountId: { type: [string, "null"] }
                                    clientId: { type: [string, "null"] }
                                    userId: { type: [string, "null"] }
                                    ip: { type: [string, "null"] }
                                    details:
                                        type: object
                                        additionalProperties: true
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]

"/admin/oauth/clients/{uniqueId}/step-up/challenge":
    parameters:
        - in: path
          name: uniqueId
          required: true
          schema: { type: string }
    post:
        tags: [OAuth]
        operationId: oauthStepUpChallenge
        summary: Send a step-up challenge code
        description: Emails a 6-digit code to the caller. The code is then submitted to `/step-up/verify` to open the unlock window.
        responses:
            "200":
                description: Challenge sent.
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]

"/admin/oauth/clients/{uniqueId}/step-up/verify":
    parameters:
        - in: path
          name: uniqueId
          required: true
          schema: { type: string }
    post:
        tags: [OAuth]
        operationId: oauthStepUpVerify
        summary: Verify the step-up code
        description: Verifies the 6-digit code from `/step-up/challenge` and opens a brief unlock window during which the caller may mutate the client.
        requestBody:
            required: true
            content:
                application/json:
                    schema:
                        type: object
                        required: [code]
                        properties:
                            code:
                                type: string
                                description: The 6-digit code from the challenge email.
        responses:
            "200":
                description: Step-up unlocked.
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Moderator, Fabricator, SuperUser]

"/admin/oauth/clients/audit":
    get:
        tags: [OAuth]
        operationId: oauthGlobalAudit
        summary: Global OAuth audit log
        description: Returns the global OAuth audit log spanning every client. SuperUser-only.
        responses:
            "200":
                description: Global audit-log entries.
                content:
                    application/json:
                        schema:
                            type: array
                            items:
                                type: object
                                properties:
                                    uniqueId: { type: string }
                                    at:
                                        type: integer
                                        format: int64
                                    eventType: { type: string }
                                    actorAccountId: { type: [string, "null"] }
                                    clientId: { type: [string, "null"] }
                                    userId: { type: [string, "null"] }
                                    ip: { type: [string, "null"] }
                                    details:
                                        type: object
                                        additionalProperties: true
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [SuperUser]

"/admin/oauth/clients/{uniqueId}/hard_delete":
    parameters:
        - in: path
          name: uniqueId
          required: true
          schema: { type: string }
    post:
        tags: [OAuth]
        operationId: oauthHardDeleteClient
        summary: Hard-delete an OAuth client
        description: Removes the client row entirely. Typically used on already-soft-deleted rows; also works on live rows. SuperUser-only.
        responses:
            "200":
                description: Client hard-deleted.
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [SuperUser]
