# @leumas/auth

The ONE Leumas gate — clean-room login + JWT session + RBAC (roles/permissions) + Stripe membership + PassNode token wallet + API keys.


The **one gate** every Leumas resource routes through. Clean-room (does not port the legacy login) but
reproduces its shapes + security. Server-side; built on [`@leumas/db`](../db) + [`@leumas/schemas`](../schemas).

## Surface

| Group | Endpoints |
|---|---|
| **Auth** | `POST /auth/signup` · `POST /auth/verify` · `POST /auth/login` · `POST /auth/logout` · `GET /auth/session` · `GET /auth/me` |
| **Membership** (Stripe) | `GET /membership/plans` · `GET /membership` · `POST /membership/checkout` · `/portal` · `/cancel` · `/grant` (admin) · `POST /membership/webhook` |
| **Tokens** (PassNode) | `GET /tokens/balance` · `POST /tokens/spend` · `GET /tokens/history` · `POST /tokens/grant` (admin) |
| **API keys** | `POST /keys` (developer) · `GET /keys` · `DELETE /keys/:id` · `POST /keys/verify` |

## Guards ("protect when necessary")

```js
import { requireAuth, requireRole, requirePermission, requireMembership, requireDeveloper } from '@leumas/auth';
router.post('/admin-thing', requireRole('admin'), handler);
router.post('/paid-thing', requirePermission('run_adapter'), handler);
```

Ownership guards (`canRead`/`canWrite`/`canClone`) live in `@leumas/db` and are applied inside handlers.

## Mount

```js
import express from 'express';
import { mountAuth } from '@leumas/auth';
const app = express();
// skip json parsing for the Stripe webhook (it needs the raw body):
app.use((req, res, next) => req.path === '/membership/webhook' ? next() : express.json()(req, res, next));
mountAuth(app);   // attaches req.user + mounts /auth /membership /tokens /keys
```

## Config (env)

`JWT_SECRET`, `LEUMAS_COOKIE_NAME`/`_DOMAIN`, `AUTH_AUTO_VERIFY` (dev), `LEUMAS_APIKEY_PEPPER`,
`STRIPE_SECRET_KEY`/`STRIPE_WEBHOOK_SECRET`, `STRIPE_PRICE_{STARTER,PRO,UNLIMITED}`, `SEED_ADMIN_*`.
Sensible dev defaults keep P1 runnable offline; Stripe endpoints return 501 until configured, while
`/membership/grant` + `/tokens/grant` give an offline path for testing entitlements.


---
Source: shared/packages/auth/README.md
Canonical: https://docs.leumas.tech/p/packages/auth
