Valtuutus.Data.Postgres 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Valtuutus.Data.Postgres --version 1.0.0
                    
NuGet\Install-Package Valtuutus.Data.Postgres -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Valtuutus.Data.Postgres" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Valtuutus.Data.Postgres" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Valtuutus.Data.Postgres" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Valtuutus.Data.Postgres --version 1.0.0
                    
#r "nuget: Valtuutus.Data.Postgres, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Valtuutus.Data.Postgres@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Valtuutus.Data.Postgres&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Valtuutus.Data.Postgres&version=1.0.0
                    
Install as a Cake Tool

Valtuutus

Valtuutus is a high-performance Relationship-Based Access Control (ReBAC) authorization library for .NET, inspired by Google Zanzibar.

It enables fine-grained authorization for ASP.NET Core and .NET applications — modeling permissions and access control through relationships instead of relying only on roles.

Features:

  • Google Zanzibar-inspired permission model
  • High-performance authorization engine
  • ASP.NET Core / .NET integration
  • Strongly typed schema support (source generator)
  • Multiple evaluation engines (Check, LookupEntity, LookupSubject, SubjectPermission, Explain)
  • Low-allocation execution
  • Native AOT compatible

The implementation is inspired on permify and other ReBAC open source projects.

NuGet Version

<a href="https://bencher.dev/perf/valtuutus?clear=true&key=true&reports_per_page=4&branches_per_page=8&testbeds_per_page=8&benchmarks_per_page=8&plots_per_page=8&reports_page=1&branches_page=1&testbeds_page=1&benchmarks_page=1&plots_page=1&tab=branches&measures=b549a9dd-6ff0-4525-b90a-c9e3af815580&branches_search=main&branches=1bffa1be-8399-4560-814d-30231501957f%2C9e4cbdcf-9fee-4cd3-ada1-62aefe433145&heads=deb5918c-87b4-4bdb-9b46-25e563bdba14%2C5bdd1841-0a0f-4532-84b7-87ef3d065302&testbeds=072da3db-e609-4676-99a6-5b9262df6086&benchmarks_search=check_complex&benchmarks=86537617-e761-40b8-bd7a-8ad4b6559b47%2C177b6be7-d449-45cb-928a-04f792c80c43%2C8dc1fb40-6499-45e0-be05-23bbf539cd7e%2Cfa90791e-1700-480d-a973-a5df9b695431&start_time=1782864000000&utm_medium=share&utm_source=bencher&utm_content=img&utm_campaign=perf%2Bimg&utm_term=valtuutus"><img src="https://api.bencher.dev/v0/projects/valtuutus/perf/img?branches=1bffa1be-8399-4560-814d-30231501957f%2C9e4cbdcf-9fee-4cd3-ada1-62aefe433145&heads=deb5918c-87b4-4bdb-9b46-25e563bdba14%2C5bdd1841-0a0f-4532-84b7-87ef3d065302&testbeds=072da3db-e609-4676-99a6-5b9262df6086&specs=&benchmarks=86537617-e761-40b8-bd7a-8ad4b6559b47%2C177b6be7-d449-45cb-928a-04f792c80c43%2C8dc1fb40-6499-45e0-be05-23bbf539cd7e%2Cfa90791e-1700-480d-a973-a5df9b695431&measures=b549a9dd-6ff0-4525-b90a-c9e3af815580&start_time=1782864000000" title="valtuutus" alt="valtuutus - Bencher" /></a>

Functionality

The library is designed to be simple and easy to use. Each subset of functionality is divided in engines. The engines are:

  • ICheckEngine: The engine that handles the answering of three questions:
    • Can entity U perform action Y in resource Z? For that, use the Check function.
    • What permissions entity U have in resource Z? For that, use the SubjectPermission function.
    • Why did that permission check succeed or fail? For that, use the Explain function — returns a full resolution tree showing every evaluated relation, attribute, and expression.
  • ILookupSubjectEngine: The engine that can answer: Which subjects of type T have permission Y on entity:X? For that, use the Lookup function.
  • ILookupEntityEngine: The engine that can answer: Which resources of type T can entity:X have permission Y? For that, use the LookupEntity function. Supports scoped queries and cursor pagination — see below.
  • IDataWriterProvider: This is the provider that can write your relational or attribute data.
  • IDbDataWriterProvider: Works similarly to IDataWriterProvider, with the addition of accepting a connection and transaction as parameters.
  • Read here about how the relational data is stored.
  • Read here for engine usage examples (Check, Explain, SubjectPermission, LookupSubject, LookupEntity).

LookupEntity — scoped queries and pagination

LookupEntity returns a LookupEntityPage:

LookupEntityPage page = await lookupEntityEngine.LookupEntity(
    new LookupEntityRequest("task", "view", "user", "alice"),
    cancellationToken);

// page.EntityIds — IReadOnlyList<string>
// page.ContinuationToken — null if no more pages

Scope — constrain results to a parent entity

Use EntityScope when you need to answer a scoped question like "which tasks in project X can this user view?" — the same query you'd back a GET /projects/{projectId}/tasks endpoint with.

Without scope, LookupEntity returns all tasks the user can view across the entire system. With scope, results are limited to tasks that have the specified relation to the given parent entity — so only tasks belonging to project-1 are considered.

var page = await lookupEntityEngine.LookupEntity(
    new LookupEntityRequest("task", "view", "user", "alice")
    {
        Scope = new EntityScope(
            Relation: "parent",      // the relation on "task" that points to its parent
            SubjectType: "project",  // the parent entity type
            SubjectId: "project-1"   // the specific parent to scope to
        )
    },
    cancellationToken);

Pagination

string? token = null;
do
{
    var page = await lookupEntityEngine.LookupEntity(
        new LookupEntityRequest("task", "view", "user", "alice")
        {
            Scope = new EntityScope("parent", "project", "project-1"),
            PageSize = 50,
            ContinuationToken = token
        },
        cancellationToken);

    Process(page.EntityIds);
    token = page.ContinuationToken;
} while (token is not null);

Documentation

Guide Description
Getting Started End-to-end quickstart — install, configure, write data, check permissions
Modeling Authorization Schema DSL walkthrough with the GitHub example
Schema Reference Complete reference for every keyword, operator, and type in the DSL
Authorization Patterns Ready-made patterns: RBAC, hierarchical RBAC, ABAC, multi-tenancy
Using the Engines Code examples for Check, Explain, SubjectPermission, LookupSubject, LookupEntity, depth
Storing Data Writing, deleting, snap tokens
Source Generator Build-time schema constants and compiled fn functions
Testing Unit-testing your authorization model with the InMemory provider
Caching Reducing database load with FusionCache
Telemetry OpenTelemetry activity sources, emitted spans, and what to monitor

Usage

Install the package from NuGet:

If using Postgres:

dotnet add package Valtuutus.Data.Postgres

If using SqlServer:

dotnet add package Valtuutus.Data.SqlServer

If you prefer using an InMemory provider:

dotnet add package Valtuutus.Data.InMemory

Adding to DI:

builder.Services.AddValtuutusCore(c =>
        ... 

See examples of how to define your schema here.

If using Postgres:

builder.Services
    .AddPostgres(_ => () => new NpgsqlConnection(builder.Configuration.GetConnectionString("PostgresDb")!));

If using SqlServer:

builder.Services
    .AddSqlServer(_ => () => new SqlConnection(builder.Configuration.GetConnectionString("SqlServerDb")!));

If using InMemory:

builder.Services
    .AddInMemory();

Database migrations

If you are using a DB provider to store your data, please look at the scripts that create the tables that Valtuutus require to function.

Schema and table name customization

Both relational providers accept an optional options object to customise the database schema and table names. Pass it as the second argument to AddPostgres or AddSqlServer:

// Postgres — defaults: schema="public", tables="transactions", "relation_tuples", "attributes"
builder.Services.AddValtuutusCore(/* schema */)
    .AddPostgres(
        _ => () => new NpgsqlConnection(connectionString),
        new ValtuutusPostgresOptions(
            schema:                 "authz",
            transactionsTableName:  "transactions",
            relationsTableName:     "relation_tuples",
            attributesTableName:    "attributes"));

// SQL Server — defaults: schema="dbo", same table names
builder.Services.AddValtuutusCore(/* schema */)
    .AddSqlServer(
        _ => () => new SqlConnection(connectionString),
        new ValtuutusSqlServerOptions(
            schema:                 "authz",
            transactionsTableName:  "transactions",
            relationsTableName:     "relation_tuples",
            attributesTableName:    "attributes"));

Make sure the migration script targets the same schema and table names you configure here.

ValtuutusPostgresOptions also exposes two Npgsql-specific properties for automatic prepared statements:

Property Default Meaning
MaxAutoPrepare 64 Maximum number of statements Npgsql will auto-prepare
AutoPrepareMinUsages 2 Minimum executions before a statement is prepared

These map directly to Npgsql's prepared statement feature and can improve performance for repeated queries under load.

Using query concurrent limiting

It is expected that you don't want to allow Valtuutus to expand queries while it has resources. The default limit is 5 concurrent queries for the same request. To change that, you can use the AddConcurrentQueryLimit method, for example:

builder.Services
    .AddPostgres(_ => () => new NpgsqlConnection(builder.Configuration.GetConnectionString("PostgresDb")!)) // Replace this with any provider you want
    .AddConcurrentQueryLimit(10);

Change your data provider according to your database.

Caching

Valtuutus supports caching the calls to the engines through the Valtuutus.Data.Caching package. To use it, install like:

dotnet add package Valtuutus.Data.Caching

In your DI setup, add the caching component:

builder.Services
    .AddPostgres(_ => () => new NpgsqlConnection(builder.Configuration.GetConnectionString("PostgresDb")!)) // Replace this with any provider you want
    .AddCaching(); // <-- This line

This packages requires that you set up the amazing FusionCache library. Click here for more information.

Telemetry

The library uses OpenTelemetry to provide telemetry data. To enable it, just add a source with the name "Valtuutus":

builder.Services
    .AddOpenTelemetry()
    .WithTracing(telemetry =>
    {
        telemetry
            .AddSource("Valtuutus")
            ...
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed.  net11.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.3.0 132 7/30/2026
1.2.0 120 7/24/2026
1.1.0 104 7/17/2026
1.0.0 116 7/11/2026
0.11.1-beta 125 7/4/2026
0.11.0-beta 147 6/26/2026
0.10.2-beta 265 6/19/2026
0.10.1-beta 112 6/15/2026
0.10.0-beta 111 6/9/2026
0.9.0-beta 131 4/20/2026
0.8.2-beta 109 4/17/2026
0.8.1-beta 109 4/17/2026
0.8.0-beta 115 4/13/2026
0.7.3.1-beta 337 4/3/2025
0.7.3-beta 231 3/20/2025
0.7.2-beta 195 12/30/2024
0.7.1-beta 179 12/30/2024
0.7.0-beta 176 11/19/2024
0.6.0-beta 185 10/9/2024
0.5.0-beta 198 8/21/2024
Loading failed

First stable release. All prior releases were ; the public API from this version forward follows semantic versioning.

## Changes since v0.11.1-beta

### Performance
- Index InMemory store by entity/subject type to avoid full-table scans (#250)
- Avoid nested-loop plan for JOIN-collapse queries on Postgres (#248)
- Batch sibling relation queries in  (#247)
- Extend sibling-relation batching to constrained/negate Intersect paths (#246)
- Batch sibling direct-relation queries in  (#244)
- Batch sibling direct-relation checks in  (#236)
- Schema-driven pruning of statically-dead check branches (#232)

### Bug Fixes
- Split benchmark workflows per-provider, fix Bencher Namespace collision (#245)
-  fan-out fix, pruning, baseline benchmarks (#241)
-  Scope/Negate bug and schema-driven pruning (#239)
- Core AOT crashes in the runtime fn Expression-tree fallback path (#228)
- Annotate  return with  to match  (#227)
- Bump  to 1.15.3 (#211)

### Features
- Enable  analyzer across src projects (#229)
- Compile schema DSL functions at build time via source generator (#216) (#224)

### Refactors
- Use source-gen  for delete-filter serialization (#223)
- Replace  with hand-written  impls (SqlServer bulk copy) (#222)
- Remove remaining Dapper usage from SqlServer provider (#221)
- Remove Dapper SqlBuilder from SqlServer provider (#220)
- Remove Dapper SqlBuilder from Postgres provider (#212)

### Docs / Chore
- Boot benchmark containers once per suite instead of per method (#251)
- Update Bencher benchmark image link
- SEO-oriented README intro and richer NuGet metadata
- Split source generator content into its own guide
- Document  wiring for schema fn functions (#231)
- Remove broken post_coverage workflow (#230)