6 Commits

Author SHA1 Message Date
MiaoRuidx
f1632cc351
fix(run): add run event stream contract (#4342)
* docs: document run event stream contract

* fix(run): address event stream review feedback

---------

Co-authored-by: MiaoRuidx <12540796+MiaoRuidx@users.noreply.github.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-07-23 21:33:57 +08:00
hataa
10890e10a8
feat(authz): propagate trusted authorization principal context (#4203) 2026-07-17 14:49:51 +08:00
黄云龙
4fd521e88e
fix(guardrails): empty allowlist must deny all tools instead of failing open (#4067)
* fix(guardrails): empty allowlist must deny all tools, not fail open

* test(guardrails): empty allowlist blocks all tools (regression)
2026-07-11 18:40:07 +08:00
Miracle778
e5d361876a
feat(guardrails): persist security interventions as run events (#3837)
* feat: record guardrail decisions in run events

Persist security-relevant GuardrailMiddleware outcomes (deny and
provider-error fail-open/fail-closed) as middleware:guardrail run
events via RunJournal.record_middleware(), mirroring
SafetyFinishReasonMiddleware. Recording is best-effort: it reads
__run_journal from the runtime context and swallows persistence
failures, so tool execution behavior is unchanged.

The audit payload records tool name/id, agent id, subagent flag, user
role, allow decision, policy id, reason codes/messages, fail_closed
mode, and provider_error flag. Tool input/args and identity fields
(user_id, oauth_*) are deliberately excluded to avoid persisting the
sensitive content being blocked.

The fail-closed provider-error branch returns the denied message
directly from the except block so it records exactly once and does
not fall through to the generic deny branch.

* docs: clarify guardrail journal runtime boundary

* fix: preserve subagent attribution in guardrail events

* test: align guardrail event attribution fixtures

* refactor(guardrails): resolve runtime context once per tool call

Extract `_resolve_context` and thread the already-resolved context dict
through `_build_request` and `_record_guardrail_event` so the
getattr/runtime.context chain runs once per wrap_tool_call instead of twice.

Also document the `is_subagent` field boundary: native subagents do not
inherit __run_journal, so the field is structurally False in persisted
records today; custom runtimes may still supply it with attribution.

Addresses review feedback on #3837 (context-read-twice cleanup and the
is_subagent trade-off note). No behavior change.
2026-07-03 16:08:41 +08:00
Miracle778
5a699e24a1
feat(guardrails): expose authenticated runtime context in GuardrailRequest (#3665)
* docs: guardrail runtime attribution spec

* docs: guardrail request attribution implementation plan

* feat(guardrails): add runtime user context and attribution fields to GuardrailRequest

Extend GuardrailRequest with optional runtime attribution fields so that
pluggable GuardrailProviders can access authenticated user context and
tool-call-level attribution:

- Gateway injects user_role, oauth_provider, oauth_id into runtime context
  alongside the existing user_id (server-authenticated only, client spoofing
  prevented)
- GuardrailRequest gains: user_id, user_role, oauth_provider, oauth_id,
  run_id, tool_call_id (all optional, backward compatible)
- GuardrailMiddleware reads these from ToolCallRequest.runtime.context
- thread_id now actually populated from context (was always None before)
- Tests: 15 new/expanded tests covering Gateway injection, runtime context
  reading, partial/missing fields, and client spoofing prevention
- Docs: new Runtime Attribution section in GUARDRAILS.md with provider
  example and YAML policy illustration

* fix(guardrails): propagate attribution to subagents

* fix(guardrails): complete subagent attribution propagation

---------

Co-authored-by: Miracle778 <miracle778@no-reply.com>
2026-06-21 16:08:25 +08:00
Uchi Uchibeke
a29134d7c9
feat(guardrails): add pre-tool-call authorization middleware with pluggable providers (#1240)
Add GuardrailMiddleware that evaluates every tool call before execution.
Three provider options: built-in AllowlistProvider (zero deps), OAP passport
providers (open standard), or custom providers loaded by class path.

- GuardrailProvider protocol with GuardrailRequest/Decision dataclasses
- GuardrailMiddleware (AgentMiddleware, position 5 in chain)
- AllowlistProvider for simple deny/allow by tool name
- GuardrailsConfig (Pydantic singleton, loaded from config.yaml)
- 25 tests covering allow/deny, fail-closed/open, async, GraphBubbleUp
- Comprehensive docs at backend/docs/GUARDRAILS.md

Closes #1213

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-03-23 18:07:33 +08:00