MODULES / FOUNDATION

Kernel

Free · MITv0.1.1

Shared runtime every module builds on: Supabase clients, session refresh, permissions, the event outbox and the UI kit.

terminalnpx ajolla add kernel

What you get

  • Server and admin Supabase clients
  • Session refresh via proxy.ts (Next 16) or middleware.ts (Next 15)
  • can()/requirePermission() backed by the same SQL check RLS uses
  • Durable event outbox with retries, dispatched after each response
  • Dependency-free UI kit themed with CSS variables, light and dark

Routes it adds

/api/ajolla/events

Plus 2 Supabase migrations with row-level security, and an AGENTS.md your coding agent reads after install.

Configuration

NEXT_PUBLIC_SUPABASE_URL (required)
Supabase project URL.
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY (required)
Supabase publishable (or legacy anon) key.
SUPABASE_SECRET_KEY (required)
Supabase secret (or legacy service_role) key. Server-only; used to dispatch events.
CRON_SECRET (required)
Bearer secret for the /api/ajolla/events retry sweeper cron.
AJOLLA_SIGN_IN_PATH
Where signed-out users are sent (default /sign-in).

AGENTS.md

Read the instructions installed with this module
markdown# Ajolla Kernel

Shared runtime for every Ajolla module. Installed automatically as a dependency.

## What you get
- `lib/ajolla/supabase.ts` — `createAjollaServerClient()` (signed-in user, RLS applies) and `createAjollaAdminClient()` (secret key; server-only, bypasses RLS).
- `lib/ajolla/access.ts` — `getAjollaUser()`, `requireAjollaUser(next?)`, `can(permission, orgId?)`, `requirePermission(permission)`, `getAjollaScope()`.
- `lib/ajolla/session.ts` + `proxy.ts` (Next 16) / `middleware.ts` (Next 15) — refreshes the Supabase session on every request.
- `lib/ajolla/events.ts` — `emitEvent(type, payload)` from server actions and route handlers; dispatched right after the response.
- `lib/ajolla/subscribers/index.ts` — generated by the CLI; lists every installed module's event subscribers. Do not edit.
- `app/api/ajolla/events/route.ts` — retry sweeper for failed event deliveries.
- `components/ajolla/ui` — UI kit (`Page`, `Card`, `Button`, `Field`, `Input`, `Table`, `SubmitButton`…). Restyle every module by overriding the `--aj-*` CSS variables. Dark mode is opt-in: add `class="dark"` or `data-theme="dark"` to `<html>` (next-themes and Tailwind conventions), or `data-ajolla-theme="auto"` to follow the OS setting.

## Setup
1. Fill in the env vars added to `.env.example` (copy them to `.env.local`).
2. Apply migrations: `supabase db push` (or `supabase migration up` locally).
3. Schedule the retry sweeper — `vercel.json`: `{ "crons": [{ "path": "/api/ajolla/events", "schedule": "*/5 * * * *" }] }` (Hobby plans: once a day).
4. If the CLI reported it kept your existing `proxy.ts`/`middleware.ts`, call `updateAjollaSession(request)` from it.

## Permissions
Module screens and RLS policies call `ajolla_has_permission(permission, org_id)`. Until you install Roles & Permissions, admins are users with `app_metadata.role = "admin"`:

```sql
update auth.users set raw_app_meta_data = raw_app_meta_data || '{"role":"admin"}' where email = 'you@example.com';
```
(They must sign in again to refresh their token.)

## Conventions for your own code
- Event types are `<module>.<action>`. Subscribers run at least once — make them idempotent (key on `event.id`).