Break-glass and audit
This page covers the two mechanisms that keep provider access honest: break-glass, the only way platform staff can touch your project's contents, and the audit log, the append-only record your whole team can read.
Break-glass
Platform admins hold no authority over your project's contents — the security overview explains why. When one genuinely needs in (usually to fix something you asked them to fix), they take a break-glass grant: a self-granted, temporary membership with strings deliberately attached.
The mechanics
Every break-glass grant:
- requires a written reason of at least 8 characters, shown to your project's members word for word. The API insists:
a reason is required and is shown to the project's members verbatim - say what you are fixing and, if there is one, name the ticket; - expires on its own — 4 hours by default, 24 hours at most. Work that outlives the ceiling needs a fresh grant with a fresh reason:
a break-glass grant may last at most 24h0m0s - take a fresh one, with a fresh reason, if the work outlives it; - is visible immediately on your IAM & members page, rendered louder than any normal row, with the reason, who took it, and when it expires;
- is written to your audit log as
project.break-glass— a record that outlives the grant; - requires a human credential — machine credentials are refused;
- is only available to a platform admin holding no existing grant on the project. It is an escalation from nothing, never a quiet role upgrade:
break-glass access is for platform admins repairing a project they are not a member of; you already hold a grant here, or you hold none to escalate from.
The grant itself comes back with a note that summarizes the deal:
this grant is visible to the project's members and recorded in its audit log. It expires on its own; remove it sooner with DELETE /v1/projects/<id>/members/<userId>
For the curious, the API call (platform admins only):
curl -s -X POST "$CAI_API/v1/projects/$PROJ/break-glass" \
-H "Authorization: Bearer $TOK" \
-d '{"reason":"debugging stuck builds, ticket OPS-142","minutes":120}'
You should see:
{"grant":{"break_glass":true,"expires_at":"...","reason":"debugging stuck builds, ticket OPS-142","granted_by":"..."},"note":"this grant is visible to the project's members and recorded in its audit log. It expires on its own; remove it sooner with DELETE /v1/projects/<id>/members/<userId>"}
After the grant
- Expiry is automatic. The row stays on the IAM page marked expired — it becomes history, not clutter, so a grant can never be quietly forgotten.
- Early removal is an ordinary member removal, recorded as
project.member.removein the audit log. - Break-glass admins never count toward the "last admin" guard — a temporary provider grant can never become the reason your project appears to have an admin it doesn't really have.
What to do when you see one
Nothing is required — visibility is the feature. But if a break-glass row appears with a reason you don't recognize, ask the person named in granted_by, and remember the reason string was written knowing you would read it.
The audit log
Every project has an append-only audit log: a per-project history of state changes that any member can read — not just admins. It is the other half of the break-glass bargain: provider access is only trustworthy if the record of it is yours.
What one entry looks like
| Field | Meaning |
|---|---|
ts | When it happened |
actor | The email of the user or service account that did it; empty means the platform system itself |
action | A dotted name like agent.deploy (full list below) |
target | What it happened to |
detail | Extra context — for example the role that was granted |
Entries are returned newest first and paged with a cursor. Read it in the console on the Audit log page, or from the API:
curl -s "$CAI_API/v1/projects/$PROJ/audit?page_size=20" \
-H "Authorization: Bearer $TOK"
You should see:
{"entries":[{"ts":"...","actor":"sam@acme.com","action":"project.member.add","target":"dana@acme.com","detail":"..."}],"next_page_token":"..."}
What gets recorded
Every state change through the API. The complete set of actions:
| Family | Actions |
|---|---|
| Agents and functions | agent.deploy, agent.redeploy, agent.delete, agent.config, agent.file.write, agent.file.delete, agent.set-traffic |
| Embed widget | agent.embed.update, agent.embed.rotate-key, agent.embed.delete |
| Membership | project.member.add, project.member.role, project.member.remove, project.member.sa.role, project.member.sa.remove |
| Invitations | project.invite, project.invite.revoke, invitation.accept |
| Break-glass | project.break-glass |
| Project lifecycle | project.create, project.rename, project.delete |
| Secrets | project.secret.write, project.secret.delete, project.secret.reveal, project.secret.issue-token, project.secret.apply, project.secret.bind, project.secret.unbind |
| Credentials | apikey.create, apikey.revoke, serviceaccount.create, serviceaccount.delete, serviceaccount.key.create, serviceaccount.key.revoke |
| MCP servers | mcpserver.create, mcpserver.delete, mcpserver.tool.publish, mcpserver.tool.delete, mcpserver.version.rollback, mcpserver.version.yank, mcpserver.version.unyank |
| Crusoe Cloud integration | project.crusoe-cloud.map, project.crusoe-cloud.unmap, project.crusoe-cloud.bucket.create, project.crusoe-cloud.repository.create |
| Platform administration | org.create, org.delete, org.member.add, org.member.remove, org.member.role, user.create, user.delete, user.role, user.reset-password, valkey-acl.backfill |
Note the quiet standouts: project.secret.reveal means reading a secret's value is itself an audited event, and functions appear under agent.deploy because they share the agent pipeline.
What the log guarantees — and what it doesn't
Guarantees:
- Append-only. There is no API to edit or delete an entry.
- Member-readable. Every member sees the same history, including provider actions.
- Never blocks you. An audit write failure never fails the underlying request.
Honest alpha limits:
- That last guarantee cuts both ways: because audit writes are best-effort, an entry could in principle be missing after an infrastructure failure. The log is a strong record, not yet a cryptographic one.
- No export, no retention controls, no server-side date-range filter yet — you page backward from newest.
- Reads (list/get calls) are not logged; the log records changes, plus the read-like exceptions called out above (
project.secret.reveal,project.secret.issue-token).
Summary checklist
- Platform staff access = break-glass only: reason (≥ 8 chars, shown verbatim), expiry (default 4 h, max 24 h), loud IAM row, audit entry.
- Expired grants stay visible as history; early removal shows as
project.member.remove. - Any member can read the full audit log;
actorempty means the system did it. - Secret reveals are audited; audit writes never fail your request; no export/retention yet (alpha).
Next steps
- Quotas and audit log — the console page for this history
- Security overview — the model that makes break-glass necessary
- API authentication — the credentials all of this is checked against