Skip to content

Commit 92853f6

Browse files
committed
docs(apl): document HTTP request-line attrs, response: block, and entity-less HTTP authz
Add http.method/path/host/scheme to the extensions and read_headers tables. Document the route/global response: (denyWith) block and the global-policy path that authorizes generic HTTP requests carrying no MCP/A2A entity. Signed-off-by: Frederico Araujo <frederico.araujo@ibm.com>
1 parent 4608522 commit 92853f6

2 files changed

Lines changed: 38 additions & 2 deletions

File tree

docs/content/docs/apl/_index.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,42 @@ For richer conditionals, use the `when` / `do` form, where `do` is a single effe
9494
- "plugin(audit-log)"
9595
```
9696

97+
## Custom denial response
98+
99+
By default a deny surfaces a reason and code, and the host renders its own denial. A route can instead attach a custom HTTP response — status, body, headers — through a `response:` block, a sibling of the route's `apl:` block:
100+
101+
```yaml
102+
routes:
103+
- tool: locked
104+
apl:
105+
policy:
106+
- "require(authenticated)"
107+
response:
108+
status: 403
109+
body: "{\"error\":\"forbidden\"}"
110+
headers:
111+
WWW-Authenticate: "Bearer"
112+
```
113+
114+
All three fields are optional; an absent block leaves the host's default denial unchanged. When the route denies, the status/body/headers are carried on the violation for the host to render on the wire. `response:` is honored at route scope and at `global` scope (below); it is inert — and warns at load time — under `defaults` or a policy bundle. It is scope-local: a `global` `response:` is not inherited by entity routes.
115+
116+
## Authorizing HTTP requests without an entity
117+
118+
Routes key on an MCP / A2A entity — a tool, prompt, resource, or LLM. A generic HTTP request that carries no such entity is authorized by the `global` policy instead: when `global.apl` declares an `args:` or `policy:` block, CPEX evaluates it for these requests, reading the request line (`http.method`, `http.path`, `http.host`, `http.scheme`) and headers. Pair it with a `global` `response:` to return a custom denial.
119+
120+
```yaml
121+
global:
122+
apl:
123+
policy:
124+
- "http.method != 'GET': deny"
125+
response:
126+
status: 405
127+
headers:
128+
Allow: "GET"
129+
```
130+
131+
The host must populate `http.host` from a validated request authority, never a raw client `Host` header, so host-based predicates cannot be spoofed by the caller.
132+
97133
## Field pipelines
98134

99135
`args:` and `result:` map a field to a pipeline of stages separated by `|`. Stages run left to right; a failed validator denies the phase.

docs/content/docs/extensions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Each extension flattens into bag attributes under its namespace, gated by a read
2323
| Agent | session, conversation, turn, and lineage context | `agent.*` | `read_agent` |
2424
| Meta | entity metadata: type, name, tags, scope, properties | `meta.*` | `read_meta` |
2525
| Request | environment, request id, timestamp, trace and span ids | `request.*` | `read_request` |
26-
| HTTP | request and response headers (lowercased) | `http.request_headers.*`, `http.response_headers.*` | `read_headers`, `write_headers` |
26+
| HTTP | request line (method, path, host, scheme) and request/response headers (lowercased) | `http.method`, `http.path`, `http.host`, `http.scheme`, `http.request_headers.*`, `http.response_headers.*` | `read_headers`, `write_headers` |
2727
| LLM | model id, provider, capabilities | `llm.*` | `read_llm` |
2828
| MCP | tool, resource, or prompt metadata | `mcp.*` (`mcp.tool.*`, `mcp.resource.*`, `mcp.prompt.*`) | `read_mcp` |
2929
| Completion | stop reason, token counts, model, latency | `completion.*` | `read_completion` |
@@ -64,7 +64,7 @@ plugins:
6464
| `read_agent` | `agent.*` |
6565
| `read_meta` | `meta.*` |
6666
| `read_request` | `request.*` |
67-
| `read_headers` | `http.request_headers.*`, `http.response_headers.*` |
67+
| `read_headers` | `http.method`, `http.path`, `http.host`, `http.scheme`, `http.request_headers.*`, `http.response_headers.*` |
6868
| `read_llm` | `llm.*` |
6969
| `read_mcp` | `mcp.*` |
7070
| `read_completion` | `completion.*` |

0 commit comments

Comments
 (0)