Follow this guide to get started using Kilpi fast from installation to first protected function.
You can adopt Kilpi incrementally into an existing project.
Kilpi does not require a rewrite of your codebase to start using. Instead, you can test Kilpi out by moving one policy at a time and by protecting one mutation, query, or page at a time. Get started by following this guide.
If you run into issues migrating any existing applications, you are welcome to file a new issue on GitHub.
Install Kilpi
npm install @kilpi/core
yarn add @kilpi/core
pnpm add @kilpi/core
bun add @kilpi/core
Project structure
Create a kilpi
directory (e.g. directly under your /src
folder) with the following file structure.
-
- policies.tsDefine your policies here
- subject.tsDefine your subject here
- kilpi.tsDefine your Kilpi instance here
As your project grows, you may start extracting policies into their own files by domain, using e.g. a policies
directory (below) or feature-based architecture.
-
- organizations.policies.ts
- documents.policies.ts
- media.policies.ts
- subject.ts
- kilpi.ts
You would then import these policies in a policies.ts
file or directly in your kilpi.ts
file.
import { createKilpi } from '@kilpi/core';import { organizationPolicies } from './policies/organizations.policies';import { documentPolicies } from './policies/documents.policies';import { mediaPolicies } from './policies/media.policies';
export const Kilpi = createKilpi({ policies: { organizations: organizationPolicies, documents: documentPolicies, media: mediaPolicies, }, // ...})
Create your subject
Create subject.ts
and create a Subject
type and a getSubject
function to wrap your authentication provider and return the current user (and optionally any other data about the caller for the policies).
This function will automatically be called (and cached) by Kilpi while authorizing.
export type Subject = { id: string, email: string, name: string };
export async function getSubject(): Promise<Subject | null> { const session = await getSession(); // From your auth provider if (!session) return null; return { id: session.id, email: session.email, name: session.name };}
Create your policies
Create policies.ts
where you define all your policies as functions that take in the user
and optionally a resource, and return grant(user)
or deny()
.
import { type Policyset, deny, grant } from "@kilpi/core";import type { Subject } from "./subject";
const policies = { documents: { // All authed users can read documents they own or public documents read(user, document: Document) { if (!user) return deny("Unauthenticated"); if (document.isPublic) return grant(user); if (user.id === document.ownerId) return grant(user); return deny(); }, },} as const satisfies Policyset<Subject | null>
Create your Kilpi instance
Create kilpi.ts
where you create your Kilpi instance from your subject and policies. The Kilpi
object will be used primarily for authorization.
import { createKilpi } from "@kilpi/core";import { getSubject } from "./subject";import { policies } from "./policies";
export const Kilpi = createKilpi({ getSubject, policies,});
Also list any plugins, default behaviours and other configuration here.
Protect your first function
Create a function that you want to protect with Kilpi, using for example the Kilpi.authorize
method. Read more about authorizing.
export async function myFunction() { await Kilpi.authorize("documents:create"); // Your logic here ...}