- 1) Goal & Preconditions
- 2) User Flow
- 3) Functional Requirements
- 4) Non‑Functional Requirements
- 5) Data & Validation Cheatsheet
- 6) API Stubs
- 7) UX Copy & Errors (EN/AR)
- 8) Edge Cases
- 9) Acceptance Criteria
- 10) Analytics (events)
Date: 31‑Aug‑2025
Goal. Enable Super Admin to manage Admin accounts (distinct from Tenant Admins).
super_admin, admin_super, admin_normal, tenant_admin, tenant_user.Flow: Create → Invite → Accept (password+phone) → OTP verified → Assign customers/platforms → Active States: pending_invite → accepted → phone_verified
name, email (unique), role = super_admin | normal_admin.Email + in‑app popup when new customer assigned.
Normal Admin sees BoQ, Assets, Devices, Dashboard, Alerts, Pricing, Facilities for assigned customers only.
Admin { adminId, name, email, role(super_admin|normal_admin), assignedPlatforms[], assignedCustomers[], status }
Status: pending_invite → accepted → phone_verified
Validation: email unique; role immutable post‑creation; assignedCustomers[] can be empty (see empty state)
POST /v1/superadmin/admins
{ name, email, role:"normal_admin"|"super_admin", platforms:["pl_1"], customers:["ten_1","ten_2"] }
GET /v1/superadmin/admins
→ 200 { items:[{ adminId, name, email, role, status, assignedCustomersCount, assignedPlatformsCount }] }
PATCH /v1/superadmin/admins/{id}/assign
{ customers:["ten_1","ten_3"], platforms?:["pl_1","pl_3"] }
GET /v1/superadmin/admins/{id}/status
→ 200 { accepted:true, phoneVerified:true }
POST /v1/auth/admin-invite/accept
{ token:"invite_123", password:"Strong!123", phone:"+971..." }
admin_created { adminId, role, createdBy }
admin_invite_sent { adminId, email }
admin_invite_accepted { adminId, verified }
admin_customer_assigned { adminId, customerId }
admin_login { adminId, role }