RowGate is a lightweight, framework-agnostic Row-Level Security (RLS) engine for TypeScript applications. It lets you define policies in your application code and automatically enforces them on all database queries - select, insert, update, and delete.
RowGate is inspired by the safety of Postgres RLS, but built to be portable across different databases, ORMs, and query builders.
- Universal RLS - works with any database or query system via adapters.
- Type-safe policies - enforced at runtime, defined in TypeScript.
- Composable and declarative - policies are simple objects describing filters and checks.
- Context-aware - each request can carry its own auth/user context.
- Adapter-based architecture - easy to add support for additional ORMs/DB layers.
pnpm add @rowgate/coreAdapters are installed separately:
pnpm add @rowgate/kyselyYou can also install the adapter directly - they have @rowgate/core as a dependency.
RowGate wraps your database client using a small higher-order function:
import { withRowgate } from "@rowgate/core";
const db = withRowgate({
context: z.string(), // your user context type
adapter: yourAdapter, // any supported adapter
policy: {
// table policies
},
});const db = withRowgate({
context: z.object({ userId: z.string() }),
adapter: someAdapter(rawDb),
policy: (ctx) => ({
Post: {
select: { filter: (qb) => qb.where("authorId", "=", ctx.userId) },
insert: { check: (row) => row.authorId === ctx.userId },
update: {
filter: (qb) => qb.where("authorId", "=", ctx.userId),
check: (row) => row.authorId === ctx.userId,
},
delete: { filter: (qb) => qb.where("authorId", "=", ctx.userId) },
},
}),
});- Kysely -
@rowgate/kysely
Status: ✅ Stable
- Prisma -
@rowgate/prisma
Status: 🚧 Work in progress; API may change
MIT - see LICENSE for details.