Rekamedika Docs

Multi-tenancy & Access Control

How tenant isolation, OAuth scopes, and RBAC compose on every request.

Rekamedika is one API serving many hospitals (tenants). Isolation is enforced in layers, and none of them can be chosen by the request:

Identity — a verified better-auth session cookie or an OAuth Bearer token. Unauthenticated requests to tenant data fail with 401.

Tenant — read from the authenticated user's row on the server. Every tRPC resolver runs inside a transaction that sets the Postgres RLS GUC app.tenant_id and additionally filters where tenant_id = … (defense in depth). One deliberate exception: a superadmin session may select a tenant with the x-tenant-code header; OAuth Bearer callers are always pinned to their user's tenant regardless of role.

Scope (Bearer callers only) — simrs:read for reads, simrs:write for writes. Missing scope ⇒ 403.

RBAC — mutations require one of the roles the domain declares (requireRoles), read from the server-side user_roles table. A broad OAuth scope never widens roles.

OAuth scopes

ScopeMeaning
openid · profile · emailOIDC identity claims
offline_accessRefresh tokens
simrs:readtRPC queries, SATUSEHAT GETs, read MCP tools
simrs:writetRPC mutations, SATUSEHAT POST/PATCH, write MCP tools

What this means for examples

All examples in these docs use placeholders (YOUR_ACCESS_TOKEN, you@your-hospital.example) — there is no demo tenant credential, and no real tenant data ever appears in generated pages.

Is this page helpful?

On this page