🚗 KM Livre · Sem Depósito · Seguro Incluso

Admin Access Architecture

Final Production-Ready Model | March 6, 2026

1. Overview

This is the final, production-ready access control architecture for Easy Rent A Car. It replaces all ad-hoc implementations with a clean, deterministic model.

Core Principle

Two-tier access (Platform Admin vs Company Admin), scope-based routing, zero ambiguity.

2. Final Role Model

Platform Roles

  • platform_owner - Highest platform privilege
  • platform_admin - Standard platform admin
  • platform_support - Platform support staff

Company Roles

  • company_owner - Highest company privilege
  • company_admin - Standard company admin
  • fleet_manager - Vehicle operations
  • reservations_manager - Booking management
  • finance_manager - Financial operations
  • support_agent - Customer support

3. Key Entity Changes

User Entity Schema

{
  "platform_role": "platform_owner|platform_admin|platform_support|null",
  "company_id": "string (required if company_role set)",
  "company_role": "company_owner|company_admin|fleet_manager|...|null",
  "status": "active|inactive|pending_activation"
}

Rule: User has EITHER platform_role OR company_role, never both.

UserInvitation Entity Schema

{
  "scope": "platform|company",
  "platform_role": "string (if scope=platform)",
  "company_role": "string (if scope=company)",
  "company_id": "string (if scope=company)",
  "invitation_status": "pending|accepted|expired|cancelled",
  "token": "hashed token (64-char hex)",
  "token_expires_at": "ISO datetime (30 days)"
}

4. Core Auth Functions

// Get user's scope
getUserScope(user) → 'platform' | 'company' | null

// Platform checks
isPlatformAdmin(user) → boolean
hasPlatformRole(user, role) → boolean
hasPlatformRoleOrHigher(user, minRole) → boolean

// Company checks
isCompanyAdmin(user) → boolean
hasCompanyRole(user, role) → boolean
hasCompanyRoleOrHigher(user, minRole) → boolean

5. Login Redirect Rules

  1. User authenticates via Google OAuth
  2. System checks user scope:
    • scope = 'platform' → /admin-super-dashboard
    • scope = 'company' → /admin-dashboard
    • scope = null → /admin-login (denied)

6. Guard Components

AdminGuard

Base authentication check. Ensures user is authenticated + has valid scope.

PlatformAdminGuard

Restricts pages to platform admins only. Check: isPlatformAdmin(user)

CompanyAdminGuard

Restricts pages to company admins. Check: isCompanyAdmin(user) OR (isPlatformAdmin(user) AND impersonatingCompanyId)

7. Sidebar & Branding

Platform Admin Sidebar

  • Icon: 🔒 Lock
  • Title: "Easy Rent A Car Admin"
  • Subtitle: "Platform Admin"
  • Background: Dark gray (bg-gray-950)
  • Menu: Dashboard, Companies, Users, Tenants, Domains, Feature Flags, Import, Maintenance

Company Admin Sidebar

  • Icon: 🚗 Car (or company logo)
  • Title: Company name
  • Subtitle: "Company Admin"
  • Background: Dark blue (bg-slate-900)
  • Menu: Dashboard, Vehicles, Groups, Pricing, Policies, Drivers, Reservations, Finance, Payments

8. Impersonation (Secure)

Flow

  1. Platform admin clicks "Impersonate" on company
  2. Set impersonatingCompanyId in sessionStorage
  3. Show yellow warning banner in sidebar
  4. CompanyAdminGuard allows access
  5. Logout → impersonation ends, audit logged

Security Rules

  • No privilege escalation
  • Tenant isolation enforced
  • Audit trail logged (impersonate_start/end)
  • Session-based (ends on logout)

9. Tenant Isolation (Backend Rules)

All backend queries for company-scoped data MUST filter by company_id:

// WRONG - allows access to any company's data
const vehicles = await base44.entities.Vehicle.list();

// RIGHT - only returns vehicles for user's company
const vehicles = await base44.entities.Vehicle.filter({
  company_id: user.company_id
});

Affected Entities: Vehicle, VehicleGroup, PricingRule, Reservation, DriverProfile, CompanyPolicy, Payment, Payout, Review, etc.

10. Files Changed

✅ Entities

  • entities/User.json - Updated schema
  • entities/UserInvitation.json - Updated schema

✅ Auth & Guards

  • components/admin/AdminAuthContext.jsx - New scope logic
  • components/admin/AdminGuard.jsx - Rewritten
  • components/admin/PlatformAdminGuard.jsx - Rewritten
  • components/admin/CompanyAdminGuard.jsx - Rewritten

✅ Pages & Layout

  • pages/AdminLogin.jsx - Uses getUserScope()
  • pages/AdminRoot.jsx - Uses getUserScope()
  • pages/AdminFallback.jsx - Uses getUserScope()
  • Layout.js - Removed minRole param
  • components/admin/AdminSidebar.jsx - Scope-based branding

11. Production Checklist

  • ✅ User entity migrated to new role model
  • ✅ Existing users migrated or cleanup ready
  • ✅ All guards use deterministic scope logic
  • ✅ All backend functions enforce tenant isolation
  • ✅ All pages use correct guards
  • ✅ Error pages show clear role/scope info
  • ✅ No deprecated role checks in codebase
  • ✅ All pages tested with correct roles
  • ✅ Logout clears impersonation session
  • ✅ Audit logging for impersonation
  • ✅ AdminSidebar shows correct branding
  • ✅ Admin domain routing uses new guards
  • ✅ Invitation model matches new schema

12. Summary

✅ Production-Ready Architecture

  • Clear: Two scopes, predefined roles, zero ambiguity
  • Secure: Tenant isolation, audit logging, no escalation
  • Maintainable: Centralized logic in AdminAuthContext
  • Scalable: Easy to add new roles or pages
  • Testable: Deterministic checks, clear errors
  • User-friendly: Clear UI indicators, helpful messages