For the complete documentation index, see llms.txt. Prefer markdown by appending .md to documentation URLs or sending Accept: text/markdown.

API trust

Hide buttons for UX, but enforce every mutation on the Hono API. Never authorize from a client-supplied organization id alone.

Access control has two jobs:

  1. Prove who the caller is (authentication)
  2. Prove what they are allowed to do (authorization)

On mobile, (1) starts with the Better Auth session on the device. (2) must still happen on the API. Hiding a menu item in React Native is not enough.

Call protected routes

The Expo app uses the shared Hono client with the user session. Sensitive reads and all mutations should hit routes guarded by enforceAuth (and permission middleware when needed).

// After the user is signed in on device
const { data } = await handle(api.billing.summary.$get)({
  query: { referenceId: user.id },
});

If a screen is “private”, still assume a modified client can call the endpoint directly. The server decides.

See Protected routes and Web access control for middleware details.

Client RBAC is UX only

Organization helpers like hasPermission / checkRolePermission on the auth client are useful to disable buttons and hide screens.

They are NOT a security boundary. Repeat the same checks in the API with enforceOrganizationPermission or enforceMembership.

Organizations RBAC

Roles and client-side permission helpers.

Multi-tenant isolation

Never authorize from a client-provided organizationId alone. Send the id if the API needs it, but the server must verify membership for the authenticated user before scoping queries.

When you add features (projects, documents, …):

  1. Authenticate the request (enforceAuth)
  2. Confirm membership / permission for that organization
  3. Filter every query by the verified tenant id

Feature and plan gates

Plan-based UI (paywalls, locked screens) should match server enforcement - feature middleware or entitlement checks on the API. See the feature-based access recipe.

Practical rules

  • Do not embed admin-only logic that only runs on the device
  • Do not trust boolean flags stored only in AsyncStorage / SecureStore as proof of entitlement
  • Do not pass secret API keys into the mobile client “to make a shortcut”
  • Do log auth failures and 401/403 spikes in monitoring so abuse is visible

How is this guide?

Last updated on

On this page

Ship your startup everywhere. In minutes.Try TurboStarter