Policies, not plumbing
Describe who can see and change each row in a small JSON policy — Postgres-style USING and WITH CHECK. Your existing SQL keeps working unchanged.
Declarative policies, per-query user context, and real enforcement — in one small loadable extension that works from any driver.
SQLite has no built-in row-level security. sqlite-rls adds it by turning each protected table into a filtered view plus triggers, driven by the current user's claims that you bind per query:
-- once, at setup:
SELECT rls_protect('{
"table": "documents",
"select": "owner_id = rls_ctx(''user_id'') OR rls_ctx(''role'') = ''admin''",
"insert": "NEW.owner_id = rls_ctx(''user_id'')"
}');
SELECT rls_guard(); -- drop privileges
-- per request:
SELECT rls_set_context('{"user_id": 42, "role": "user"}');
SELECT * FROM documents; -- only user 42's rows come backNo query rewriting, no ORM plugin, no separate policy engine. Just SQL your application was already writing, now scoped to the person making the request.
Head to What is sqlite-rls? for the gentle tour, or jump straight to your language guide.