EVRION.
Taskhaus — main project image

SaaS · Team Productivity

A multi-tenant team task and project manager built to demonstrate the hard part of SaaS done right: authentication, multi-tenancy, and role-based authorization enforced on the server.

Project
Taskhaus
Year
2026
Discipline
SaaS · Auth & Tenancy
Stack
Next.js · Prisma · Postgres

Context

Taskhaus looks like a team task board — organizations, projects, tasks, roles, invitations — but the board is the easy part. The project exists to show the plumbing underneath it: authentication, multi-tenancy, and authorization that actually holds.

Anyone can draw a Kanban column. The interesting question is whether a user from one organization can reach another organization's data — and here the answer is a hard no, enforced in several independent ways.

Challenge

Multi-tenant authorization is where SaaS products quietly leak. Trust a client-supplied org id, forget a `where` clause, or lean on the UI to hide a button, and you've shipped an IDOR that hands one customer another customer's data.

The goal was a model where authorization is re-derived from the trusted session on every request, and where even a forgotten filter fails closed rather than open.

Approach

Identity comes from a Better Auth session cookie; the active org is resolved from the URL slug only after confirming the user is a member — a non-member gets a 404, so the app won't even admit the org exists. Every mutating action runs a `can(role, action)` check, and every tenant query is org-scoped so a foreign id simply matches zero rows.

Postgres Row-Level Security sits underneath as a database-level backstop: data queries run through a non-superuser role with a transaction-local org id, so even a query that forgot its filter returns nothing across tenants.

Outcome

The result is a working task manager whose real value is its security posture: four layers of tenant isolation — membership checks, permission checks, org-scoped queries, and RLS — each of which independently fails closed.

Better Auth owns only the dangerous primitives (password hashing, sessions, cookies); the organization, membership, role, and permission logic is written by hand and out in the open, which is the entire point.

Technical Detail

Next.js 16 (App Router) + React 19 + TypeScript, PostgreSQL 16 via Prisma 7 on the `@prisma/adapter-pg` driver adapter, Better Auth for primitives, and Tailwind CSS 4. Tenancy, roles, and the `can()` permission layer live in `src/lib/permissions.ts` and `src/lib/tenancy.ts`.

RLS policies in `prisma/sql/rls.sql` filter every row by a transaction-local `app.current_org_id` set through `withTenant()`, and the suite is covered by Vitest.

// Gallery

The kanban board with optimistic create / move
The kanban board with optimistic create / move
Projects across the workspace
Projects across the workspace
Members & role management
Members & role management

// Next step

The next case study could be yours. Tell us what you're building and we'll tell you honestly how we'd ship it.