-
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.
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