Skip to content

Tenant isolation and access

Heysen is multi-tenant by construction. Tenants share a platform — the same servers, the same database, the same code — and never share data.

Every tenant-scoped read and write is filtered by tenant. This is not a convenience applied to the interesting queries; it is a structural rule, and changes that touch data access are reviewed for it specifically.

Consequences you can rely on:

  • An agent’s app shows only the tenant that agent belongs to.
  • The same username in two tenants is two accounts with two independent sets of records.
  • A platform operator’s wider access is a separate, deliberate grant — not a side effect of using the same login page.
  • Historical and source-replica data is scoped the same way as live data. Reading versions does not widen the scope.
Public (no sign-in) Authenticated
This documentation site and the blog SaaS Admin and Platform Admin
The marketing site The agent app and member app
Static assets and feed metadata Any data about agents, clients, policies, or commissions

The backend splits its routes along the same line:

  • /admin-api/* — back-office surfaces.
  • /app-api/* — the agent and member app.
  • /app-api/ws/im — the real-time messaging channel used by the app.

Every response uses one envelope — code, msg, data — with code: 0 for success, 401 for “not signed in”, and non-zero codes carrying a readable message for everything else.

Sign-in produces a token that identifies the session and the tenant it belongs to. Two properties matter in daily use:

  • Signing in again elsewhere does not silently inherit the previous identity. Finish with a device by signing out; do not hand a device over with a session open.
  • A session’s reach is the account’s reach. An agent session cannot read another agent’s commission, and an operator session does not become an agency session because both use the same login page.

What the platform deliberately will not do

Section titled “What the platform deliberately will not do”
  • It will not guess an attribution. An unconfirmed policy-to-agent relation is shown as pending rather than assigned to a likely candidate.
  • It will not substitute a zero for an unknown. A missing value stays missing; collapsing it to 0 would be a silent, confident-looking error.
  • It will not present stale data as current. A delivery outside its validity window is labelled delayed. The platform would rather say “I do not know” than be quietly wrong.

Those three refusals are the same principle applied in three places: the platform’s job is to be trustworthy about what it knows, including the edges of what it knows.

Per-tenant switches, data-source health, and reconciliation results are covered in The daily feed, versioning, and freshness and Tenant settings that change behaviour. The engineering rationale behind a few of these rules is written up on the blog — see Versioned source data and What a reconciliation gate protects.