KilnDocs
Management

Admin, RBAC and audit

Issue API and MCP tokens with scopes per factory, manage secrets, and read the audit log.

Access to Kiln's API and MCP is controlled by tokens whose scopes are granted per factory, and every change people or Kiln make is written to the audit log.

Tokens

A token belongs to a subject (a person or a service), has a name, a list of grants and an optional lifetime in hours. Kiln shows the token once, when it is issued, and stores only its hash. Tokens can be revoked; a revoked or expired token is refused.

Send it as Authorization: Bearer <token> to the API, and configure it in your MCP client for the Kiln MCP. See the API overview and the MCP reference.

Only server admins and team owners and admins can issue scoped tokens, list them, manage secrets and read the audit log.

Server admins and team admins

Who Audit log Token list GET/PUT /api/v1/secrets Issuing scoped tokens
Server admin: the bootstrap admin token (admin on *), dev auth, or a user listed in KILN_ADMIN_EMAILS Every team Every token The server's secret store Any grants
Team owner or admin Their current team only Tokens of their team and its members The team's raw secrets Only on their team's factories, never *. The token belongs to the team.

Server page

Server admins get a Server item in the sidebar (/admin, API GET /api/v1/admin/server). It shows the host's memory, disk (the data directory and /), load, the Kiln API's own memory, running and queued runs, connected workers, and every sandbox on the host with its state, owner, CPU and memory. It refreshes every 5 seconds. Everyone else gets a 403.

Kiln records the team of each audit entry from what it is about: the factory, work item, run, gate, secret, token, team or user. When a factory moves to another team, its history moves with it.

Token types

Type Grants
scoped The explicit grants it was issued with (POST /api/v1/tokens). The bootstrap admin token is one.
session A login. Grants come from the user's team and factory roles, computed on every request.
personal An API key that acts as its user, like a session.
agent A team service account: read and send on the team's factories.
worker A self-hosted worker. It has no API scopes.

Sessions and personal, agent and worker keys are covered in Teams and users.

Scopes

Each grant pairs one scope with one factory ID, or * for all factories.

Scope Allows
read See factories, definitions, work items, runs, gates, scores, metrics, self-improvement proposals, benchmarks and memories.
send Send work items, post messages, cancel work, pull a task to a local worktree and hand it back, steer, replay, pause, resume and cancel runs, propose memories, and create and plan projects.
decide:spec Approve or reject spec gates.
decide:preview Approve or reject preview gates.
decide:question Answer, approve or reject question gates.
decide:merge Decide merge and custom gates, and confirm a handed-off work item complete without a merge.
definitions:write Apply, sync and connect definitions, promote or roll back canaries, run self-improvement and benchmarks, approve or reject proposals, accept or reject memories, save benchmark tasks, publish and install skills.
admin Everything above on the granted factories, plus tokens, secrets and the audit log when granted on *.

Rules:

  • admin implies every other scope.
  • There are no wildcard scopes such as decide:*. Grant each one you need.
  • A grant for one factory never covers another. Only * covers all.
  • Connecting a new config repo needs definitions:write on *, because the factory does not exist yet.

Grant strings

Grants can be written as a comma-separated string of <scope>:<factory>:

read:*,send:webapp,decide:spec:webapp,decide:preview:webapp

An unknown scope is an error.

Typical tokens

Who Grants
Product owner read:*, send:<factory>, decide:spec:<factory>, decide:preview:<factory>, decide:question:<factory>
Engineer read:*, send:<factory>, decide:question:<factory>, decide:merge:<factory>
Factory engineer read:*, send:<factory>, definitions:write:<factory>
CI validating definitions Any valid token; validation needs no scope. Add definitions:write:<factory> to apply.
Admin admin:*

A product owner's token cannot touch definitions, and a decide:preview token cannot apply definition changes.

Roles map onto scopes

People do not need hand-made grants. Their factory role (User, Editor or Admin) gives them the scopes in Factory roles, and team owners and admins are Admin on every factory in their team. A team-wide check (*), or a factory that does not exist yet, is decided by the team role. Members may read and send. Owners and admins may do everything.

Run tokens are different

Agents never get API tokens. Each run gets its own run token, valid for 60 minutes, that can only push kiln/* branches of the run's repositories, open pull requests, comment and add labels. It can never approve or merge. See Architecture and security.

Secrets

Server admins store named secrets, such as webhook secrets and API keys, in Kiln. (For a team admin, the same endpoints read and write the team's raw secrets.) Listing secrets returns names only; values never leave the server through the API. When a secret is not in the store, Kiln looks for the server environment variable KILN_SECRET_<NAME>. The only plain environment variables Kiln reads as secrets are model-provider keys: CLAUDE_CODE_OAUTH_TOKEN, ANTHROPIC_API_KEY, OPENAI_API_KEY, CODEX_API_KEY, OPENROUTER_API_KEY and GOOGLE_GENERATIVE_AI_API_KEY. This way an agent definition cannot ask for the server's own credentials by name. Listing secrets includes names found in the environment.

These server secrets are the last place Kiln looks. Typed team and personal secrets, which most teams should use, are described in Secrets, MCP servers and environments.

Audit log

Kiln writes an entry with the time, the actor, the action and the target for:

Area Actions
Definitions definition.applied (with SHA, diff and canary share), definition.rejected (with errors), canary.promoted, canary.rolled_back
Work items work_item.created, work_item.cancelled, notify.failed (posting back to a thread or issue, or a notification to a person), transcript.failed
Gates gate.approve, gate.reject, gate.answer, with the surface used
Runs run.steered (with the message), run.cancelled, run.paused, run.resumed
Self-improvement proposal.opened, proposal.approved, proposal.force_approved, proposal.rejected, proposal.empty, proposal.invalid
Accounts user.created, user.password_changed, user.email_changed, user.account_linked, user.account_unlinked, auth.login, auth.login_failed, auth.logout, api_key.created, api_key.revoked
Teams team.created, team.updated, team.avatar_changed, team.settings_changed, team.member_added, team.member_role_changed, team.member_removed, team.invite_created, team.invite_resent, team.invite_revoked, team.invite_accepted
Factory roles factory.team_assigned, factory.member_added, factory.member_role_changed, factory.member_removed
Secrets, MCP servers and environments secret.created, secret.updated, secret.deleted, mcp.created, mcp.updated, mcp.deleted, environment.created, environment.updated, environment.deleted
Skills, memories and routers skill.published, skill.installed, memory.accepted, memory.rejected, router.proposed
Planning and benchmarks project.created, roadmap.created, benchmark.ran
Scoring score.invalid_label
Admin token.issued, secret.set

The audit log returns the newest entries first, 200 by default.

Typed decisions have their own log with inputs, answers, action, provider, fallback and latency. See Typed decisions.

Edit this page on GitHub