Skip to content

docs: Plugin architecture proposal#342

Draft
huang195 wants to merge 3 commits intokagenti:mainfrom
huang195:docs/plugin-architecture
Draft

docs: Plugin architecture proposal#342
huang195 wants to merge 3 commits intokagenti:mainfrom
huang195:docs/plugin-architecture

Conversation

@huang195
Copy link
Copy Markdown
Contributor

@huang195 huang195 commented Apr 22, 2026

Summary

Adds docs/plugin-architecture.md — a design proposal for an extensible plugin pipeline in AuthBridge.

Key design decisions

  • One interface: Plugin with OnRequest(ctx) / OnResponse(ctx) — no layered abstractions
  • Identity-first context: every plugin receives AgentIdentity (SPIFFE ID + client_id) alongside caller Claims — security decisions no external proxy can make
  • Mutations on context: plugins modify ctx.Headers / ctx.Body directly, return Continue or Reject
  • Mode-agnostic: thin adapter per deployment mode converts to/from shared Context (formalizes existing adapter pattern)
  • Tighten-only enforcement: built-in plugins cannot be removed; claims are read-only to custom plugins; protected registry prevents name collisions
  • Body access as hard constraint: ext_authz (waypoint) can never provide body; ext_proc requires explicit Envoy config; proxy has full access. Validated at startup.
  • Protocol parsing as a plugin: MCP/A2A parsing populates ctx.Values, enabling tool-level authorization via composition
  • Observability by default: pipeline auto-instruments every plugin with OTel spans and metrics
  • Registry loading (v1): compiled-in via Go import + init() registration
  • Praxis alignment: three concrete integration models (A/B/C) with Phase 1 recommendation

What changed in v2

  • Clarity: grounded in actual codebase — shows real Auth struct, real listener code, real migration seams
  • Plugin terminology: renamed "filter" to "plugin" throughout. AuthBridge extensions are identity-aware security plugins, not generic stream filters
  • Innovation: identity-aware context, tighten-only enforcement mechanisms, auto-observability, tool-level authorization composition, concrete Praxis integration models

Discussion points

  • Body buffering budget for LLM prompts and SSE streaming
  • ext_proc body auto-configuration via operator
  • Multi-turn agent session context
  • Plugin interface versioning strategy
  • Praxis integration timeline

Assisted-By: Claude (Anthropic AI) noreply@anthropic.com

Proposes an extensible filter pipeline for AuthBridge with:
- Single Filter interface (OnRequest/OnResponse on shared Context)
- Mutations directly on context (headers, body, values)
- Mode-agnostic pipeline with thin adapters per deployment mode
- Registry-based compiled-in plugin loading (v1)
- Protocol parsing as a composable filter (not a special layer)
- Tighten-only policy (plugins cannot weaken built-in security)
- Praxis alignment for potential collaboration

Signed-off-by: Hai Huang <hai@us.ibm.com>
Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Hai Huang <huang195@gmail.com>
- Rename "filter" to "plugin" throughout — AuthBridge extensions are
  security-aware plugins, not generic stream filters
- Add "Current Architecture" section grounding the proposal in actual
  codebase (Auth struct, existing adapter pattern, func type precedent)
- Add AgentIdentity to Context — dual SPIFFE/OAuth identity gives plugins
  security context no external proxy can provide
- Add ResolvedRoute to Context for destination-aware policy decisions
- Add "Tighten-Only Enforcement" section with concrete mechanisms
  (required plugins, protected registry, read-only claims)
- Add "Observability by Default" section — auto-instrumented spans and
  metrics per plugin invocation
- Add "Identity-Aware Protocol Policy" showing tool-level authorization
  via MCP parser + tool-policy plugin composition
- Add concrete Praxis integration models (A/B/C) with recommendation
- Sharpen migration path with real before/after code from ext_proc listener
  and mapping table from existing Auth fields to built-in plugins
- Clarify body access as hard mode constraint (ext_authz: never, ext_proc:
  requires BUFFERED config, proxy: always)
- Add WASM to future loading mechanisms, multi-turn sessions to open
  questions

Signed-off-by: Hai Huang <huang195@gmail.com>
Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Hai Huang <huang195@gmail.com>
- Remove "Observability by Default" section — too prescriptive about
  implementation details for an architecture proposal
- Make AgentIdentity generic: WorkloadID + TrustDomain instead of
  SPIFFEID. Works with SPIFFE, k8s SA, or any workload identity scheme.
- Reframe Praxis section: position as Envoy replacement where AuthBridge
  benefits indirectly (universal body access, pre-parsed protocol
  metadata, simpler adapter layer) rather than peer integration models
- Update tool-policy example to use trust_domain instead of SPIFFE pattern

Signed-off-by: Hai Huang <huang195@gmail.com>
Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Hai Huang <huang195@gmail.com>
@imolloy
Copy link
Copy Markdown

imolloy commented Apr 24, 2026

This is a great start, and something that I think we can help build on a deliver. Many of the requirements listed here are things we've worked through with CPEX, and learned what works well and what doesn't work. Here is what I would suggest at a high level, and then I'll give a few more comments. Let us write up a proposal / spec for how to deliver CPEX to provide the plugin capabilities for AuthBridge and share it early next week. This will mirror what we already did for Praxis and Mellea and ContextForge. Given the rewrite in Rust, we can support AuthBridge / Go using Rust + C ABI + Go (cgo).

Some things we can then work through are the placement of the hooks (ingress and egress, return response, etc.) and things like the payload and how to configure it. For things like the Context object, the Common Message Format and extensions have gone evolved from our original work and will allow for much more robust plugin systems, while also allowing us to build a strong capability model to prevent overwriting sensitive data, provide the tighten-only semantics, copy-on-write, etc.

The other thing this will provide is robust prioritized, parallel, and sequential pipelines with varying semantics (fail on error, fire-and-forget, async versus blocking, etc.). This is all stuff you'll get for free. Let's see how we can provide these capabilities for automatically.


Smaller, comments:

  • AgentIdentity : Need to see how this will encode delegation chains
  • Claims : would like to see what this looks like. Just scopes? RAR? etc.
  • Values map[string]any : We've done things like this in the past and found it causes issues (similar Authzen). The CMF and extensions are our solution.
  • Need to designate which plugins can and cannot mutate, which can affect the order and parallel execution
  • token-exchange : this should always be the last item in the pipeline
  • read-only claims: Need to see how this gets enforced in Go. Rust will provide strong separation.
  • Plugin Loading: if we use CPEX, you only need to initiate the library and register the hooks. All plugin loading, configuration, scheduling, etc. will be taken care of, which helps keeps the AuthBridge code base smaller.
  • Identity-Aware Protocol Policy : Check out APL, but why not use a policy language here like Cedar for more robust policies?

@huang195
Copy link
Copy Markdown
Contributor Author

Thanks Ian — this is really helpful feedback, and the timing is great. A few responses:

Values map[string]any — You're right, and the AuthZEN parallel is exactly the concern. We're thinking about replacing Values with typed extension slots — one struct per protocol domain (MCP, A2A, Security, etc.) with plugins declaring what they read and write. The pipeline would validate wiring at startup so mismatches are caught before any request arrives. This is directly inspired by CMF's typed-slot + capability model.

Policy language — Great point about moving beyond custom YAML rules. Since we're already in the Kuadrant ecosystem (MCP Gateway uses Kuadrant), one option we're exploring is integrating with Authorino for policy evaluation. AuthBridge's role would be enriching the authorization context with protocol-level data (tool name, arguments, method) that Authorino can't extract on its own, then delegating the policy decision via ext_authz. This would give us OPA/Rego, pattern-matching, and SpiceDB support through existing infrastructure.

Plugin interface and CPEX integration — Our current thinking is to keep the initial pipeline implementation in Go to match the rest of the AuthBridge codebase and keep the build simple. That said, we want to design the Plugin interface to be open:

type Plugin interface {
    Name() string
    Capabilities() PluginCapabilities
    OnRequest(ctx *Context) Action
    OnResponse(ctx *Context) Action
}

If CPEX provides a bridge implementation behind this interface — bringing the Rust runtime, scheduling, and CMF — that would work well. The interface is the contract, and CPEX would be a first-class way to implement it. This is similar to how CPEX adapts to Praxis and Mellea's extension models. We'd love to see how this could look concretely.

Other points:

  • AgentIdentity + delegation chains — agreed, will address in the next revision
  • Claims — currently carries scopes, subject, issuer, audience, client_id. We should discuss whether RAR belongs here
  • token-exchange ordering — good catch, will enforce as last in the outbound chain
  • Read-only claims enforcement — startup validation + unexported setter, but open to hearing how the Rust approach works

Would love to see the CPEX spec for AuthBridge when it's ready next week. Having a concrete proposal to compare against will help us find the right integration points.

@araujof
Copy link
Copy Markdown

araujof commented Apr 28, 2026

@huang195 Thanks for sharing the initial proposal!

Building on your draft and @imolloy's feedback on CPEX integration, I put together a concrete spec that wires CPEX into AuthBridge as the hook system and plugin runtime:

https://github.com/araujof/kagenti-extensions/blob/docs/authbridge_hook_system/docs/proposals/authbridge-hooks.md

In short, the spec defines typed hooks across the AuthBridge lifecycle (startup, inbound JWT validation, outbound token exchange, and cross-cutting audit), with CPEX embedded in-process via Go bindings to the Rust core. Plugins declare capabilities that gate which Extensions they can access (Security, Http, Delegation, etc.), and all policy results compose through a tighten-only monoid; plugins can deny but never override a deny to allow. It also addresses several points from the discussion: typed extension slots instead of map[string]any, capability-gated token and header access, delegation chain support in outbound hooks, and body access as a mode-validated opt-in.

I'd be happy to team up and refine it to cover any missing requirements, adjust scope, and incorporate feedback from others.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

4 participants