Production-grade monorepo for the chem-lab SaaS.
From the repo root:
pnpm install
pnpm --filter @chem-lab/api devTo start the backing services for the API (Postgres + Redis):
cd apps/api
docker compose up -dCopy the environment template before running the API:
cp apps/api/.env.example apps/api/.envThe API uses AsyncLocalStorage to keep a per-request context with userId,
orgId (aka activeOrgId), and isSystemAdmin. Prisma middleware enforces
tenant isolation for tenant-scoped models (Project, SceneVersion) using that
context.
Security invariants
- Tenant-scoped queries must include an
activeOrgIdin the request context. - Prisma automatically injects
orgIdinto tenantcreateoperations and intowherefilters forfindMany,findFirst,updateMany,deleteMany, andcount. findUnique,update, anddeleteare rejected for tenant models unless a compound key that includesorgIdis provided.isSystemAdminbypasses tenant filtering for administrative workflows.
Setting activeOrgId in session
Set req.session.activeOrgId during authentication or org-switch endpoints,
for example after login or when the user selects an organization. The request
context interceptor reads it into AsyncLocalStorage so Prisma can enforce
scoping.