Quickstart
Ninka is an authorization compiler. You write authorization as a declarative Tegata (手形), compile it to Rego/WASM, and enforce it through a typed check(). This guide takes you from an empty project to your first authorization decision. For the ideas behind it, see Authorization Compiler.
1. Install
npm install ninka-authz
Node.js 20 or later. The package bundles the ninka CLI and the runtime.
2. Scaffold
npx ninka init
Creates the authz/ workspace, a lib/authz.ts boundary, and an AGENTS.md. See the CLI reference.
3. Write a Tegata
One policy per authz/<policy-id>.tegata.json. Start with a single rule:
{
"tegata": "0.1",
"policy": { "id": "invoice-access", "description": "Invoice access" },
"rules": [
{
"id": "allow-employee-view-invoice",
"effect": "allow",
"subject": { "roles": ["employee"] },
"actions": ["view"],
"resource": { "type": "invoice" }
}
]
}
An employee may view an invoice. See Tegata and the Tegata Schema.
4. Compile
npx ninka compile
Runs the Sekisho checks and emits Rego, WASM, and typed TypeScript to authz/out/. See Generated Files.
5. Verify
npx ninka verify
The CI gate: recompiles and requires byte-identity with the committed authz/out/. Run it on every pull request.
6. Enforce in your app
ninka init generated lib/authz.ts. Call check() from your handler:
import { check, policies } from "@/lib/authz";
const allowed = await check(policies.invoiceAccess, {
subject: { properties: { roles: session.user.roles, user_id: session.user.id } },
action: { name: "view" },
resource: { type: "invoice", properties: { amount: invoice.amount, submitted_by: invoice.submittedBy } },
});
if (!allowed) {
return new Response("Forbidden", { status: 403 });
}
check()returns a boolean —trueto proceed,falseto reject.- The policy is named explicitly through the typed
policiestable. - The input shape is enforced by the generated types.
For Ninka.load, decision logs, and options, see the Runtime API.