Add secure administrator operations console
Provide TOTP-authenticated, role-controlled user and credit workflows with paginated audit data and SQL-backed statistics so operations can manage growth safely.
This commit is contained in:
+621
-1
@@ -412,12 +412,345 @@ paths:
|
||||
"200": { description: Bilingual HTML landing page }
|
||||
"404": { description: Invalid, unknown, or expired invitation }
|
||||
"503": { description: Invitation lookup is temporarily unavailable }
|
||||
/v1/admin/auth/session:
|
||||
get:
|
||||
security:
|
||||
- adminMtls: []
|
||||
summary: Check the current administrator session
|
||||
responses:
|
||||
"200":
|
||||
description: Authenticated or anonymous session state
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminSessionState" }
|
||||
"404": { description: Verified administrator client certificate is absent }
|
||||
/v1/admin/auth/login:
|
||||
post:
|
||||
security:
|
||||
- adminMtls: []
|
||||
summary: Authenticate an administrator with password and TOTP
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [username, password, totpCode]
|
||||
properties:
|
||||
username: { type: string, minLength: 3, maxLength: 64 }
|
||||
password: { type: string, minLength: 1, maxLength: 1024 }
|
||||
totpCode: { type: string, pattern: "^[0-9]{6}$" }
|
||||
responses:
|
||||
"200":
|
||||
description: Secure session and CSRF cookies created
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminLoginResponse" }
|
||||
"401": { description: Credentials are invalid }
|
||||
"429": { description: Login is locked or rate limited }
|
||||
/v1/admin/auth/logout:
|
||||
post:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Revoke the current administrator session
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminCsrf"
|
||||
responses:
|
||||
"204": { description: Session revoked }
|
||||
"401": { description: Session is invalid }
|
||||
/v1/admin/overview:
|
||||
get:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Return registration, activity, and credit overview statistics
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminRange"
|
||||
responses:
|
||||
"200":
|
||||
description: Overview statistics
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminOverview" }
|
||||
"400": { description: Range is invalid }
|
||||
"401": { description: Session is invalid }
|
||||
/v1/admin/referrals:
|
||||
get:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Return referral funnel and ranking statistics
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminRange"
|
||||
responses:
|
||||
"200":
|
||||
description: Referral statistics
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminReferralOverview" }
|
||||
"400": { description: Range is invalid }
|
||||
"401": { description: Session is invalid }
|
||||
/v1/admin/users:
|
||||
get:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: List users or search by exact internal user ID
|
||||
parameters:
|
||||
- name: q
|
||||
in: query
|
||||
schema: { type: string, maxLength: 36 }
|
||||
- name: cursor
|
||||
in: query
|
||||
schema: { type: string, maxLength: 256 }
|
||||
- $ref: "#/components/parameters/Limit"
|
||||
responses:
|
||||
"200":
|
||||
description: Privacy-minimized user summaries
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminUserPage" }
|
||||
"400": { description: Query or cursor is malformed }
|
||||
"401": { description: Session is invalid }
|
||||
"403": { description: ANALYST role cannot access user records }
|
||||
/v1/admin/users/{userId}:
|
||||
get:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Return privacy-minimized user details
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminUserId"
|
||||
responses:
|
||||
"200":
|
||||
description: User details
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminUserDetail" }
|
||||
"403": { description: ANALYST role cannot access user records }
|
||||
"404": { description: User was not found }
|
||||
/v1/admin/users/{userId}/ledger:
|
||||
get:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Return the immutable credit ledger for a user
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminUserId"
|
||||
- name: cursor
|
||||
in: query
|
||||
schema: { type: string, maxLength: 256 }
|
||||
- $ref: "#/components/parameters/Limit"
|
||||
responses:
|
||||
"200":
|
||||
description: Credit ledger entries ordered by creation time and entry ID
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminLedgerPage" }
|
||||
"400": { description: Cursor is malformed }
|
||||
"403": { description: ANALYST role cannot access credit ledger records }
|
||||
"404": { description: User was not found }
|
||||
/v1/admin/credits/grants:
|
||||
post:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Grant integer credits through an idempotent ledger transaction
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminCsrf"
|
||||
- $ref: "#/components/parameters/IdempotencyKey"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [userId, amount, reason]
|
||||
properties:
|
||||
userId: { type: string, format: uuid }
|
||||
amount: { type: integer, format: int64, minimum: 1 }
|
||||
reason: { type: string, minLength: 4, maxLength: 200 }
|
||||
responses:
|
||||
"200":
|
||||
description: Grant applied or replayed
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminGrantResponse" }
|
||||
"400": { description: Grant input or idempotency key is invalid }
|
||||
"403": { description: CSRF or role authorization failed }
|
||||
"404": { description: Target user was not found }
|
||||
"409": { description: Idempotency key conflicts with another grant }
|
||||
/v1/admin/operators/summary:
|
||||
get:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Return administrator and active-session security indicators
|
||||
responses:
|
||||
"200":
|
||||
description: Security indicators
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [enabledOperators, lockedOperators, activeSessions]
|
||||
properties:
|
||||
enabledOperators: { type: integer, minimum: 0 }
|
||||
lockedOperators: { type: integer, minimum: 0 }
|
||||
activeSessions: { type: integer, format: int64, minimum: 0 }
|
||||
"403": { description: INSUFFICIENT_PERMISSION; SUPER_ADMIN is required }
|
||||
/v1/admin/operators:
|
||||
get:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: List administrator operators
|
||||
parameters:
|
||||
- name: cursor
|
||||
in: query
|
||||
schema: { type: string, maxLength: 256 }
|
||||
- $ref: "#/components/parameters/Limit"
|
||||
responses:
|
||||
"200":
|
||||
description: Operators ordered by creation time
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminOperatorPage" }
|
||||
"403": { description: INSUFFICIENT_PERMISSION; SUPER_ADMIN is required }
|
||||
"400": { description: Cursor or limit is malformed }
|
||||
post:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Create an operator and return TOTP provisioning data once
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminCsrf"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminOperatorCreateRequest" }
|
||||
responses:
|
||||
"201":
|
||||
description: Operator created; plaintext TOTP material is returned only here
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminOperatorProvisioning" }
|
||||
"400": { description: VALIDATION_ERROR }
|
||||
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
||||
"409": { description: ADMIN_USERNAME_CONFLICT }
|
||||
/v1/admin/operators/{operatorId}/enable:
|
||||
post:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Enable an operator
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminOperatorId"
|
||||
- $ref: "#/components/parameters/AdminCsrf"
|
||||
responses:
|
||||
"204": { description: Operator enabled and action audited }
|
||||
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
||||
"404": { description: ADMIN_OPERATOR_NOT_FOUND }
|
||||
/v1/admin/operators/{operatorId}/disable:
|
||||
post:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Disable an operator and atomically revoke all active sessions
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminOperatorId"
|
||||
- $ref: "#/components/parameters/AdminCsrf"
|
||||
responses:
|
||||
"204": { description: Operator disabled and sessions revoked }
|
||||
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
||||
"404": { description: ADMIN_OPERATOR_NOT_FOUND }
|
||||
"409": { description: CANNOT_DISABLE_SELF or LAST_SUPER_ADMIN_REQUIRED }
|
||||
/v1/admin/operators/{operatorId}/unlock:
|
||||
post:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Clear an operator login lock
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminOperatorId"
|
||||
- $ref: "#/components/parameters/AdminCsrf"
|
||||
responses:
|
||||
"204": { description: Operator unlocked }
|
||||
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
||||
"404": { description: ADMIN_OPERATOR_NOT_FOUND }
|
||||
/v1/admin/operators/{operatorId}/credentials/reset:
|
||||
post:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Reset password and TOTP, atomically revoking all active sessions
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminOperatorId"
|
||||
- $ref: "#/components/parameters/AdminCsrf"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminOperatorPasswordRequest" }
|
||||
responses:
|
||||
"200":
|
||||
description: Credentials reset; plaintext TOTP material is returned only here
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminOperatorProvisioning" }
|
||||
"400": { description: VALIDATION_ERROR }
|
||||
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
||||
"404": { description: ADMIN_OPERATOR_NOT_FOUND }
|
||||
/v1/admin/operators/{operatorId}/sessions/revoke:
|
||||
post:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Revoke every active session for an operator
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/AdminOperatorId"
|
||||
- $ref: "#/components/parameters/AdminCsrf"
|
||||
responses:
|
||||
"204": { description: All active sessions revoked }
|
||||
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
||||
"404": { description: ADMIN_OPERATOR_NOT_FOUND }
|
||||
/v1/admin/audit:
|
||||
get:
|
||||
security:
|
||||
- adminMtls: []
|
||||
adminSession: []
|
||||
summary: Return append-only administrator audit events
|
||||
parameters:
|
||||
- name: cursor
|
||||
in: query
|
||||
schema: { type: string, maxLength: 256 }
|
||||
- $ref: "#/components/parameters/Limit"
|
||||
responses:
|
||||
"200":
|
||||
description: Recent audit events
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/AdminAuditPage" }
|
||||
"400": { description: Cursor is malformed }
|
||||
"403": { description: Super-administrator role is required }
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
adminMtls:
|
||||
type: mutualTLS
|
||||
description: Client certificate issued by the dedicated administrator CA.
|
||||
adminSession:
|
||||
type: apiKey
|
||||
in: cookie
|
||||
name: osg_admin_session
|
||||
parameters:
|
||||
Limit:
|
||||
name: limit
|
||||
@@ -432,7 +765,26 @@ components:
|
||||
name: Idempotency-Key
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string, minLength: 1, maxLength: 255 }
|
||||
schema: { type: string, minLength: 8, maxLength: 128 }
|
||||
AdminCsrf:
|
||||
name: X-CSRF-Token
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string, minLength: 32, maxLength: 512 }
|
||||
AdminRange:
|
||||
name: range
|
||||
in: query
|
||||
schema: { type: string, enum: [7d, 30d, 90d], default: 30d }
|
||||
AdminUserId:
|
||||
name: userId
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string, format: uuid }
|
||||
AdminOperatorId:
|
||||
name: operatorId
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string, format: uuid }
|
||||
responses:
|
||||
HealthUp:
|
||||
description: Service is healthy
|
||||
@@ -454,6 +806,274 @@ components:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/GatewayError" }
|
||||
schemas:
|
||||
AdminSessionState:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [authenticated]
|
||||
properties:
|
||||
authenticated: { type: boolean }
|
||||
operatorName: { type: ["string", "null"], minLength: 3, maxLength: 64 }
|
||||
role:
|
||||
type: ["string", "null"]
|
||||
enum: [SUPER_ADMIN, SUPPORT, ANALYST, null]
|
||||
description: CSRF material is intentionally not reconstructed or returned by session checks.
|
||||
AdminLoginResponse:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [operatorName, role, csrfToken]
|
||||
properties:
|
||||
operatorName: { type: string, minLength: 3, maxLength: 64 }
|
||||
role: { type: string, enum: [SUPER_ADMIN, SUPPORT, ANALYST] }
|
||||
csrfToken:
|
||||
type: string
|
||||
minLength: 32
|
||||
maxLength: 512
|
||||
description: Returned once for the new session; the CSRF cookie is the reload fallback.
|
||||
AdminUsageAggregate:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [kind, requests, chargedCredits, asrMillis, inputTokens, outputTokens]
|
||||
properties:
|
||||
kind: { type: string }
|
||||
requests: { type: integer, format: int64, minimum: 0 }
|
||||
chargedCredits: { type: integer, format: int64, minimum: 0 }
|
||||
asrMillis: { type: integer, format: int64, minimum: 0 }
|
||||
inputTokens: { type: integer, format: int64, minimum: 0 }
|
||||
outputTokens: { type: integer, format: int64, minimum: 0 }
|
||||
AdminTrendPoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [date, registrations, creditsUsed]
|
||||
properties:
|
||||
date: { type: string, format: date }
|
||||
registrations: { type: integer, format: int64, minimum: 0 }
|
||||
creditsUsed: { type: integer, format: int64, minimum: 0 }
|
||||
AdminOverview:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required:
|
||||
- totalUsers
|
||||
- activeUsers
|
||||
- newUsers
|
||||
- totalCreditBalance
|
||||
- creditsGranted
|
||||
- creditsUsed
|
||||
- trend
|
||||
- usage
|
||||
properties:
|
||||
totalUsers: { type: integer, format: int64, minimum: 0 }
|
||||
activeUsers: { type: integer, format: int64, minimum: 0 }
|
||||
newUsers: { type: integer, format: int64, minimum: 0 }
|
||||
totalCreditBalance: { type: integer, format: int64, minimum: 0 }
|
||||
creditsGranted: { type: integer, format: int64, minimum: 0 }
|
||||
creditsUsed: { type: integer, format: int64, minimum: 0 }
|
||||
trend:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/AdminTrendPoint" }
|
||||
usage:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/AdminUsageAggregate" }
|
||||
AdminFunnelStep:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [label, count]
|
||||
properties:
|
||||
label:
|
||||
type: string
|
||||
enum: [邀请码创建, 成功绑定, 有效使用并奖励, 待资格确认, 不符合奖励条件]
|
||||
count: { type: integer, format: int64, minimum: 0 }
|
||||
AdminReferralRank:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [userId, invited, qualified, creditsEarned]
|
||||
properties:
|
||||
userId: { type: string, format: uuid }
|
||||
invited: { type: integer, format: int64, minimum: 0 }
|
||||
qualified: { type: integer, format: int64, minimum: 0 }
|
||||
creditsEarned: { type: integer, format: int64, minimum: 0 }
|
||||
AdminReferralOverview:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [pendingBindings, ineligibleBindings, funnel, ranking]
|
||||
properties:
|
||||
pendingBindings: { type: integer, format: int64, minimum: 0 }
|
||||
ineligibleBindings: { type: integer, format: int64, minimum: 0 }
|
||||
funnel:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/AdminFunnelStep" }
|
||||
ranking:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/AdminReferralRank" }
|
||||
AdminUserSummary:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [userId, displayName, status, creditBalance, createdAt]
|
||||
properties:
|
||||
userId: { type: string, format: uuid }
|
||||
displayName: { type: string }
|
||||
status: { type: string, enum: [active, suspended, closed] }
|
||||
creditBalance: { type: integer, format: int64, minimum: 0 }
|
||||
createdAt: { type: string, format: date-time }
|
||||
AdminUserPage:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [items]
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/AdminUserSummary" }
|
||||
nextCursor: { type: ["string", "null"] }
|
||||
AdminUserReferral:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [invitedUsers, rewardedInvites]
|
||||
properties:
|
||||
inviterUserId: { type: ["string", "null"], format: uuid }
|
||||
invitedUsers: { type: integer, format: int64, minimum: 0 }
|
||||
rewardedInvites: { type: integer, format: int64, minimum: 0 }
|
||||
AdminUserDetail:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required:
|
||||
- userId
|
||||
- displayName
|
||||
- status
|
||||
- creditBalance
|
||||
- createdAt
|
||||
- qualifiedUsage
|
||||
- usage
|
||||
- referral
|
||||
properties:
|
||||
userId: { type: string, format: uuid }
|
||||
displayName: { type: string }
|
||||
status: { type: string, enum: [active, suspended, closed] }
|
||||
creditBalance: { type: integer, format: int64, minimum: 0 }
|
||||
createdAt: { type: string, format: date-time }
|
||||
lastActiveAt: { type: ["string", "null"], format: date-time }
|
||||
qualifiedUsage: { type: boolean }
|
||||
referralCode: { type: ["string", "null"] }
|
||||
referredByUserId: { type: ["string", "null"], format: uuid }
|
||||
usage:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/AdminUsageAggregate" }
|
||||
referral: { $ref: "#/components/schemas/AdminUserReferral" }
|
||||
AdminLedgerEntry:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [entryId, type, amount, balanceAfter, reasonCode, createdAt]
|
||||
properties:
|
||||
entryId: { type: string, format: uuid }
|
||||
type: { type: string, enum: [grant, reserve, settle, refund, adjustment] }
|
||||
amount: { type: integer, format: int64 }
|
||||
balanceAfter: { type: integer, format: int64, minimum: 0 }
|
||||
reasonCode: { type: string }
|
||||
createdAt: { type: string, format: date-time }
|
||||
AdminLedgerPage:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [items]
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/AdminLedgerEntry" }
|
||||
nextCursor: { type: ["string", "null"] }
|
||||
AdminGrantResponse:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [transactionId, balanceAfter]
|
||||
properties:
|
||||
transactionId: { type: string, format: uuid }
|
||||
balanceAfter: { type: integer, format: int64, minimum: 0 }
|
||||
AdminAudit:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [auditId, operatorName, action, targetType, targetId, result, createdAt]
|
||||
properties:
|
||||
auditId: { type: string, format: uuid }
|
||||
operatorName: { type: string }
|
||||
action: { type: string }
|
||||
targetType: { type: string }
|
||||
targetId: { type: string }
|
||||
requestId: { type: ["string", "null"] }
|
||||
result: { type: string, enum: [success, rejected] }
|
||||
createdAt: { type: string, format: date-time }
|
||||
AdminAuditPage:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [items]
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/AdminAudit" }
|
||||
nextCursor: { type: ["string", "null"] }
|
||||
AdminOperator:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required:
|
||||
- operatorId
|
||||
- username
|
||||
- role
|
||||
- enabled
|
||||
- failedLoginCount
|
||||
- createdAt
|
||||
- updatedAt
|
||||
properties:
|
||||
operatorId: { type: string, format: uuid }
|
||||
username:
|
||||
type: string
|
||||
pattern: "^[a-z0-9][a-z0-9._@-]{2,63}$"
|
||||
role: { type: string, enum: [SUPER_ADMIN, SUPPORT, ANALYST] }
|
||||
enabled: { type: boolean }
|
||||
failedLoginCount: { type: integer, minimum: 0 }
|
||||
lockedUntil: { type: ["string", "null"], format: date-time }
|
||||
lastLoginAt: { type: ["string", "null"], format: date-time }
|
||||
createdAt: { type: string, format: date-time }
|
||||
updatedAt: { type: string, format: date-time }
|
||||
AdminOperatorPage:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [items]
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/AdminOperator" }
|
||||
nextCursor: { type: ["string", "null"] }
|
||||
AdminOperatorCreateRequest:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [username, password, role]
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
minLength: 3
|
||||
maxLength: 64
|
||||
pattern: "^[A-Za-z0-9][A-Za-z0-9._@-]{2,63}$"
|
||||
password: { type: string, minLength: 12, maxLength: 1024 }
|
||||
role: { type: string, enum: [SUPER_ADMIN, SUPPORT, ANALYST] }
|
||||
AdminOperatorPasswordRequest:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [password]
|
||||
properties:
|
||||
password: { type: string, minLength: 12, maxLength: 1024 }
|
||||
AdminOperatorProvisioning:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [operatorId, totpSecret, otpauthUri]
|
||||
properties:
|
||||
operatorId: { type: string, format: uuid }
|
||||
operator:
|
||||
oneOf:
|
||||
- $ref: "#/components/schemas/AdminOperator"
|
||||
- type: "null"
|
||||
totpSecret:
|
||||
type: string
|
||||
pattern: "^[A-Z2-7]{32}$"
|
||||
description: 160-bit Base32 secret returned once; never persisted in plaintext.
|
||||
otpauthUri:
|
||||
type: string
|
||||
pattern: "^otpauth://totp/"
|
||||
description: Provisioning URI returned once; never persisted.
|
||||
AppleSignInRequest:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
Reference in New Issue
Block a user