Skip to content

Multi-tenant deployment

Ahamie ships L1 + L2 tenant enforcement at v0. The growth path is documented:

LevelMechanismShips in
L1Branded ID types in Drizzle schemav0
L2ORPC + Hono middleware (requireOrg)v0
L3Postgres RLS via Better-Auth claimsv1
L4Schema-per-tenantv2
L5DB-per-tenant (regulated)v3

L1 is automatic — every Drizzle row carries a branded OrgId.

L2 — mount the Hono middleware:

import { Hono } from "hono";
import { createAuth, requireOrg } from "@ahamie/identity";
const auth = createAuth({ db, baseUrl: "http://localhost:3000", secret: process.env.AUTH_SECRET! });
const app = new Hono();
app.use(requireOrg(auth));
app.get("/runs", async (c) => {
const { org_id } = c.get("ahamie_auth");
// every query MUST filter on org_id
});
Terminal window
pnpm exec ahamie doctor

Two-org isolation is also asserted by packages/storage/test/tenancy.test.ts — a row written under org A must not be visible to org B’s session.

  • Do not read from a Drizzle table without filtering on org_id. The L1 brand catches some misuse at compile time, but the runtime contract is yours.
  • Do not share credentials rows across orgs — even if the underlying token would technically work.