fix(19.7): RA-WR-01 never wait on a session lock under the router lock

Fan-out matching snapshots the sessions (and stateless entries) under the
router-wide lock, releases it, and reads each identity through a small
identity box that is never held across I/O, so an event no longer waits on
a session that is re-filtering while it holds sr.mu or sp.mu.

Widening and the fan-out recomputes run their guard checks with
guardContext: not cancelled with the triggering request, but bounded by
mcp.call_timeout, so a provider that never answers cannot hold a session
lock forever. README and docs/services/mcp.md describe the wider meaning of
mcp.call_timeout.

TestLockScopeUnderWidening blocks a widening guard check, fires a
permission event for that session and asserts that another session's call
still finishes, and that a never-answering check ends at call_timeout.
This commit is contained in:
2026-10-23 20:02:13 +02:00
parent f53668a3e8
commit cccf4025ea
7 changed files with 198 additions and 28 deletions

View File

@@ -39,7 +39,7 @@ path: /mcp
| `mcp.resource` | `app.url` + `mcp.path` | The resource indicator; must equal the OAuth server's MCP resource. |
| `mcp.throttle` | `120,1` | The endpoint's rate limit, `<max>,<minutes>`. |
| `mcp.allowed_origins` | the origin of `app.url` | Browser origins allowed to call the endpoint; another `Origin` is refused with 403. |
| `mcp.call_timeout` | `30s` | Bound on one tool call. |
| `mcp.call_timeout` | `30s` | Bound on one tool call, and on the guard checks that re-filter a session when its grant or permissions change. |
| `mcp.max_result_bytes` | `1048576` | Cap on a route answer returned as a tool result. |
## Declaring tools and prompts