Just-in-time (JIT) access replaces standing privilege with access that a person switches on for a limited time, with a reason, a fresh second factor and, where you require it, someone else's approval. The console page is Access > JIT and break-glass.
Make a role eligible
Create a binding with state: "eligible" instead of active. Eligible bindings are held by users (an activation on a group binding would unlock the role for every member).
curl -sS -X POST "$KEYSTONE_URL/api/v1/access/bindings" \
-H "Authorization: Bearer $ADMIN_TOKEN" -H 'Content-Type: application/json' \
-d '{"node_id": "'$PROJECT_NODE'", "principal_type": "user", "principal_id": "'$USER_ID'",
"role_id": "'$ROLE_ID'", "state": "eligible", "requires_approval": true,
"max_activation_minutes": 120, "description": "Production deploys"}'
| Field | Meaning |
|---|---|
requires_approval | The activation waits for an approver |
max_activation_minutes | 1 to 10080, bounded by the organisation's jit_max_minutes |
break_glass | Marks an emergency binding (below) |
The escalation guard applies as for any binding; see Roles and permissions.
Activate
The person sees what they can activate with GET /api/v1/access/me/eligibility, and activates with:
curl -sS -X POST "$KEYSTONE_URL/api/v1/access/activations" \
-H "Authorization: Bearer $USER_TOKEN" -H 'Content-Type: application/json' \
-d '{"binding_id": "'$BINDING_ID'", "justification": "Hotfix for incident 2026-114",
"minutes": 60, "mfa_code": "123456"}'
justificationis 10 to 2000 characters.mfa_codeis a fresh TOTP code.- The person needs
iam.activations:requeston the binding's node. Every resource role holds it. - The answer is
active, orpending_approvalwhen the binding requires approval.
Activations end on their own at the end of their duration. The holder, or someone with iam.activations:approve on the node, can end one early with POST /api/v1/access/activations/{id}/end.
Approve
A pending activation appears in the approvals inbox with source access_activation. Only someone who holds iam.activations:approve on the node and is not the requester can approve it. Pending activations are settled every 30 seconds from the approval decision. The organisation's approval_timeout_minutes setting bounds how long approval is awaited. See Approvals.
Break-glass
A binding with break_glass: true is eligible only. Activating it:
- skips approval, but still needs a justification and a fresh second factor;
- is capped by the organisation's
break_glass_max_minutes; - raises an alert: an audit record marked for alerting and the organisation webhook event
access.breakglass.activated; - opens a mandatory post-use review that someone other than the user completes.
The review is POST /api/v1/access/activations/{id}/review with {"outcome": "appropriate" | "inappropriate", "notes": "..."} after the activation has ended. It needs iam.breakglass:review on the node. Reading break-glass activations of others needs iam.breakglass:read.
Break-glass for signing in while SSO is required is a different feature; see Domains and SSO enforcement.
Temporary authority stays temporary
Authority that comes from an activation can create only bindings that expire no later than the activation, cannot share resources, revoke shares or decide resource access requests, and never counts for Owner-reserved actions. An activation cannot be turned into standing access.
Activation routes
| Route | Who |
|---|---|
GET /api/v1/access/activations | Own activations; anyone's with iam.activations:read (and iam.breakglass:read for break-glass) on the organisation node |
POST /api/v1/access/activations | The holder of the eligible binding |
GET /api/v1/access/activations/{id} | Own, or iam.activations:read on the node |
POST /api/v1/access/activations/{id}/end | The holder, or iam.activations:approve on the node |
POST /api/v1/access/activations/{id}/review | iam.breakglass:review on the node, not the person who activated |
GET /api/v1/access/me/eligibility | Signed in, own only |
Resource access requests
A person who lacks access to one object (a project, a model connection, an MCP server and the other shareable types) can ask for a level on it:
| Route | Who |
|---|---|
POST /api/v1/access/resources/{type}/{id}/requests | Anyone signed in: ask for a level with a reason; one open request per person and object |
GET /api/v1/access/resources/{type}/{id}/requests | Managers of the object |
POST /api/v1/access/resource-requests/{id}/approve, /deny | A Manager of the object who is not the requester (403 self_approval otherwise) |
POST /api/v1/access/resource-requests/{id}/withdraw | The requester |
GET /api/v1/access/me/resource-requests | The caller's own requests |
Approval grants the level in the same transaction. Requests and decisions are audited (access.request.approved or denied) and send the webhook event access.request.created. A request for an object that does not exist is filed like any other and denied by the scheduler, so requests cannot be used to probe for objects.
Self-service requests for IDE and tool access (/api/v1/me/access-requests) are a separate, partial feature: an approval is recorded but grants nothing on the device yet.
Compliance overrides
Access > Compliance overrides lists compliance break-glass overrides (/api/v1/compliance/break-glass, compliance:read to read and compliance:manage to create or remove).