Skip to main content
Version: Current

Verified .NET Quickstart

Use this page when you want the shortest path to a working RBAC decision in a fresh ASP.NET Core app.

What this path proves

  • A brand-new net9.0 app can install PrimusSaaS.Rbac and PrimusSaaS.Rbac.InMemory.
  • The app builds with 0 Warning(s), 0 Error(s).
  • A seeded allow request returns "allowed": true.
  • An unknown principal returns "allowed": false with "reason": "no_match".

Prerequisites

  • .NET 9 SDK
  • A new empty ASP.NET Core app, for example:
dotnet new web -n PrimusRbacQuickstart -f net9.0
cd PrimusRbacQuickstart

Install packages

dotnet add package PrimusSaaS.Rbac
dotnet add package PrimusSaaS.Rbac.InMemory

Replace Program.cs

using PrimusSaaS.Rbac;
using PrimusSaaS.Rbac.InMemory;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddPrimusRbacInMemory(options =>
{
options.SeedMode = "none";
options.AllowMultipleInheritance = false;
});

var app = builder.Build();

app.Services.SeedPrimusRbac(rbac =>
{
var scope = new RbacScope(ApplicationId: "app-rbac-quickstart", TenantId: "tenant-a");

rbac.UpsertPermission(new RbacPermission(
Id: "perm:reports:read",
Action: "read",
Resource: "reports",
Effect: RbacEffect.Allow,
Scope: scope));

rbac.UpsertRole(new RbacRole(
Id: "role:viewer",
Name: "Viewer",
Scope: scope,
PermissionIds: new[] { "perm:reports:read" }));

rbac.UpsertAssignment(new RbacAssignment(
Id: "assign:user-123:viewer",
PrincipalId: "user-123",
PrincipalType: "user",
RoleId: "role:viewer",
Scope: scope));
});

app.MapPost("/api/rbac/check", (IRbacService rbac, RbacAccessRequest request) =>
{
var decision = rbac.Evaluate(request);
return Results.Ok(decision);
});

app.Run();

Run the app

dotnet run

Verify the documented outcome

Allow:

curl -s \
-H "Content-Type: application/json" \
-d '{
"principalId": "user-123",
"principalType": "user",
"action": "read",
"resource": "reports",
"applicationId": "app-rbac-quickstart",
"tenantId": "tenant-a"
}' \
http://localhost:5000/api/rbac/check

Expected fragment:

{
"allowed": true,
"reason": "allow_rule_matched"
}

Deny:

curl -s \
-H "Content-Type: application/json" \
-d '{
"principalId": "user-999",
"principalType": "user",
"action": "read",
"resource": "reports",
"applicationId": "app-rbac-quickstart",
"tenantId": "tenant-a"
}' \
http://localhost:5000/api/rbac/check

Expected fragment:

{
"allowed": false,
"reason": "no_match"
}

Current validation evidence

  • Fresh app path recorded in docs/technical/docs-onboarding-validation-matrix.md
  • Current workspace run validated the broader RBAC package family with 385/385 passing tests across net8.0, net9.0, and net10.0

Next step