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:

  1. Loads a policy from rulegate.yaml.
  2. Validates and compiles the manifest.
  3. Activates the complete policy source as an immutable snapshot.
  4. Creates a subject and a protected resource.
  5. Evaluates an authorization request.
  6. Prints Allowed when 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.read permission.

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 inputRequest value
Resource typedocument
Actionread
Required permissiondocument.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:

  • LoadErrors contains file and YAML-loading failures.
  • ValidationErrors contains invalid RuleGate manifest structures and values.

Do not register policies when compilation.IsSuccess is false.

Next steps

Continue with: