diff --git a/src/BuildingBlocks/Contracts/Authorization/AuthorizationPolicy.cs b/src/BuildingBlocks/Contracts/Authorization/AuthorizationPolicy.cs
new file mode 100644
index 0000000..c730eef
--- /dev/null
+++ b/src/BuildingBlocks/Contracts/Authorization/AuthorizationPolicy.cs
@@ -0,0 +1,35 @@
+namespace OpenHealthOS.Contracts.Authorization;
+
+///
+/// Represents a named authorization policy.
+///
+public sealed record AuthorizationPolicy
+{
+ ///
+ /// Initializes a new instance of the
+ /// class.
+ ///
+ /// The stable policy identifier.
+ public AuthorizationPolicy(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ throw new ArgumentException(
+ "Authorization policy value cannot be null or whitespace.",
+ nameof(value));
+ }
+
+ Value = value;
+ }
+
+ ///
+ /// Gets the stable policy identifier.
+ ///
+ public string Value { get; }
+
+ ///
+ /// Returns the policy identifier.
+ ///
+ /// The policy identifier string.
+ public override string ToString() => Value;
+}
diff --git a/src/BuildingBlocks/Security/Authorization/IAuthorizationPolicy.cs b/src/BuildingBlocks/Security/Authorization/IAuthorizationPolicy.cs
new file mode 100644
index 0000000..0edb365
--- /dev/null
+++ b/src/BuildingBlocks/Security/Authorization/IAuthorizationPolicy.cs
@@ -0,0 +1,23 @@
+namespace OpenHealthOS.Security.Authorization;
+
+using OpenHealthOS.Contracts.Authorization;
+
+///
+/// Represents a policy used to determine whether an authorization
+/// request satisfies a defined authorization rule.
+///
+public interface IAuthorizationPolicy
+{
+ ///
+ /// Determines whether the specified authorization context satisfies
+ /// this policy.
+ ///
+ ///
+ /// The authorization context to evaluate.
+ ///
+ ///
+ /// when the context satisfies the policy;
+ /// otherwise .
+ ///
+ bool IsSatisfied(AuthorizationContextDto context);
+}
diff --git a/src/BuildingBlocks/Security/Authorization/PermissionPolicy.cs b/src/BuildingBlocks/Security/Authorization/PermissionPolicy.cs
new file mode 100644
index 0000000..00adf07
--- /dev/null
+++ b/src/BuildingBlocks/Security/Authorization/PermissionPolicy.cs
@@ -0,0 +1,44 @@
+namespace OpenHealthOS.Security.Authorization;
+
+using OpenHealthOS.Contracts.Authorization;
+
+///
+/// Authorization policy that requires a specific permission.
+///
+public sealed class PermissionPolicy : IAuthorizationPolicy
+{
+ private readonly Permission _permission;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The permission required by this policy.
+ ///
+ public PermissionPolicy(Permission permission)
+ {
+ ArgumentNullException.ThrowIfNull(permission);
+
+ _permission = permission;
+ }
+
+ ///
+ /// Determines whether the authorization context satisfies the policy.
+ ///
+ ///
+ /// The authorization context to evaluate.
+ ///
+ ///
+ /// when the requested permission matches the
+ /// policy permission; otherwise .
+ ///
+ public bool IsSatisfied(AuthorizationContextDto context)
+ {
+ ArgumentNullException.ThrowIfNull(context);
+
+ return string.Equals(
+ context.Permission.Value,
+ _permission.Value,
+ StringComparison.OrdinalIgnoreCase);
+ }
+}
diff --git a/tests/UnitTests/Authorization/PermissionPolicyTests.cs b/tests/UnitTests/Authorization/PermissionPolicyTests.cs
new file mode 100644
index 0000000..aa632e6
--- /dev/null
+++ b/tests/UnitTests/Authorization/PermissionPolicyTests.cs
@@ -0,0 +1,63 @@
+namespace OpenHealthOS.UnitTests.Authorization;
+
+using OpenHealthOS.Contracts.Authorization;
+using OpenHealthOS.Contracts.Identity;
+using OpenHealthOS.Security.Authorization;
+using Xunit;
+
+public sealed class PermissionPolicyTests
+{
+ [Fact]
+ public void IsSatisfied_ShouldReturnTrue_WhenPermissionMatches()
+ {
+ var policy = new PermissionPolicy(
+ new Permission("patient.read"));
+
+ var context = CreateContext("patient.read");
+
+ var result = policy.IsSatisfied(context);
+
+ Assert.True(result);
+ }
+
+ [Fact]
+ public void IsSatisfied_ShouldReturnTrue_WhenPermissionMatchesIgnoringCase()
+ {
+ var policy = new PermissionPolicy(
+ new Permission("patient.read"));
+
+ var context = CreateContext("PATIENT.READ");
+
+ var result = policy.IsSatisfied(context);
+
+ Assert.True(result);
+ }
+
+ [Fact]
+ public void IsSatisfied_ShouldReturnFalse_WhenPermissionDoesNotMatch()
+ {
+ var policy = new PermissionPolicy(
+ new Permission("patient.read"));
+
+ var context = CreateContext("patient.write");
+
+ var result = policy.IsSatisfied(context);
+
+ Assert.False(result);
+ }
+
+ private static AuthorizationContextDto CreateContext(
+ string permission)
+ {
+ return new AuthorizationContextDto
+ {
+ Identity = new IdentityContextDto
+ {
+ SubjectId = "test-user",
+ PrincipalType = PrincipalType.User,
+ },
+ Permission = new Permission(permission),
+ ResourceType = "Patient",
+ };
+ }
+}