Gishen — Cross-App Master Spec
Living collective contract across Gishen client apps. Deeper API sketches live in each repo’s own backend sheet; this file is the shared map of roles, domain objects, auth providers, and known divergences.
| Field |
Value |
| Home repo (this file) |
Gishen-Admin |
| Sibling root |
/Users/kirukib/Desktop/Yaltopia Project/ |
| Shared API base (TBD) |
https://api.gishen.example/v1 (Ecom/Mob/Admin) · B2B draft: https://api.gishenpharmacy.org/v1 — unify TBD |
| Last reconciled |
2026-08-07 |
Changelog
| Date |
Change |
| 2026-08-07 |
Seed batch: Created master spec from Admin living contract + sibling Mob/Ecom/B2B/Dispatch sheets. Documented product surface map, shared domain objects (auth, orgs, doctors, orders/guest, Rx dosing, catalogue multi-UOM + PDP, stock, loyalty), auth provider matrix, divergence & sync notes, deeper-doc links, Sources stamp, and pre-push update rule. Wired .cursor/rules + optional .githooks/pre-push reminder. Linked from Admin README.md and admin-backend-spec.md. |
Update rule (before every push)
This file is the cross-app master. Before git push from Gishen-Admin (humans and agents):
- Diff Admin
src/ / docs/admin-backend-spec.md against the last Sources stamp below.
- Skim sibling Mob / Ecom / B2B / Dispatch specs if those folders exist on disk.
- Refresh relevant sections here; append a Changelog row (date + why).
- If Admin endpoints/fields changed, also update
admin-backend-spec.md in the same change set.
- Update the Sources stamp (
Last reconciled + checklist dates).
Agents: the Cursor rule .cursor/rules/update-master-spec-before-push.mdc applies on push requests. Optional git hook: see Pre-push tooling.
Sources stamp
Update these dates whenever you reconcile against a sibling.
| Source |
Path (sibling area) |
Found |
Spec / README |
Last skimmed |
| Admin |
Gishen-Admin/ |
✅ |
docs/admin-backend-spec.md |
2026-08-07 |
| Mob |
Gishen-Mob/ |
✅ |
docs/BACKEND_SPEC.md (relative from sibling root) |
2026-08-07 |
| Ecom |
Gishen-Ecom/ |
✅ |
docs/backend.md |
2026-08-07 |
| B2B |
Gishen-B2B/ |
✅ |
docs/backend/OVERVIEW.md + coordination |
2026-08-07 |
| Dispatch Bot |
Gishen-Dispatch-Bot/ |
✅ (related) |
docs/BACKEND_SPEC.md |
2026-08-07 |
| Telegram Mini App |
Gishen-Telegram-MiniApp/ |
⚠️ empty scaffold |
— |
2026-08-07 |
Sources not found
None for the four primary surfaces (Admin / Mob / Ecom / B2B). Related folders present but thin: Gishen-Telegram-MiniApp (empty), Dispatch Bot documented as rider surface.
Pre-push checklist (human / agent)
1. Product surface map
One shared pharmacy platform; four primary clients + rider bot.
| App |
Repo |
Who |
Primary jobs |
| Admin |
Gishen-Admin |
Pharmacy staff: pharmacist, stock_manager, procurement, finance, marketing_manager, operations, super_admin |
Branch Rx queue, orders/POS, stock, procurement, org commercial activation, CRM/loyalty config, dispatch board, team/audit, catalogue master, doctor roster |
| Mob |
Gishen-Mob |
Retail customer (Expo) |
Catalog/PDP, cart/checkout, guest pharmacist codes, Rx Care (scan/reminders), loyalty, family, subscriptions, B2B join/contexts, tracking |
| Ecom |
Gishen-Ecom |
Retail customer (Next.js PWA) |
Storefront catalog, Rx upload/check, cart → order request, profile/favorites/loyalty, branches; v1 confirmation often phone/WhatsApp |
| B2B |
Gishen-B2B |
Institutional: SUPER_USER, HR_ADMIN, FINANCE, MEMBER |
Org self-register; HR members/packages/migration; Finance statements/approvals; Member allowance + own Rx (clinical withhold for HR/Finance) |
| Dispatch Bot |
Gishen-Dispatch-Bot |
Riders/drivers |
Telegram-enrolled trip status + POD; no separate rider login app for v1 |
| Telegram Mini App |
Gishen-Telegram-MiniApp |
Customers (planned) |
Placeholder — Ecom backend mentions Telegram auth/bootstrap; TBD |
Who creates what
| Artefact |
Created by |
Verified / fulfilled by |
| Retail order (registered) |
Customer (Mob/Ecom) |
Pharmacist / Ops (Admin) |
Guest order / pharmacist code (GSH-XXXX) |
Guest/customer Mob/Ecom; staff/doctor Admin |
Pharmacist Admin (by-code / POS) |
| Prescription intake (customer scan) |
Mob/Ecom/B2B member |
Pharmacist Admin |
| Doctor-authored Rx / clinical order |
Doctor (hospital org) |
Pharmacist Admin |
| Catalogue Item master |
Stock/super_admin Admin |
Consumed by Mob/Ecom as /catalog/products |
| Org commercial terms |
Admin Finance |
B2B unlocks on org.activated |
| Trip assign |
Ops Admin |
Dispatch Bot rider |
External actors (not Admin staff roles)
| Actor |
Auth surface |
Notes |
| Doctor |
Separate doctor JWT (Admin sheet); hospital/clinic org affiliation |
Create Rx & guest/registered patient orders; not a StaffRole |
| End customer (guest) |
None / Mob POST /auth/guest / Ecom guest order |
Phone required for assisted/guest checkout; loyalty gated |
| B2B roles |
B2B portal session |
Distinct from pharmacy staff; shared customer_id linkage TBD |
2. Shared domain objects
Fields below are the platform-level vocabulary. Path prefixes and exact DTOs still differ per sheet — see §4 Divergence.
2.1 Users & auth providers
| Concept |
Shared idea |
App notes |
| Platform person |
UUID user / customer |
Staff vs customer vs doctor vs B2B user are actors, not one role enum everywhere |
| Staff |
Admin StaffUser + StaffRole + optional branchId |
Bearer JWT |
| Customer |
Retail identity; loyalty points/tier |
Mob GET /users/me; Ecom same idea |
| Doctor |
Hospital/clinic-affiliated clinician |
Admin roster + POST /auth/doctor/login |
| B2B session user |
roles[], org_id, active_role |
Clinical withhold for HR/Finance |
authProvider |
email | google | phone | telegram (+ Mob guest) |
Report on /me / login response |
| Locale |
en | am |
Admin preferredLocale; Mob/Ecom/B2B locale / Accept-Language |
See §3 Auth matrix.
2.2 Organisations
| Type (Admin) |
Used for |
corporate | ngo | other |
B2B benefits clients — credit, packages, members |
hospital | clinic |
Doctor affiliation; clinical Rx/orders |
Lifecycle (B2B): pending_activation → active → suspended | closed. Admin writes commercial terms (credit, payment terms, price_list_id, contract dates) and emits activation events. B2B self-register UI → Admin approval queue.
2.3 Doctors
- Roster under hospital/clinic orgs in Admin (
/doctors, org detail).
- Fields (Admin):
name, specialty, licenseNumber, phone, email, status, orgId, …
- Can create prescriptions and orders for guest or registered patients, org-scoped.
- Cannot manage catalogue, RBAC, finance, other hospitals.
- Identity provider strategy vs B2B hospital users: open (Admin Q8 / Q17).
2.4 Orders (registered + guest)
| Field / idea |
Meaning |
customerType |
Admin: registered | guest on staff/doctor-created orders |
| Guest identity |
customerName + required customerPhone; no customerId |
| Channels |
Admin includes branch / POS / doctor / (ops); Mob/Ecom retail + guest codes |
| Pharmacist code |
Mob/Ecom: GSH-XXXX via POST /orders/guest-codes; Admin fulfill GET/POST .../by-code/:code |
| Fulfillment |
pickup | delivery (+ branch / any-branch for guest codes) |
| Payments |
Mob: Chapa / Telebirr / M-Pesa for delivery; pay_at_branch pickup-only. Ecom v1 often offline confirm |
Guest limits (proposed): valid phone; controlled SKUs still need approved Rx; no loyalty earn until claim/merge — TBD claim-by-OTP (Admin Q9–10).
2.5 Prescriptions + dosing schedule
| Layer |
Contract |
| Admin line item |
frequency?: QD|BID|TID|QID|QXH|custom; intervalHours? (QXH); times?: HH:mm[] |
| Mob reminders |
POST /health/reminders with times[], grace, escalate; calendar UI; confirm/snooze |
| Sync intent |
Persist pharmacist final times (+ interval) on approve/dispense so Mob can seed reminders without re-derive — when to push still open (Admin Q13) |
| Customer Rx Care |
Mob/Ecom upload + prescriptions/check stock match statuses |
| B2B |
Member submits Rx; HR/Finance never see clinical lines |
Admin helper: src/lib/dosingSchedule.ts.
2.6 Catalog / Items + multi-UOM + storefront PDP
| Concept |
Admin (source of truth for ops) |
Mob / Ecom (retail read model) |
| Master product |
/admin/catalog/items — Item with SKU, classification, media, EFDA, … |
/catalog/products (+ slug) |
| Stock link |
Inventory rows reference itemId |
/stock/product/:productId, branches nearby |
| Multi-UOM |
uoms[] + conversionFactor into stock baseUnit; toStockQty / fromStockQty |
Not yet on Mob product type — sell unit is display unit string only |
| PDP fields |
storefrontUnit, useCase, compareAtPriceEtb, side-effect lists, directions[], storageNotes[], pharmacistTip |
Mob PDP: product + getDrugFacts() clinical overlay (useCase, form, dosages, mild/severe, storage, directions, advice) |
| Pricing lists |
B2B price_list_id on org commercial |
Ecom/Mob show retail (and credit quote at checkout) |
2.7 Stock
- Branch qty, batch/lot, expiry on Stock, not Item.
- ERP sync / field ownership / merge proposals: Admin Stock module.
- Mob/Ecom: availability APIs only (no warehouse write).
2.8 Loyalty
| Surface |
Role |
| Admin Marketing |
Config, ledger, activities, CRM points adjust, liability KPI; POS earn |
| Mob / Ecom |
GET /loyalty/me, ledger, redeem; referrals (Ecom) |
| Guests |
No earn by default until registered claim |
| Rx/Controlled |
Catalogue auto-excludes loyalty eligibility (Admin) |
| B2B |
Pointer/summary only; retail owns full wallet UI |
3. Auth provider matrix
| Provider |
Admin (staff) |
Mob (customer) |
Ecom (customer) |
B2B (portal) |
Dispatch (rider) |
Doctor |
| Google |
POST /auth/staff/oauth/google (ID token); mock UI |
POST /auth/oauth/google |
OTP-first sheet; Google TBD in older Ecom auth § |
UI mock → demo session; .../oauth/google/start planned |
— |
TBD (Admin Q17) |
| Email |
Password POST /auth/staff/login |
POST /auth/email/login (+ optional register) |
Magic-link sketched |
Magic/OTP planned; demo persona login today |
— |
Email/invite primary (/auth/doctor/login) |
| Phone OTP |
phone/start + phone/verify |
otp/request + otp/verify (primary demo) |
otp/request + otp/verify |
SMS OTP planned |
— |
TBD |
| Telegram |
Login Widget → POST /auth/staff/telegram |
POST /auth/oauth/telegram |
Telegram Mini App POST /telegram/auth sketched |
Widget/Mini App callback planned |
Telegram user id enrollment (identity) |
Not primary |
| Guest |
N/A (staff always auth); guest customers on orders |
POST /auth/guest + guest-codes |
Guest checkout by phone |
N/A (org membership) |
N/A |
Creates guest patients |
| Biometric |
— |
Bind device key (Mob) |
— |
— |
— |
— |
Path naming diverges (/auth/staff/* vs /auth/otp/* vs /v1/auth/*) — consolidation TBD; shared authProvider enum values should stay aligned.
Env (Admin SPA): VITE_GOOGLE_CLIENT_ID, VITE_TELEGRAM_BOT_USERNAME (empty = mock UX). Server-only: bot token, OTP gateway, Google audience.
4. Divergence & sync notes
Accurate as of 2026-08-07 skim. Prefer fixing sheets over inventing a third truth here.
| Topic |
Divergence |
Sync action |
| API base host |
Admin/Mob/Ecom use api.gishen.example; B2B OVERVIEW uses api.gishenpharmacy.org |
Pick one production host |
| Money |
Admin demos major ETB; Ecom sheet says cents optional |
Platform-wide decision (Admin open Q1) |
| Auth path prefixes |
Staff /auth/staff/*, Mob /auth/otp/*, B2B /v1/auth/* |
Shared IdP façade TBD |
| Guest orders |
Admin: staff/doctor customerType=guest; Mob/Ecom: guest session + GSH-XXXX codes |
Document both flows; Admin POS by-code must match Mob code shape |
| Guest Admin endpoints |
Mob lists GET /admin/orders/by-code/:code |
Ensure Admin sheet mirrors when POS wire-up lands |
| Rx dosing |
Admin structured frequency/times; Mob reminders separate resource |
On approve, map Admin times → /health/reminders seed |
| Catalogue ID |
Admin Item / itemId; retail productId / slug |
Mapping table or shared SKU key |
| Multi-UOM |
Admin full uoms[]; Mob/Ecom display unit string only |
Expose sales UOM on catalog DTO when POS/cart need conversion |
| PDP clinical |
Admin stores PDP fields on Item; Mob still derives much from clinical.ts overrides |
Prefer catalogue PDP fields once API live; keep Mob overrides as fallback |
| Loyalty paths |
Aligned idea (/loyalty/me); Admin config under /admin/loyalty/* |
OK |
| Org types |
Admin hospital/clinic for doctors + B2B commercial orgs |
Keep OrganisationType shared |
| Roles naming |
Admin snake staff roles; B2B HR_ADMIN SCREAMING; Ecom older pharmacy_staff names |
Map in backend claims; don't rename UI mid-flight without sheet sync |
| Rider auth |
Dispatch: Telegram enrollment; Ecom older Flutter rider JWT sketch superseded for v1 |
Prefer Dispatch sheet |
| Mini App |
Ecom documents endpoints; Mini App folder empty |
Implement or mark out of scope |
| Doctor in B2B |
Not a B2B portal role today |
Open: doctor realm vs hospital org user |
5. Links to deeper docs
Admin (this repo)
| Doc |
Purpose |
docs/admin-backend-spec.md |
Living Admin API/UI contract (primary depth) |
README.md |
Runbook, demo accounts, deploy |
src/lib/dosingSchedule.ts |
Frequency → default times helpers |
src/config/navigation.ts |
Page registry |
Mob
| Doc |
Purpose |
Gishen-Mob/docs/BACKEND_SPEC.md |
Customer mobile API sheet |
Gishen-Mob/README.md |
Expo run + demo OTP |
| UI anchors |
app/(root)/auth/*, ...(screens)/product/[id].tsx, prescription/*, checkout.tsx |
Ecom
| Doc |
Purpose |
Gishen-Ecom/docs/backend.md |
Storefront + platform API proposal |
Gishen-Ecom/README.md |
Product proposal / demo |
Gishen-Ecom/docs/README.md |
Docs index |
B2B
| Doc |
Purpose |
Gishen-B2B/docs/README.md |
Standing rule + layout |
Gishen-B2B/docs/backend/OVERVIEW.md |
Tenancy, RBAC, clinical withhold |
Gishen-B2B/docs/backend/entities/ · endpoints/ |
Model + REST |
Gishen-B2B/docs/coordination/gishen-admin.md |
Admin ↔ B2B events |
Gishen-B2B/docs/coordination/gishen-ecom.md |
Checkout entitlement split |
Gishen-B2B/docs/coordination/open-items.md |
Cross-repo decisions |
Gishen-B2B/docs/features/INDEX.md |
Feature → pages map |
Related
| Doc |
Purpose |
Gishen-Dispatch-Bot/docs/BACKEND_SPEC.md |
Rider Telegram events / trips |
Gishen-Dispatch-Bot/docs/FEATURE_BRIEF.md |
Acceptance inventory |
6. Cross-cutting open items (rolled up)
Do not invent APIs here — track decisions:
- Unify API host + money units (cents vs major ETB).
- Shared auth façade for Google / Email / Phone / Telegram across actors.
- Guest order claim by phone OTP + PII retention.
- Checkout entitlement-split owner (B2B recommends Ecom + shared calc).
- Doctor IdP (dedicated realm vs hospital B2B user).
- Multi-UOM ownership ERP vs Platform.
- When Rx
times fan out to Mob reminders.
- Telegram Mini App scope vs empty repo.
- Admin ↔ Mob
by-code / POS scan contract end-to-end.
Admin-local list: admin-backend-spec.md § Open questions.
B2B cross-repo: Gishen-B2B/docs/coordination/open-items.md.
Pre-push tooling
Committed in Gishen-Admin only:
| Piece |
Path |
Behavior |
| Cursor rule |
.cursor/rules/update-master-spec-before-push.mdc |
Agents must refresh this master (and Admin sheet if needed) before push |
| Reminder script |
scripts/sync-master-spec-reminder.sh |
Prints Sources checklist + whether master looks stale vs src/ / Admin sheet |
| Git hook |
.githooks/pre-push |
Warns loudly if significant paths changed since last push while master was not updated; does not call LLMs. Soft warn by default (GISHEN_MASTER_SPEC_STRICT=1 to exit 1) |
| Enable hooks |
scripts/setup-githooks.sh |
Sets local core.hooksPath=.githooks for this repo only |
# One-time per clone (optional but recommended)
bash scripts/setup-githooks.sh
# Manual check anytime
bash scripts/sync-master-spec-reminder.sh
Do not silently rewrite global git config. Local core.hooksPath for this repository is intentional and reversible (git config --unset core.hooksPath).