Getting Started with RuleGate
August 1, 2026 ยท View on GitHub
This guide creates and evaluates a complete RuleGate authorization policy without requiring an identity provider, database, or remote policy service.
What you will build
You will create a small .NET console application that:
- Loads a policy from
rulegate.yaml. - Validates and compiles the manifest.
- Activates the complete policy source as an immutable snapshot.
- Creates a subject and a protected resource.
- Evaluates an authorization request.
- Prints
Allowedwhen the subject has the required permission.
Prerequisites
Install one of the supported .NET SDKs:
- .NET 8
- .NET 9
- .NET 10
Verify the installed SDK:
dotnet --version
1. Create the application
mkdir rulegate-getting-started
cd rulegate-getting-started
dotnet new console
2. Install RuleGate
Install the ASP.NET Core integration:
dotnet add package \
Fotbiler.RuleGate.AspNetCore \
--version 1.0.0
Fotbiler.RuleGate.AspNetCore brings in the authorization engine and public
contracts together with YAML loading, validation, policy compilation, and
local policy sources.
The RuleGate CLI is distributed as a separate .NET tool. Install the exact stable version used by this guide:
dotnet tool install \
--global \
Fotbiler.RuleGate.Cli \
--version 1.0.0
3. Create the policy manifest
Create rulegate.yaml in the project directory:
schemaVersion: 1
application:
id: getting-started
name: RuleGate Getting Started
policies:
- id: document-read
resourceType: document
action: read
requirement:
id: document-read-permission
permission: document.read
This policy matches requests where:
- The resource type is exactly
document. - The action is exactly
read. - The subject contains the
document.readpermission.
RuleGate matching is ordinal and case-sensitive.
Validate the manifest before startup
From the directory containing rulegate.yaml, run:
rulegate validate
A valid manifest returns exit code 0. Manifest loading, schema, structural,
or semantic validation failures return exit code 1.
For CI systems and other automation, request pure JSON output:
rulegate validate --format json
An explicit path may be supplied when the manifest is stored elsewhere:
rulegate validate ./policies/rulegate.yaml
CLI validation uses the same fail-closed manifest compiler as application startup. A failed validation never produces or exposes a partial policy set.
Before deployment, lint the valid manifest for structural risks:
rulegate lint ./policies/rulegate.yaml --format json
See Explain and Lint for lint finding codes and redacted decision explanations built from deterministic policy-test fixtures.
Generate deterministic policy, resource-type, and action constants:
rulegate generate csharp \
./rulegate.yaml \
--namespace Sample.Authorization \
--output Generated/RuleGate.g.cs
Verify committed generated output in CI without modifying it:
rulegate generate csharp \
./rulegate.yaml \
--namespace Sample.Authorization \
--output Generated/RuleGate.g.cs \
--check
4. Create the authorization flow
Replace Program.cs with:
using Fotbiler.RuleGate.Abstractions.Authorization;
using Fotbiler.RuleGate.Abstractions.Policies;
using Fotbiler.RuleGate.AspNetCore.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
var services =
new ServiceCollection();
services.AddLogging();
services.AddAuthorizationCore();
services
.AddRuleGate()
.AddYamlPolicyFile("rulegate.yaml");
using var serviceProvider =
services.BuildServiceProvider(
new ServiceProviderOptions
{
ValidateOnBuild = true,
ValidateScopes = true,
});
var reload = await serviceProvider
.GetRequiredService<IPolicyReloadService>()
.ReloadAsync();
if (!reload.IsSuccess)
{
foreach (var diagnostic in reload.Diagnostics)
{
Console.Error.WriteLine(
$"{diagnostic.SourceName}: " +
$"{diagnostic.Code} at " +
$"{diagnostic.Path ?? "root"}");
}
return 1;
}
var engine =
serviceProvider.GetRequiredService<
IAuthorizationEngine>();
var request =
new AuthorizationRequest(
subject:
new AuthorizationSubject(
id: "user-1",
permissions:
[
"document.read",
]),
resource:
new AuthorizationResource(
type: "document",
id: "document-1"),
action:
"read",
context:
new AuthorizationContext(
DateTimeOffset.UnixEpoch));
var decision =
await engine.EvaluateAsync(
request);
Console.WriteLine(
decision.IsAllowed
? "Allowed"
: "Denied");
return decision.IsAllowed
? 0
: 1;
This example uses a bare ServiceCollection instead of an ASP.NET Core
application builder. AddLogging supplies the logging services required by
ASP.NET Core authorization. A WebApplicationBuilder normally registers
those services automatically.
AddAuthorizationCore registers the ASP.NET Core authorization primitives,
while AddRuleGate registers the RuleGate policy engine and built-in
requirement evaluators. AddYamlPolicyFile adds the manifest as a local policy
source. The explicit initial reload validates the complete source and activates
one immutable snapshot before the first authorization request.
ASP.NET Core hosts perform the initial source load through a hosted service.
This console example calls IPolicyReloadService directly because it builds a
bare service provider rather than starting a host. See
Policy sources and atomic reload for file-change,
configuration, embedded-resource, and application-defined sources.
5. Run the application
dotnet run
Expected output:
Allowed
The request is allowed because all three policy inputs match:
| Policy input | Request value |
|---|---|
| Resource type | document |
| Action | read |
| Required permission | document.read |
6. Verify denial behavior
Remove document.read from the subject:
subject:
new AuthorizationSubject(
id: "user-1")
Run the application again:
dotnet run
Expected output:
Denied
The process exits with a non-zero code because the policy requirement is not satisfied.
RuleGate denies authorization when:
- No matching policy exists.
- A required permission, role, or attribute is missing.
- A requirement cannot be evaluated safely.
- A policy or request contains incompatible values.
Understanding the flow
The example follows this pipeline:
rulegate.yaml
|
v
RuleGateManifestCompiler
|
v
Compiled policy definitions
|
v
AddRuleGate + AddPolicies
|
v
IAuthorizationEngine
|
v
AuthorizationRequest
|
v
AuthorizationDecision
Manifest loading and validation happen before the policies are registered. A failed compilation never returns a partial policy collection.
Common problems
The manifest file is not found
Run dotnet run from the directory containing rulegate.yaml, or pass the
correct path to CompileFromFileAsync.
The request is denied unexpectedly
Check the exact spelling and casing of:
- Resource type
- Action
- Permission
- Role
- Attribute name
RuleGate does not perform case-insensitive matching or implicit string normalization.
The manifest does not compile
Read both error collections:
LoadErrorscontains file and YAML-loading failures.ValidationErrorscontains invalid RuleGate manifest structures and values.
Do not register policies when compilation.IsSuccess is false.
Next steps
Continue with:
- The root README for ASP.NET Core dynamic policies, Minimal API endpoints, controller attributes, diagnostics, and HTTP result mapping.
- The ASP.NET Core enrichment guide when subject, resource, or context attributes must be loaded from trusted application services.
- The RuleGate CLI guide for deterministic manifest validation.
- The policy-testing guide for host-independent authorization fixtures.
- The C# code-generation guide for generated constants and stale-output checks.
- The Angular SDK guide for frontend route and template checks.
- The Keycloak integration guide for optional provider mapping.
- The roadmap for planned capabilities and releases.
- The documentation index to navigate all available guides.