-
Notifications
You must be signed in to change notification settings - Fork 0
11 Policy Sources and Reload
RuleGate evaluates local immutable policy snapshots. Sources can be combined, but a candidate becomes active only after every source succeeds and the complete combined set is valid.
| Source | Registration | Automatic reload | Good fit |
|---|---|---|---|
| In-memory definitions |
AddPolicy, AddPolicies
|
no | programmatic policies, tests |
| YAML file | AddYamlPolicyFile |
optional | deployable local policy file |
| Embedded YAML | AddEmbeddedPolicyResource |
no | immutable policy inside assembly |
| .NET configuration | AddConfigurationPolicySource |
provider-dependent | structured host configuration |
| Application source | AddPolicySource |
manual | local application-owned transformation |
RuleGate does not require a database or remote authorization server. Custom sources still load into the local process.
YAML is optional. Applications can construct policies directly in C# and do not need the Manifest package or CLI for this path:
using Fotbiler.RuleGate.Abstractions.Policies;
using Fotbiler.RuleGate.AspNetCore.DependencyInjection;
builder.Services
.AddRuleGate()
.AddPolicy(
new PolicyDefinition(
id: "invoice-approve",
resourceType: "invoice",
action: "approve",
requirement: new AllRequirementDefinition(
[
new PermissionRequirementDefinition("INVOICE.APPROVE"),
new RoleRequirementDefinition("FINANCE.APPROVER"),
])));Use AddPolicies when definitions are assembled in an application module.
Code-first policies use the same engine, fail-closed behavior, diagnostics,
enrichment, and ASP.NET Core enforcement as compiled manifests. They are a
good fit when policies change only with application deployments or when an
existing code-based authorization system is being migrated incrementally.
YAML becomes useful when policies need independent review, CLI validation, deterministic tests, identifier generation, or safe local reload. Choose the source according to ownership and deployment needs; neither representation is more trusted merely because of its format.
var manifestPath = Path.Combine(
builder.Environment.ContentRootPath,
"rulegate.yaml");
builder.Services
.AddRuleGate()
.AddYamlPolicyFile(
manifestPath,
options =>
{
options.ReloadOnChange = true;
});File changes are debounced. A missing, unreadable, malformed, invalid, or conflicting candidate is rejected while the last valid snapshot remains active.
<ItemGroup>
<EmbeddedResource Include="Authorization/rulegate.yaml" />
</ItemGroup>builder.Services
.AddRuleGate()
.AddEmbeddedPolicyResource(
typeof(Program).Assembly,
"DocumentService.Authorization.rulegate.yaml");This is useful for immutable artifacts and legacy deployment layouts that cannot manage an external file safely.
{
"RuleGate": {
"SchemaVersion": 1,
"Application": {
"Id": "document-api",
"Name": "Document API"
},
"Policies": [
{
"Id": "document-read",
"ResourceType": "document",
"Action": "read",
"Requirement": {
"Permission": "DOC.READ"
}
}
]
}
}builder.Services
.AddRuleGate()
.AddConfigurationPolicySource(
builder.Configuration,
"RuleGate",
options => options.ReloadOnChange = true);Configuration providers decide whether reload notifications exist. Secrets stores are not automatically policy stores; keep policy and secret concerns separate.
public sealed class ApplicationPolicySource : IPolicySource
{
private readonly ILocalPolicyCatalog _catalog;
public ApplicationPolicySource(ILocalPolicyCatalog catalog)
{
_catalog = catalog;
}
public string Name => "application";
public async ValueTask<PolicySourceLoadResult> LoadAsync(
CancellationToken cancellationToken = default)
{
var policies = await _catalog.LoadAsync(cancellationToken);
return PolicySourceLoadResult.Success(policies);
}
}builder.Services
.AddRuleGate()
.AddPolicySource<ApplicationPolicySource>();Source names must be unique. Exceptions become stable diagnostics without exposing messages or stack traces. Cancellation propagates.
var reloader = app.Services.GetRequiredService<IPolicyReloadService>();
var result = await reloader.ReloadAsync(cancellationToken);
if (!result.IsSuccess)
{
foreach (var diagnostic in result.Diagnostics)
{
logger.LogError(
"Policy source {Source} failed with {Code} at {Path}",
diagnostic.SourceName,
diagnostic.Code,
diagnostic.Path);
}
}CurrentSnapshot contains operational metadata: local version, policy count,
and sorted source names. It does not expose manifest values or authorization
input. Local snapshot versions are not distributed generation IDs.
flowchart TD
A[Reload requested] --> B[Load every source]
B --> C{All sources succeeded?}
C -->|No| X[Reject candidate; keep last valid snapshot]
C -->|Yes| D[Combine complete results]
D --> E{Unique source names, policy IDs, and routes?}
E -->|No| X
E -->|Yes| F[Build immutable lookup]
F --> G[Atomic reference swap]
G --> H[New requests observe new snapshot]
I[Concurrent requests] --> J[Observe old complete snapshot]
A reader never sees half a reload. Before the first valid activation, the snapshot is empty and every lookup denies.
Each process reloads locally. For consistent fleet promotion:
- validate, lint, and test the candidate in CI;
- distribute the same versioned artifact/configuration;
- restrict source write access;
- observe reload success and active policy counts;
- coordinate rollout/rollback through deployment tooling;
- never use the in-process snapshot counter as a global version.
- Treat source write access like application code deployment access.
- Never accept arbitrary user YAML as active production policy.
- Keep file permissions minimal.
- Bound custom source data and loading time.
- Return structured diagnostics rather than raw exceptions.
- Preserve the last valid snapshot on rejection.
- Test duplicate routes across sources.
Previous: Testing and diagnostics · Next: Extensibility
Canonical source: docs/guide · Documentation index · RuleGate 1.0.0
- Home
- 1. Authorization foundations
- 2. Packages and installation
- 3. First protected API
- 4. Policy language
- 5. ASP.NET Core integration
- 6. Trusted attributes and context
- 7. Identity and Keycloak
- 8. Frontend integration
- 9. CLI and policy lifecycle
- 10. Testing and diagnostics
- 11. Policy sources and reload
- 12. Extensibility
- 13. Real-world recipes
- 14. Production checklist
- Glossary