paths: # ─── Login (Step 1 — password check) ───────────────────────────────────── "/?ctrl=staffManagementCtl&api=login&ver=v1": post: operationId: login summary: Login with username and password description: | **Step 1 of 2-step login flow.** Validates username and password. On success the server returns `two_fa_status` indicating what the client should do next: - `VERIFIED` — account has 2FA active; call `validate2FACode` to complete login. - `NOT_CONFIGURED` — account has no 2FA set up; redirect to the Setup 2FA screen. No JWT is issued at this step. tags: [staffManagement] requestBody: required: true content: application/json: schema: $ref: "../components.yaml#/components/schemas/LoginRequest" example: username: "admin@example.com" password: "P@ssw0rd123" responses: "200": description: Credentials valid — partial session info returned. content: application/json: schema: $ref: "../components.yaml#/components/schemas/LoginResponse" example: is_valid: true user_id: "usr_staff_001" role: "ADMIN" two_fa_status: "VERIFIED" failed_login_attempts: 0 locked_login_expires_at: null "400": $ref: "../components.yaml#/components/responses/ClientError" "401": $ref: "../components.yaml#/components/responses/ClientError" "500": $ref: "../components.yaml#/components/responses/ServerError" # ─── Validate2FACode (Step 2 — TOTP check) ─────────────────────────────── "/?ctrl=staffManagementCtl&api=validate2FACode&ver=v1": post: operationId: validate2FACode summary: Validate 2FA code description: | **Step 2 of 2-step login flow.** Accepts the 6-digit TOTP code from the Authenticator app together with the `user_id`. On success the server returns whether the 2FA code is valid. tags: [staffManagement] requestBody: required: true content: application/json: schema: $ref: "../components.yaml#/components/schemas/VerifyOTPRequest" example: otp_code: "123456" user_id: "usr_staff_001" responses: "200": description: 2FA code validation result returned. content: application/json: schema: $ref: "../components.yaml#/components/schemas/VerifyOTPResponse" example: valid: true "400": $ref: "../components.yaml#/components/responses/ClientError" "401": $ref: "../components.yaml#/components/responses/ClientError" "500": $ref: "../components.yaml#/components/responses/ServerError" # ─── CancelOTPSession ───────────────────────────────────────────────────── "/?ctrl=staffManagementCtl&api=cancelOTPSession&ver=v1": post: operationId: cancelOTPSession summary: Cancel intermediate OTP session description: | Destroys the intermediate password session created in Step 1. Used when the user presses **"Go Back"** from the Step 2 OTP screen without completing login. tags: [staffManagement] requestBody: required: true content: application/json: schema: $ref: "../components.yaml#/components/schemas/CancelOTPSessionRequest" example: session_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." responses: "200": description: Session cancelled successfully. Empty response body. "400": $ref: "../components.yaml#/components/responses/ClientError" "401": $ref: "../components.yaml#/components/responses/ClientError" "500": $ref: "../components.yaml#/components/responses/ServerError"