# auth — RBAC authorization service

Authorization (not authentication) over HTTP. Version 2.1.0.
Base URL: `https://auth.rodmena.app`

auth answers one question — *may user X do Y* — so services don't reinvent roles
and permissions. It does **not** log anyone in; it trusts you already know who
the user is. Model: `user` → (member of) → `role` → (holds) → `permission`.

## 30-second quickstart

Your **client key is any UUID4** — it is also your private namespace. Generate
one, keep it secret, reuse it for every call. Roles, users and permissions are
created implicitly, but a role must exist before you add members or permissions
to it.

    KEY=$(python3 -c "import uuid; print(uuid.uuid4())")
    BASE=https://auth.rodmena.app
    curl -X POST -H "Authorization: Bearer $KEY" $BASE/api/role/engineers
    curl -X POST -H "Authorization: Bearer $KEY" $BASE/api/permission/engineers/deploy
    curl -X POST -H "Authorization: Bearer $KEY" $BASE/api/membership/alice/engineers
    curl        -H "Authorization: Bearer $KEY" $BASE/api/has_permission/alice/deploy
    # -> {"success": true, "data": {"has_permission": true}, ...}

**The one gotcha to remember:** a write to a missing role returns
`200 {"result": false}`, not a 4xx — check the `result`/`data` field, never just
the status code. The full reference lists three more surprises like it.

**Leaked a key?** `POST /api/keys/rotate` with your current key mints a fresh one
and moves your whole namespace onto it in one shot — capture the returned key, it
is the only copy. See `/docs`.

## Guides

| Path | For |
|---|---|
| `/docs` | the full API reference — every endpoint and exact response shape |
| `/llms.txt` | the same reference as Markdown, for LLM ingestion |
| `/claude` | using auth from Claude Code |
| `/opencode` | *(coming soon)* |
| `/codex` | *(coming soon)* |

`/ping` and `/health` need no auth. Everything under `/api/` needs your
`Authorization: Bearer <uuid4>` header.
