openapi: 3.0.3 info: title: Baron SSO API version: "0.2.0" description: | Baron SSO Backend API 문서입니다. 이 문서는 Swagger UI/ReDoc 단일 엔드포인트에서 확인할 수 있으며, 도메인별 API 스펙은 점진적으로 확장합니다. servers: - url: / description: 동일 호스트 기준 tags: - name: System description: 공통/헬스/문서 - name: Auth description: 인증/세션/비밀번호/링크 로그인 - name: Signup description: 회원가입/검증 - name: User description: 사용자 프로필 - name: Session description: 세션 관리(계획) - name: Admin description: 관리자 기능/테넌트 - name: Public description: 인증 없이 외부에 노출되는 공개 API - name: Integrations description: API Key 기반 외부 연동 API - name: Dev description: RP/Consent 관리 - name: Audit description: 감사 로그 - name: Webhook description: 외부 게이트웨이 연동 paths: /.well-known/baron-rp-manifest: get: tags: [Public] summary: RP IAM Manifest HTML description: 외부 RP가 Baron SSO/IAM 연동 정책을 사람이 읽을 수 있는 HTML로 확인합니다. responses: "200": description: HTML content: text/html: schema: type: string /.well-known/baron-rp-manifest.json: get: tags: [Public] summary: RP IAM Manifest JSON description: 외부 RP가 Baron SSO/IAM 연동 정책을 machine-readable JSON으로 조회합니다. responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/RPManifestResponse" /.well-known/baron-rp-manifest.schema.json: get: tags: [Public] summary: RP IAM Manifest JSON Schema description: RP IAM Manifest JSON의 JSON Schema를 조회합니다. responses: "200": description: OK content: application/json: schema: type: object additionalProperties: true /health: get: tags: [System] summary: 헬스 체크 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/HealthResponse" /openapi.yaml: get: tags: [System] summary: OpenAPI YAML responses: "200": description: OK content: application/yaml: schema: type: string /docs: get: tags: [System] summary: Swagger UI responses: "200": description: HTML content: text/html: schema: type: string /redoc: get: tags: [System] summary: ReDoc responses: "200": description: HTML content: text/html: schema: type: string /api/v1/public/orgchart: get: tags: [Public] summary: 공유 링크 조직도 조회 description: 공유 링크 token으로 공개 가능한 조직도 데이터를 조회합니다. parameters: - in: query name: token required: true schema: type: string description: 조직도 공유 링크 token responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/PublicOrgChartResponse" "401": description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/tenants/registration: post: tags: [Public] summary: 테넌트 등록 요청 description: 외부에서 테넌트 등록을 요청하고 승인 대기 상태로 생성합니다. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TenantRegistrationRequest" responses: "202": description: Accepted content: application/json: schema: $ref: "#/components/schemas/TenantRegistrationResponse" "400": description: Bad Request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/integrations/org-context: get: tags: [Integrations] summary: 조직 Context 조회 description: | 외부 연동앱이 계정 세션 없이 API Key로 Baron SSO 조직 subtree를 조회합니다. `tenantSlug`가 없으면 `hanmac-family` 전체 subtree를 반환하며, slug 기반 지정만 계약으로 지원합니다. security: - BaronApiKeyId: [] BaronApiKeySecret: [] parameters: - in: query name: tenantSlug required: false schema: type: string default: hanmac-family description: 조회할 subtree root tenant slug - in: query name: includeUsers required: false schema: type: boolean default: true description: false이면 tenant members를 빈 배열로 반환합니다. - in: query name: includeUserIds required: false schema: type: boolean default: false description: true이면 tenant members[].id와 members[].phone만 추가합니다. responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/OrgContextResponse" "401": description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "403": description: Forbidden content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "404": description: Tenant slug not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/auth/password/login: post: tags: [Auth] summary: 비밀번호 로그인 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PasswordLoginRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/PasswordLoginResponse" "401": description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/auth/password/reset/initiate: post: tags: [Auth] summary: 비밀번호 재설정 시작 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PasswordResetInitiateRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/password/reset/verify: get: tags: [Auth] summary: 비밀번호 재설정 토큰 확인 페이지 responses: "200": description: HTML content: text/html: schema: type: string post: tags: [Auth] summary: 비밀번호 재설정 토큰 처리 requestBody: required: false content: application/x-www-form-urlencoded: schema: type: object properties: token: type: string responses: "302": description: Redirect /api/v1/auth/password/reset/complete: post: tags: [Auth] summary: 비밀번호 재설정 완료 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PasswordResetCompleteRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/password/policy: get: tags: [Auth] summary: 비밀번호 정책 조회 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/PasswordPolicyResponse" /api/v1/auth/enchanted-link/init: post: tags: [Auth] summary: Enchanted Link 시작 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/EnchantedLinkInitRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/EnchantedLinkInitResponse" /api/v1/auth/enchanted-link/poll: post: tags: [Auth] summary: Enchanted Link 폴링 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/EnchantedLinkPollRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/EnchantedLinkPollResponse" /api/v1/auth/magic-link/verify: post: tags: [Auth] summary: 매직 링크 검증 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/MagicLinkVerifyRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MagicLinkVerifyResponse" /api/v1/auth/sms: post: tags: [Auth] summary: SMS 전송 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SmsSendRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/verify-sms: post: tags: [Auth] summary: SMS 인증 코드 검증 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SmsVerifyRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/SmsVerifyResponse" /api/v1/auth/qr/init: post: tags: [Auth] summary: QR 로그인 세션 생성 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/QrInitResponse" /api/v1/auth/qr/poll: post: tags: [Auth] summary: QR 로그인 폴링 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/QrPollRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/QrPollResponse" /api/v1/auth/qr/approve: post: tags: [Auth] summary: QR 로그인 승인 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/QrApproveRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/signup/check-email: post: tags: [Signup] summary: 회원가입 이메일 확인 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SignupEmailCheckRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/signup/send-email-code: post: tags: [Signup] summary: 회원가입 이메일 코드 발송 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SignupEmailCodeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/signup/send-sms-code: post: tags: [Signup] summary: 회원가입 SMS 코드 발송 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SignupSmsCodeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/signup/verify-code: post: tags: [Signup] summary: 회원가입 코드 검증 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SignupVerifyCodeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/auth/signup: post: tags: [Signup] summary: 회원가입 완료 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SignupRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/SignupResponse" /api/v1/user/me: get: tags: [User] summary: 내 프로필 조회 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/UserProfileResponse" put: tags: [User] summary: 내 프로필 수정 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UserProfileUpdateRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/UserProfileResponse" /api/v1/user/me/send-code: post: tags: [User] summary: 프로필 변경 인증코드 전송 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UserProfileSendCodeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/user/me/password: post: tags: [User] summary: 비밀번호 변경 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UserPasswordChangeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/user/me/verify-code: post: tags: [User] summary: 프로필 변경 인증코드 검증 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UserProfileVerifyCodeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/user/rp/linked: get: tags: [User] summary: 연동된 RP 목록 조회 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/LinkedRpListResponse" "401": description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/sessions: get: tags: [Session] summary: 세션 목록 description: 세션 관리 API는 계획 단계입니다. x-status: planned responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/SessionListResponse" /api/v1/sessions/{id}: get: tags: [Session] summary: 세션 상세 description: 세션 관리 API는 계획 단계입니다. x-status: planned parameters: - in: path name: id required: true schema: type: string responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/SessionDetailResponse" delete: tags: [Session] summary: 세션 로그아웃(폐기) description: 세션 관리 API는 계획 단계입니다. x-status: planned parameters: - in: path name: id required: true schema: type: string responses: "204": description: No Content /api/v1/sessions/logout-all: post: tags: [Session] summary: 모든 세션 로그아웃 description: 세션 관리 API는 계획 단계입니다. x-status: planned responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/admin/check: get: tags: [Admin] summary: 관리자 인증 확인 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" "401": description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/admin/tenants: get: tags: [Admin] summary: 테넌트 목록 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/TenantListResponse" post: tags: [Admin] summary: 테넌트 생성 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TenantCreateRequest" responses: "201": description: Created content: application/json: schema: $ref: "#/components/schemas/TenantResponse" /api/v1/admin/tenants/export: get: tags: [Admin] summary: 테넌트 CSV 내보내기 description: | super admin 전용 CSV export입니다. `parentId`를 지정하면 해당 tenant의 모든 descendant를 leaf까지 포함해 내보냅니다. parameters: - in: query name: includeIds required: false schema: type: boolean default: false description: true이면 tenant_id와 parent_tenant_id 컬럼을 포함합니다. - in: query name: parentId required: false schema: type: string description: 하위 subtree를 내보낼 parent tenant ID responses: "200": description: CSV content: text/csv: schema: type: string "401": description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/admin/tenants/{id}: get: tags: [Admin] summary: 테넌트 상세 parameters: - in: path name: id required: true schema: type: string responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/TenantResponse" put: tags: [Admin] summary: 테넌트 수정 parameters: - in: path name: id required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TenantUpdateRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/TenantResponse" delete: tags: [Admin] summary: 테넌트 삭제 parameters: - in: path name: id required: true schema: type: string responses: "204": description: No Content /api/v1/admin/api-keys: get: tags: [Admin] summary: API Key 목록 description: super admin 전용 API Key 관리 화면에서 사용합니다. parameters: - in: query name: limit required: false schema: type: integer default: 50 - in: query name: offset required: false schema: type: integer default: 0 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ApiKeyListResponse" "401": description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" post: tags: [Admin] summary: API Key 생성 description: super admin만 API Key를 생성할 수 있으며, clientSecret은 생성 응답에서 한 번만 반환됩니다. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ApiKeyCreateRequest" responses: "201": description: Created content: application/json: schema: $ref: "#/components/schemas/ApiKeyCreateResponse" "400": description: Bad Request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/admin/api-keys/{id}: patch: tags: [Admin] summary: API Key 권한 수정 description: super admin 전용 API Key scope 수정입니다. client_id는 변경하지 않습니다. parameters: - in: path name: id required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ApiKeyUpdateScopesRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ApiKeySummary" "400": description: Bad Request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "404": description: Not Found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" delete: tags: [Admin] summary: API Key 삭제 description: super admin 전용 API Key 삭제입니다. parameters: - in: path name: id required: true schema: type: string responses: "204": description: No Content "401": description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/admin/api-keys/{id}/secret/rotate: post: tags: [Admin] summary: API Key Secret 재발급 description: super admin 전용 Secret rotation입니다. client_id는 유지되며 clientSecret은 응답에서 한 번만 반환됩니다. parameters: - in: path name: id required: true schema: type: string responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ApiKeyCreateResponse" "404": description: Not Found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /api/v1/dev/clients: get: tags: [Dev] summary: RP 목록 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ClientListResponse" post: tags: [Dev] summary: RP 생성 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ClientCreateRequest" responses: "201": description: Created content: application/json: schema: $ref: "#/components/schemas/ClientDetailResponse" /api/v1/dev/clients/{id}: get: tags: [Dev] summary: RP 상세 parameters: - in: path name: id required: true schema: type: string responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ClientDetailResponse" put: tags: [Dev] summary: RP 수정 parameters: - in: path name: id required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ClientUpdateRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ClientDetailResponse" delete: tags: [Dev] summary: RP 삭제 parameters: - in: path name: id required: true schema: type: string responses: "204": description: No Content /api/v1/dev/clients/{id}/status: patch: tags: [Dev] summary: RP 상태 변경 parameters: - in: path name: id required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ClientStatusPatchRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ClientDetailResponse" /api/v1/dev/consents: get: tags: [Dev] summary: Consent 목록 parameters: - in: query name: subject required: true schema: type: string - in: query name: client_id required: false schema: type: string responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/ConsentListResponse" delete: tags: [Dev] summary: Consent 회수 parameters: - in: query name: subject required: true schema: type: string - in: query name: client_id required: false schema: type: string responses: "204": description: No Content /api/v1/audit: post: tags: [Audit] summary: 감사 로그 수집 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/AuditLogRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/MessageResponse" /api/v1/client-log: post: tags: [Audit] summary: 클라이언트 로그 수집 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ClientLogRequest" responses: "200": description: OK components: securitySchemes: BaronApiKeyId: type: apiKey in: header name: X-Baron-Key-ID description: | API Key client ID입니다. Swagger UI 우측 상단 `Authorize`에서 `X-Baron-Key-ID` 값으로 입력하면 API Key 인증이 필요한 요청의 header에 자동으로 포함됩니다. BaronApiKeySecret: type: apiKey in: header name: X-Baron-Key-Secret description: | API Key client secret입니다. Swagger UI 우측 상단 `Authorize`에서 `X-Baron-Key-Secret` 값으로 입력하면 API Key 인증이 필요한 요청의 header에 자동으로 포함됩니다. schemas: ErrorResponse: type: object properties: error: type: string code: type: string details: type: object additionalProperties: true MessageResponse: type: object properties: message: type: string status: type: string HealthResponse: type: object properties: status: type: string checks: type: object RPManifestResponse: type: object additionalProperties: true properties: version: type: string example: "2026-05-11" issuer: type: string example: https://sso.hmac.kr oidc: type: object additionalProperties: true iam: type: object additionalProperties: true identity_contract: type: object additionalProperties: true trusted_headers: type: object additionalProperties: true PublicOrgChartUser: type: object properties: id: type: string name: type: string position: type: string jobTitle: type: string companyCode: type: string status: type: string PublicOrgChartResponse: type: object properties: tenants: type: array items: $ref: "#/components/schemas/TenantResponse" users: type: array items: $ref: "#/components/schemas/PublicOrgChartUser" sharedWith: type: string TenantRegistrationRequest: type: object required: [name, domain, adminEmail] properties: name: type: string slug: type: string description: type: string domain: type: string adminEmail: type: string format: email TenantRegistrationResponse: type: object properties: message: type: string tenant: $ref: "#/components/schemas/TenantResponse" OrgContextScope: type: object properties: tenantId: type: string example: 01970f08-91da-7286-bd19-882fb98d1f2c tenantSlug: type: string example: hanmac-family OrgContextTenant: type: object properties: id: type: string example: 01970f08-91da-7286-bd19-882fb98d1f2c type: type: string example: COMPANY_GROUP name: type: string example: 한맥가족 slug: type: string example: hanmac-family parentId: type: string nullable: true status: type: string example: active description: type: string domains: type: array items: type: string memberCount: type: integer visibility: type: string example: public orgUnitType: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time members: type: array description: 해당 tenant에 직접 소속된 사용자 목록입니다. items: $ref: "#/components/schemas/OrgContextMember" OrgContextTreeNode: allOf: - $ref: "#/components/schemas/OrgContextTenant" - type: object properties: children: type: array items: $ref: "#/components/schemas/OrgContextTreeNode" OrgContextMember: type: object properties: id: type: string description: includeUserIds=true일 때만 포함합니다. email: type: string format: email name: type: string phone: type: string description: includeUserIds=true일 때만 포함합니다. department: type: string grade: type: string position: type: string jobTitle: type: string isOwner: type: boolean description: appointment의 isOwner 또는 isManager 기준입니다. isLeader: type: boolean description: appointment의 lead 또는 isLead 기준이며, owner 계열 값이 true이면 true입니다. isPrimary: type: boolean description: appointment의 representative, isPrimary 또는 primary 기준입니다. OrgContextResponse: type: object properties: schemaVersion: type: string example: baron.org-context.v1 issuedAt: type: string format: date-time scope: $ref: "#/components/schemas/OrgContextScope" tree: $ref: "#/components/schemas/OrgContextTreeNode" tenants: type: array items: $ref: "#/components/schemas/OrgContextTenant" PasswordLoginRequest: type: object required: [loginId, password] properties: loginId: type: string password: type: string PasswordLoginResponse: type: object properties: sessionJwt: type: string refreshJwt: type: string status: type: string provider: type: string subject: type: string PasswordResetInitiateRequest: type: object required: [loginId] properties: loginId: type: string PasswordResetCompleteRequest: type: object required: [newPassword] properties: newPassword: type: string PasswordPolicyResponse: type: object properties: minLength: type: integer lowercase: type: boolean uppercase: type: boolean number: type: boolean nonAlphanumeric: type: boolean minCharacterTypes: type: integer EnchantedLinkInitRequest: type: object properties: loginId: type: string uri: type: string method: type: string EnchantedLinkInitResponse: type: object properties: linkId: type: string pendingRef: type: string maskedEmail: type: string expiresIn: type: integer EnchantedLinkPollRequest: type: object properties: pendingRef: type: string EnchantedLinkPollResponse: type: object properties: status: type: string sessionJwt: type: string MagicLinkVerifyRequest: type: object properties: token: type: string verifyOnly: type: boolean MagicLinkVerifyResponse: type: object properties: token: type: string status: type: string pendingRef: type: string message: type: string SmsSendRequest: type: object properties: phoneNumber: type: string SmsVerifyRequest: type: object properties: phoneNumber: type: string code: type: string SmsVerifyResponse: type: object properties: token: type: string message: type: string QrInitResponse: type: object properties: qrCode: type: string pendingRef: type: string expiresIn: type: integer QrPollRequest: type: object properties: pendingRef: type: string QrPollResponse: type: object properties: status: type: string sessionJwt: type: string QrApproveRequest: type: object properties: pendingRef: type: string token: type: string SignupEmailCheckRequest: type: object properties: email: type: string SignupEmailCodeRequest: type: object properties: email: type: string SignupSmsCodeRequest: type: object properties: phone: type: string SignupVerifyCodeRequest: type: object properties: target: type: string code: type: string SignupRequest: type: object properties: email: type: string phone: type: string name: type: string password: type: string department: type: string affiliationType: type: string companyCode: type: string SignupResponse: type: object properties: success: type: boolean message: type: string provider: type: string subject: type: string UserProfileResponse: type: object properties: id: type: string email: type: string name: type: string phone: type: string sessionAuthenticatedAt: type: string format: date-time department: type: string affiliationType: type: string companyCode: type: string UserProfileUpdateRequest: type: object properties: name: type: string phone: type: string department: type: string affiliationType: type: string companyCode: type: string UserPasswordChangeRequest: type: object properties: currentPassword: type: string newPassword: type: string UserProfileSendCodeRequest: type: object properties: phone: type: string UserProfileVerifyCodeRequest: type: object properties: phone: type: string code: type: string LinkedRpSummary: type: object properties: id: type: string name: type: string logo: type: string url: type: string init_url: type: string auto_login_supported: type: boolean auto_login_url: type: string lastAuthenticatedAt: type: string status: type: string scopes: type: array items: type: string LinkedRpListResponse: type: object properties: items: type: array items: $ref: "#/components/schemas/LinkedRpSummary" SessionSummary: type: object properties: id: type: string issuedAt: type: string expiresAt: type: string device: type: string ip: type: string userAgent: type: string SessionListResponse: type: object properties: items: type: array items: $ref: "#/components/schemas/SessionSummary" SessionDetailResponse: type: object properties: session: $ref: "#/components/schemas/SessionSummary" TenantResponse: type: object properties: id: type: string name: type: string slug: type: string description: type: string status: type: string createdAt: type: string updatedAt: type: string TenantListResponse: type: object properties: items: type: array items: $ref: "#/components/schemas/TenantResponse" limit: type: integer offset: type: integer total: type: integer TenantCreateRequest: type: object required: [name] properties: name: type: string slug: type: string description: type: string status: type: string TenantUpdateRequest: type: object properties: name: type: string slug: type: string description: type: string status: type: string ApiKeySummary: type: object properties: id: type: string name: type: string client_id: type: string scopes: type: array items: type: string example: [org-context:read] status: type: string example: active lastUsedAt: type: string nullable: true createdAt: type: string format: date-time ApiKeyListResponse: type: object properties: items: type: array items: $ref: "#/components/schemas/ApiKeySummary" total: type: integer ApiKeyCreateRequest: type: object required: [name] properties: name: type: string scopes: type: array items: type: string example: [org-context:read] ApiKeyUpdateScopesRequest: type: object required: [scopes] properties: scopes: type: array minItems: 1 items: type: string example: [audit:read, org-context:read] ApiKeyCreateResponse: type: object properties: apiKey: $ref: "#/components/schemas/ApiKeySummary" clientSecret: type: string description: 생성 시점에 한 번만 반환되는 plain secret ClientSummary: type: object properties: id: type: string name: type: string type: type: string status: type: string createdAt: type: string redirectUris: type: array items: type: string scopes: type: array items: type: string metadata: type: object additionalProperties: true ClientListResponse: type: object properties: items: type: array items: $ref: "#/components/schemas/ClientSummary" limit: type: integer offset: type: integer ClientEndpoints: type: object properties: discovery: type: string issuer: type: string authorization: type: string token: type: string userinfo: type: string ClientDetailResponse: type: object properties: client: $ref: "#/components/schemas/ClientSummary" endpoints: $ref: "#/components/schemas/ClientEndpoints" ClientCreateRequest: type: object required: [redirectUris] properties: id: type: string name: type: string type: type: string status: type: string redirectUris: type: array items: type: string scopes: type: array items: type: string grantTypes: type: array items: type: string responseTypes: type: array items: type: string tokenEndpointAuthMethod: type: string metadata: type: object additionalProperties: true ClientUpdateRequest: type: object properties: name: type: string type: type: string status: type: string redirectUris: type: array items: type: string scopes: type: array items: type: string grantTypes: type: array items: type: string responseTypes: type: array items: type: string tokenEndpointAuthMethod: type: string metadata: type: object additionalProperties: true ClientStatusPatchRequest: type: object required: [status] properties: status: type: string ConsentSummary: type: object properties: subject: type: string clientId: type: string clientName: type: string grantedScopes: type: array items: type: string authenticatedAt: type: string ConsentListResponse: type: object properties: items: type: array items: $ref: "#/components/schemas/ConsentSummary" AuditLogRequest: type: object properties: service: type: string event: type: string payload: type: object additionalProperties: true ClientLogRequest: type: object properties: level: type: string message: type: string data: type: object additionalProperties: true