Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/core/mcp.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -102,7 +102,7 @@ happens rather than what the specs allow.
| Any client that needs to self-register | yes | Enable `--enable-client-id-metadata-document` (preferred) or `--enable-dynamic-client-registration` (RFC 7591, for clients that predate CIMD) |

Both self-registration mechanisms ship in 2.4.0 and are **off by default**. Turn
on the one your client can use — see [Self-registering clients](#self-registering-clients)
on the one your client can use — see [Self-registering clients](#self-registering-clients-cimd-vs-dcr)
below. The static-token path remains the simplest option when you control the
client and do not want an interactive flow at all.

Expand Down
5 changes: 4 additions & 1 deletion docs/core/metrics-monitoring.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -170,7 +170,10 @@ The `outcome` label is what makes an intersection denial diagnosable:
This is the Confused Deputy being stopped. Do **not** widen the agent; it
cannot help, and the user genuinely lacks access.
- **`not_enforced`** — a delegated caller arrived but the active model declares
no `agent` type, so the request was authorized as the **user alone**.
no `agent` type, so the agent half of the intersection could not be evaluated.
By default the check is **denied**; with `--fga-allow-unconstrained-agents`
set it is authorized as the **delegating user alone**, with the agent
unconstrained.

Only `check_permissions` emits `allowed` / `denied_by_agent` / `denied_by_user`.
`list_permissions` intersects object *sets* rather than folding a per-check
Expand Down
16 changes: 14 additions & 2 deletions docs/enterprise/agent-identity.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -222,9 +222,21 @@ Without this an agent's actions are indistinguishable from the user's own — sa
| `allowed` | both halves permitted | — |
| `denied_by_agent` | the agent has no grant; the user may well have access | grant the **agent** a tuple |
| `denied_by_user` | the agent had its grant, the user does not have access | **do not** widen the agent — this is the Confused Deputy case working as intended |
| `not_enforced` | a delegated caller arrived but the model declares no `agent` type, so it was authorized as the **user alone** | declare `type agent` and grant your agents |
| `not_enforced` | a delegated caller arrived but the model declares no `agent` type, so the agent half could not be evaluated | declare `type agent` and grant your agents |

`not_enforced` is the one to alert on: it is the only outcome that reports a security property *not* being enforced, and it is silent by construction — the request succeeds and nothing in the response says the agent was unconstrained.
`not_enforced` is the one to alert on, and it means one of two things depending
on [`--fga-allow-unconstrained-agents`](#turning-it-on):

- **Default (flag unset):** the check was **denied**. Agents are failing against
a model that cannot express agent grants — a misconfiguration, not an attack.
Users will report it as a broken integration; this counter tells you why.
- **Flag set:** the check was authorized as the **delegating user alone**, with
the agent unconstrained. That is silent by construction — the request
succeeds and nothing in the response says so. Treat a non-zero rate here as
exposure with a clock on it, not a steady state.

Either way the remedy is the same: add `type agent` to the model and grant the
agents.

`allowed`, `denied_by_agent` and `denied_by_user` are emitted by
**`check_permissions` only**. `list_permissions` intersects object *sets*
Expand Down