KasyKasy

Admin Console

Metrics, dev tools, and paywall demos. How to open it, what each tab shows, and how to grant access.

A full-screen console at the /admin route. It serves two audiences: admins (real production data) and developers (debug tools).

Implementation

  1. To open it, tap the version number twice in the Settings footer. In debug, the console also shows up as a direct link in Settings.

  2. To grant someone admin access, set the role = "admin" field in the database, never from the app:

    • Firebase: Firestoreusers collection → the user's document → add role = admin
    • Supabase: Table editor → users table → role column = admin
    • API: your server returns and protects the role field

    To find a user's ID: open the Admin console → Tools → Copy UID, or check the current session in Overview.

    role field set to admin on the user's document in Firestore
    Firestore: user document with the role: 'admin' field added

    role can only be written from the server, never from the app. Any attempt by the client to change role is blocked across all three backends (Firestore rules / Supabase trigger / validation on your server). This is intentional: otherwise any user could make themselves an admin.

Information

Who sees what

Access uses two independent gates:

Debug (kasy run)Production (release build)
Opening the consoleAny devAdmin only
Dev tools (Kit and Tools tabs)YesDon't show up
Real user dataAdmin onlyAdmin only
Paywall/ads demoAdmin (always test)Admin

Summary: debug opens the dev tools; the role field opens the production data.

Available tabs

TabContentRequires admin role?Disappears in release?
OverviewActive backend, current session, request countPartialNo
UsersTable with search, subscriber filter, paginationYesNo
RequestsUser feature requests (moderate, edit text)YesNo
KanbanThe project's own task board (see Kanban), only shows up if the module is onYesNo
KitFeature demos and component galleryNo (dev)Yes
ToolsDev Inspector, paywalls, ads, send push, copy UID/FCM, test onboardingNo (dev)Yes

Remembers the last section (debug only)

In debug, the console reopens on the last tab you visited, so you don't have to navigate back to where you were working every time. In release, it always lands on Overview.

Also in debug, the "Admin" shortcut in Settings opens straight into the Kanban instead of Overview, so it doesn't fire the dashboard queries when all you want is the task board. To make debug behave like production here, set kDebugAdminOpensKanban to false in lib/core/navigation/admin_routes.dart.

How role is protected on each backend

The app's user.isAdmin (which compares role == "admin") only shows or hides UI. Every read of real data is validated again on the server:

BackendBlocking writes to roleHow the admin reads users
FirebaseFirestore rules block any client write to the role fieldThe listUsers Cloud Function checks role == "admin" through the Admin SDK before returning data
SupabaseThe enforce_role_immutable trigger stops anon and authenticated from writing role; only service_role and the dashboard get throughThe admin-list-users Edge Function validates the caller's role from the JWT and only then uses service_role
REST APIYour server returns role and must reject any client attempt to write itA GET /admin/users endpoint that validates role == "admin" and answers 403 otherwise

Last updated on 08/23/2026