Skip to content

feat(authorization): light up IResourceSecurityContext<TResource> in Mediator dispatch#98

Merged
MarcelRoozekrans merged 6 commits into
mainfrom
feat/mediator-authorization-resource-context
May 23, 2026
Merged

feat(authorization): light up IResourceSecurityContext<TResource> in Mediator dispatch#98
MarcelRoozekrans merged 6 commits into
mainfrom
feat/mediator-authorization-resource-context

Conversation

@MarcelRoozekrans

Copy link
Copy Markdown
Collaborator

Summary

Lights up the dormant IResourceSecurityContext<TResource> contract shipped in ZeroAlloc.Authorization v2.1.0 (PR #28, released today). AuthorizationBehavior.Handle now wraps the resolved ISecurityContext in an internal adapter that exposes the dispatched TRequest as Resource. Consumer policies that type-check ctx is IResourceSecurityContext<TConcreteRequest> rc now resolve correctly — no consumer changes required beyond writing the resource-based policy.

Why

ZeroAlloc.Authorization v2.1 shipped the contract dormant — the interface exists, but no host populates it. Mediator.Authorization is the natural first host: it already resolves an ISecurityContext from DI per dispatch and calls AuthorizerFor<TRequest>.EvaluateAsync(ctx, ct). The change is a fully-additive wrap before that call.

Design + plan

  • Design: docs/plans/2026-05-23-mediator-authorization-resource-context-design.md
  • Plan: docs/plans/2026-05-23-mediator-authorization-resource-context.md

What changed

  • NEW src/ZeroAlloc.Mediator.Authorization/ResourceSecurityContextAdapter.csinternal sealed class ResourceSecurityContextAdapter<TResource> : IResourceSecurityContext<TResource> forwarding ISecurityContext members to an inner context. No PublicAPI change.
  • MOD src/ZeroAlloc.Mediator.Authorization/AuthorizationBehavior.cs — 2-line wrap of ctx before the authorizer.EvaluateAsync(...) call.
  • NEW tests/ZeroAlloc.Mediator.Authorization.Tests/ResourceSecurityContextTests.cs — 2 runtime tests covering the resource-resolves and wrong-type-falls-through cases.
  • MOD tests/ZeroAlloc.Mediator.Authorization.Tests/TestFixtures.cs — adds ResourceOwnerPolicy / ResourceWrongTypePolicy + their request records and stub handlers.
  • MOD docs/authorization.md — new "Resource-based policies" section linking out to ZeroAlloc.Authorization's core-concepts/resource-based-authorization.md.

Task 4 (allocation-budget bump) from the plan was skipped because the existing 512 B AuthorizationBehavior.Handle budget already absorbs the ~16 B/dispatch adapter allocation — verified by AllocationBudgetTests passing without modification.

Allocation cost

One ~16 B class allocation per dispatch (object header + 2 reference fields + method-table pointer). Absorbed by the existing AuthorizationBehavior.Handle allocation budget; see AllocationBudgetTests.

Test plan

  • CI green: build + tests + aot-smoke
  • All existing tests remain green (the adapter forwards Id/Roles/Claims transparently); local 33/33 pass.
  • Two new resource-context tests cover both the matching and mismatching TResource cases.
  • AuthorizationBehavior.Handle allocation budget still respected without modification.

Out of scope

  • AI.Sentinel adoption of the same pattern. Tracked separately.
  • IHasResource<TResource> sub-property extractor. Sub-properties go through rc.Resource.X.Y inside the policy body.

🤖 Generated with Claude Code

MarcelRoozekrans and others added 6 commits May 23, 2026 21:28
…option

Lights up IResourceSecurityContext<TRequest> (dormant contract shipped
in ZeroAlloc.Authorization v2.1) by wrapping the resolved ISecurityContext
in a per-dispatch ResourceSecurityContextAdapter<TRequest> before calling
AuthorizerFor<TRequest>.EvaluateAsync. The dispatched request becomes the
typed resource. Always-wrap (no opt-in surface), ~16 B per dispatch.

Pure runtime additive behaviour — no PublicAPI change. Lands as a feat:
minor bump for Mediator.Authorization.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rce context

Task-by-task plan covering adapter creation, AuthorizationBehavior wrap,
2 runtime tests, conditional allocation-budget bump, docs section, and
push + admin-merge. Follows the precedent of the 2026-05-22 integration
tests plan.
…ource>

Per-dispatch adapter that implements IResourceSecurityContext<TResource>
(shipped dormant in ZeroAlloc.Authorization v2.1) by wrapping an inner
ISecurityContext + a resource value. ISecurityContext members forward to
the inner; Resource exposes the wrapped value.

Not wired into AuthorizationBehavior yet — that's the next commit.
Internal-only; no PublicAPI change.
AuthorizationBehavior.Handle now wraps the resolved ISecurityContext in a
ResourceSecurityContextAdapter<TRequest> before passing to the authorizer.
Policies that type-check ctx is IResourceSecurityContext<TRequest> rc now
resolve correctly; policies that ignore the resource see the same
ISecurityContext members as before.

Cost: ~16 B class allocation per dispatch (one object header + two
reference fields). Absorbed by the existing AuthorizationBehavior.Handle
budget; see AllocationBudgetTests.

Lights up ZeroAlloc.Authorization v2.1's IResourceSecurityContext<TResource>
contract for Mediator dispatch.
Two runtime tests on AuthorizationBehavior.Handle:

  - Policy_Sees_DispatchedRequest_AsResource: a [Policy] that type-checks
    IResourceSecurityContext<ResourceOwnerCommand> sees the dispatched
    request and allows when ctx.Id == request.UserId.
  - Policy_TypeChecking_WrongRequestType_FallsThrough: a [Policy] that
    type-checks the WRONG TResource (intentionally mismatched) hits the
    cast's false branch and denies.

Adds ResourceOwnerPolicy / ResourceWrongTypePolicy and their request
records to TestFixtures.cs. Tests run under the existing
[Collection("non-parallel-authorization")] guard because they set the
static AuthorizationBehaviorState.ServiceProvider.
Documents how to write a policy that inspects the dispatched request as
a typed resource via IResourceSecurityContext<TRequest>. Mediator
wraps the resolved ISecurityContext per-dispatch so the cast resolves
automatically — no host configuration. Links out to
ZeroAlloc.Authorization's resource-based-authorization.md for the
underlying contract.
@MarcelRoozekrans
MarcelRoozekrans merged commit fdadae8 into main May 23, 2026
3 checks passed
@MarcelRoozekrans
MarcelRoozekrans deleted the feat/mediator-authorization-resource-context branch May 23, 2026 20:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant