This repository has been archived on 2026-08-11. You can view files and clone it, but cannot push or open issues or pull requests.
Gishen-B2B/docs/backend/endpoints/auth.md
kirukib f2e992e0bd Add multi-method login UI and document auth method contracts.
Surface Google, email, phone, and Telegram on login (mocked), polish the brand panel and fixes for Button/Menu, and keep the backend spec sheet aligned.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 16:12:43 +03:00

6.7 KiB
Raw Blame History

Endpoints: Auth

Session and user preference endpoints for Gishen-B2B demo login and future production auth.

Workspace: /Users/kirukib/Desktop/Yaltopia Project/Gishen-B2B

Entity: ../entities/session-user.md


POST /v1/auth/login

Demo persona login (mock phase). Prefer demo_user_id; demo_role remains for compatibility.

Auth Public
Roles —

Request

{
  "demo_user_id": "user_hr",
  "locale": "en"
}

Legacy: { "demo_role": "HR_ADMIN", "locale": "en" }
demo_role: SUPER_USER | HR_ADMIN | FINANCE | MEMBER

Production (future): { "email", "password" } or OAuth code exchange.

Planned auth methods (UI present; production TBD)

Method Future flow Mock phase
Google OAuth 2.0 / OIDC Button → toast → demo persona session
Email Magic link or password OTP Same
Phone SMS OTP (E.164) Same
Telegram Telegram Login Widget / Mini App deep link Same

Demo continues to use demo_user_id until platform auth is wired.

Future endpoints (stubs)

Method Path Notes
GET /v1/auth/oauth/google/start Redirect to Google; callback exchanges code
POST /v1/auth/email/otp/start Body { "email" } — send OTP / magic link
POST /v1/auth/email/otp/verify Body { "email", "code" } — returns session
POST /v1/auth/phone/otp/start Body { "phone" } E.164
POST /v1/auth/phone/otp/verify Body { "phone", "code" }
POST /v1/auth/telegram/callback Telegram Login Widget payload verification

All production methods return the same session envelope as POST /v1/auth/login.

Response 200

{
  "data": {
    "token": "mock_jwt_...",
    "user": {
      "id": "user_hr",
      "email": "hr@yaltopia.com",
      "full_name": "Hanna HR",
      "org_id": "org_yaltopia",
      "roles": ["HR_ADMIN"],
      "active_role": "HR_ADMIN",
      "locale": "en",
      "avatar_url": "https://api.dicebear.com/9.x/lorelei/svg?seed=user_hr",
      "org_status": "active",
      "permissions": ["org:read", "org:write_hr", "members:write", "packages:write", "migration:write", "finance:read"]
    }
  }
}

Errors

Code HTTP When
VALIDATION_FAILED 400 Invalid demo_user_id / demo_role
NOT_FOUND 404 Unknown demo persona
UNAUTHENTICATED 401 Production bad credentials

Clinical withhold

N/A — session only.


POST /v1/auth/logout

Auth Required
Roles Any

Response 204

No body.


GET /v1/auth/me

Current session user.

Auth Required
Roles Any

Response 200

{
  "data": {
    "id": "usr_01HMEM",
    "email": "member.demo@acme.et",
    "full_name": "Demo Member",
    "org_id": "org_01DEMO",
    "member_id": "mbr_01DEMO",
    "customer_id": "cus_01DEMO",
    "roles": ["MEMBER"],
    "locale": "am",
    "org_status": "active",
    "allowance_summary": {
      "allowance_remaining": { "amount": "10800.00", "currency": "ETB" }
    }
  }
}

Errors

Code HTTP
UNAUTHENTICATED 401

PATCH /v1/auth/me/locale

Update user locale preference.

Auth Required
Roles Any

Request

{ "locale": "am" }

Response 200

Returns updated session user with locale: "am".

Validation

Rule Code
locale in en, am VALIDATION_FAILED

Clinical withhold

N/A.


GET /v1/auth/demo-profiles

List pre-seeded demo personas for /login test-user dropdown.

Auth Public
Roles —

Response 200

{
  "data": [
    {
      "id": "user_super",
      "email": "super@yaltopia.com",
      "full_name": "Selam Super",
      "demo_role": "SUPER_USER",
      "roles": ["SUPER_USER", "HR_ADMIN", "FINANCE", "MEMBER"],
      "avatar_url": "https://api.dicebear.com/9.x/lorelei/svg?seed=user_super",
      "label": "Super User",
      "description": "Full portal access including clinical detail"
    },
    {
      "id": "user_hr",
      "email": "hr@yaltopia.com",
      "full_name": "Hanna HR",
      "demo_role": "HR_ADMIN",
      "roles": ["HR_ADMIN"],
      "avatar_url": "https://api.dicebear.com/9.x/lorelei/svg?seed=user_hr",
      "label": "HR Administrator",
      "description": "Members, departments, packages — no clinical detail"
    },
    {
      "id": "user_fin",
      "email": "finance@yaltopia.com",
      "full_name": "Fikru Finance",
      "demo_role": "FINANCE",
      "roles": ["FINANCE"],
      "avatar_url": "https://api.dicebear.com/9.x/lorelei/svg?seed=user_fin",
      "label": "Finance Approver",
      "description": "Spend, statements, approvals — no clinical detail"
    },
    {
      "id": "user_mem",
      "email": "member@yaltopia.com",
      "full_name": "Abebe Member",
      "demo_role": "MEMBER",
      "roles": ["MEMBER"],
      "member_id": "mbr_01HMEM001",
      "avatar_url": "https://api.dicebear.com/9.x/lorelei/svg?seed=user_mem",
      "label": "Member",
      "description": "Own allowance, orders, prescriptions"
    }
  ]
}

Login request may use { "demo_user_id": "user_hr" } (preferred) or legacy { "demo_role": "HR_ADMIN" }.


GET /v1/me/profile

Current user’s profile (account page).

Auth Required
Roles Any

Response 200

{
  "data": {
    "id": "user_hr",
    "email": "hr@yaltopia.com",
    "full_name": "Hanna HR",
    "org_id": "org_yaltopia",
    "org_name": "Yaltopia",
    "roles": ["HR_ADMIN"],
    "active_role": "HR_ADMIN",
    "locale": "en",
    "avatar_url": "https://api.dicebear.com/9.x/lorelei/svg?seed=user_hr",
    "avatar_initials": "HH",
    "member_id": null
  }
}

PATCH /v1/me/profile

Update display preferences (locale / name stub / active role for multi-role users).

Auth Required
Roles Any

Request

{
  "locale": "am",
  "active_role": "SUPER_USER"
}

active_role must be one of the user’s roles[] (demo: user_super holds all four).

Response 200

Updated profile object.

Errors

Code HTTP When
VALIDATION_FAILED 400 Invalid locale or role not in roles[]

UI routes

Route Purpose
/login Sign-in methods (Google, email, phone, Telegram — mocked) + demo persona dropdown + locale
/profile Own profile — avatar, org, role switch, sign out

Clinical withhold notes

Auth endpoints do not expose clinical data. Role list / active_role on session determines withhold behavior on downstream endpoints.