Valtuutus.Data.Postgres
1.0.0
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
<PackageReference Include="Valtuutus.Data.Postgres" Version="1.0.0" />
<PackageVersion Include="Valtuutus.Data.Postgres" Version="1.0.0" />
<PackageReference Include="Valtuutus.Data.Postgres" />
paket add Valtuutus.Data.Postgres --version 1.0.0
#r "nuget: Valtuutus.Data.Postgres, 1.0.0"
#:package Valtuutus.Data.Postgres@1.0.0
#addin nuget:?package=Valtuutus.Data.Postgres&version=1.0.0
#tool nuget:?package=Valtuutus.Data.Postgres&version=1.0.0
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.
<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 theCheckfunction.What permissions entity U have in resource Z? For that, use theSubjectPermissionfunction.Why did that permission check succeed or fail?For that, use theExplainfunction — 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 theLookupfunction. - ILookupEntityEngine: The engine that can answer:
Which resources of type T can entity:X have permission Y?For that, use theLookupEntityfunction. 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 | Versions 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. |
-
net10.0
- Npgsql (>= 9.0.3)
- Valtuutus.Data.Db (>= 1.0.0)
-
net11.0
- Npgsql (>= 9.0.3)
- Valtuutus.Data.Db (>= 1.0.0)
-
net8.0
- Npgsql (>= 9.0.3)
- Valtuutus.Data.Db (>= 1.0.0)
-
net9.0
- Npgsql (>= 9.0.3)
- Valtuutus.Data.Db (>= 1.0.0)
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 |
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)