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/OVERVIEW.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

7.1 KiB

Backend overview

Living spec for the shared platform API consumed by Gishen-B2B. This repo implements mocks typed to this contract; the backend service is consolidated later from B2B, Ecom, Mobile, and Admin spec sheets.

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

Base URL (future)

https://api.gishenpharmacy.org/v1

Mock adapters in this repo live under src/lib/api/ and src/mocks/.

Tenancy

  • Every authenticated request (except public registration) is scoped to an organisation via orgId on the session or explicit path prefix.
  • Org lifecycle: pending_activation → active → suspended | closed.
  • Pending orgs: SUPER_USER may read status and submitted registration; cannot create members, packages, or migration commits until Admin activates.
X-Org-Id: org_01H...

For single-org sessions, orgId is implicit from JWT/session. Multi-org users (rare in B2B) pass X-Org-Id.

Authentication

Mode (this phase) Description
Mock demo /login offers Google, email, phone, Telegram (UI mocked) plus a test-user dropdown; any path sets session via demo_user_id
Production (future) Google OIDC, email magic-link/OTP, SMS OTP, Telegram Login Widget / Mini App — see endpoints/auth.md

Demo personas: user_super, user_hr, user_fin, user_mem — see GET /v1/auth/demo-profiles.

Session shape

See entities/session-user.md. Includes avatar_url, roles[], and active_role for multi-role demo users.

JWT claims (future)

{
  "sub": "usr_01H...",
  "org_id": "org_01H...",
  "roles": ["HR_ADMIN", "FINANCE"],
  "active_role": "HR_ADMIN",
  "locale": "am",
  "iat": 1710000000,
  "exp": 1710003600
}

RBAC matrix

Resource / action SUPER_USER HR_ADMIN FINANCE MEMBER
Own profile (/v1/me/profile) ✓ ✓ ✓ ✓
Org profile (commercial read) ✓ ✓ (active only) ✓ (active only) —
Org registration submit ✓ (public path) — — —
Departments CRUD ✓ ✓ read —
Members CRUD / import / invite ✓ ✓ read metadata own row
Pharmacy ID card (print / QR payload) ✓ ✓ — own only
Packages CRUD ✓ ✓ read own assignment
Migration jobs ✓ ✓ read history —
Finance spend / statements ✓ read aggregates ✓ —
Finance approvals ✓ — ✓ —
Member allowance / orders ✓ — — ✓
Prescriptions (clinical) ✓ full withheld withheld own only
Settings / verification ✓ ✓ — —

Clinical withhold: HR_ADMIN and FINANCE never receive prescription images, medicine line items, dosages, prescriber notes, or diagnosis-related fields. Aggregates (e.g. “Rx order — ETB 450, category: chronic”) may appear in finance spend. SUPER_USER bypasses withhold for support/disputes.

Error model

All errors return:

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Human-readable summary",
    "details": [
      { "field": "email", "code": "INVALID_FORMAT", "message": "..." }
    ],
    "request_id": "req_01H..."
  }
}

Standard HTTP status codes

Status Usage
400 Validation failed, malformed JSON
401 Missing or expired session
403 Authenticated but role/org forbids action; clinical withhold
404 Resource not found or not visible in tenant
409 Conflict (duplicate member, job already committed)
422 Business rule violation (org pending, credit exceeded)
429 Rate limit
500 Internal error

Error codes (catalog)

Code HTTP Description
UNAUTHENTICATED 401 No valid session
FORBIDDEN 403 Role cannot perform action
CLINICAL_WITHHELD 403 Clinical field requested by HR/Finance
ORG_PENDING 422 Org not yet activated by Admin
ORG_SUSPENDED 422 Org suspended
VALIDATION_FAILED 400 Field-level validation
DUPLICATE_MEMBER 409 Phone/email/employee_id conflict
CREDIT_LIMIT_EXCEEDED 422 Would exceed org credit
MIGRATION_JOB_LOCKED 409 Job already committed or rolled back
INVITE_EXPIRED 422 Invite token expired
NOT_FOUND 404 Generic not found

Pagination

List endpoints accept:

?page=1&page_size=25&sort=-created_at&q=search

Response envelope:

{
  "data": [ ... ],
  "pagination": {
    "page": 1,
    "page_size": 25,
    "total_items": 142,
    "total_pages": 6
  }
}

Default page_size: 25. Max: 100.

Filtering & date ranges

List endpoints support search + filters (portal toolbar / modal when >3 filters):

Domain Query params (common)
Members q, status, department_id, package_id, member_type, has_dependants
Finance spend from, to, department_id, category, coverage, member_id, approval_status
Statements year, status
Migration status, dataset_type, has_errors, created_by
Packages / departments q, status / site
?from=2026-01-01&to=2026-01-31&department_id=dept_01H...

ISO 8601 dates in org timezone (default Africa/Addis_Ababa).

Pharmacy ID card (platform contract)

Members carry a printable verification card used at Gishen pharmacy / Ecom checkout:

Field Purpose
avatar_url Photo on card + portal UI
card_id Human-readable card number (e.g. GSH-1042)
verification_id Org verification token encoded in QR

QR payload (canonical):

gishen://member/{member_id}?v={verification_id}

Admin / POS scans the QR to resolve the member for covered purchase. Clinical detail is not on the card. See endpoints/members.md and ../coordination/gishen-admin.md.

File uploads

Multipart for Rx images and migration files:

POST /v1/... 
Content-Type: multipart/form-data

Max file size (Rx page): 10 MB. Accepted: image/jpeg, image/png, application/pdf.

Migration uploads: 50 MB .xlsx, .xls, .csv.

Idempotency

Mutating endpoints that create billing or migration commits accept:

Idempotency-Key: <uuid>

Duplicate keys within 24h return the original response.

Webhooks / events

Domain events published to platform bus; see events/README.md. B2B emits and consumes events for org registration, migration, and prescriptions.

Environment (Vercel frontend)

Variable Purpose
NEXT_PUBLIC_API_BASE_URL Platform API base (mock or real)
NEXT_PUBLIC_MOCK_AUTH true for demo role selector
NEXT_PUBLIC_DEFAULT_LOCALE en

Document production URL in this file when first Vercel deploy is finalized.