SeliseBlocks.Data.Authorization.Genesis 10.0.0.4-alpha
SeliseBlocks.Data.Authorization
An authorization gateway for MongoDB data access. Every read and write goes through one
IDataAccessGateway that resolves the acting user, checks the entity rules, the field policy and the
row ACL of the addressed resource, executes the operation against that tenant's database and audits
the outcome. A denial is a DataAccessDeniedException with a DenyCode; it is never retried
unrestricted.
Two packages:
| Package | What it is | Depends on |
|---|---|---|
SeliseBlocks.Data.Authorization |
the engine: policy, ACL, capabilities, analysis, audit | MongoDB.Driver, Newtonsoft.Json |
SeliseBlocks.Data.Authorization.Genesis |
hosting it in a Genesis Blocks service: tenant routing, the policy switch, stamping, DI | the engine + Genesis framework |
The engine references no product and no host framework. The Genesis package is the only one that knows about Blocks, and a different platform needs its own adapter rather than changes to the engine.
Integrating it
The host provides two framework services, which an ordinary Genesis service already has:
ISecurityContextProvider (who is calling) and IBlocksMongoDbDataContextProvider (which database a
tenant maps to). Then one call, plus content:
services.AddDataAccess(configuration, new DataAccessContent
{
ResourceRegistry = sp => /* your manifest */,
Capabilities = sp => /* your capability registry */,
StandardSchemas = sp => EntitySchemaBuilder.Default,
IdentitySchemas = sp => /* schemas with your role-bearing fields protected */,
IdentityEntityKeys = new[] { "User" },
PolicyStoreGrant = "policy.store"
});
Everything else has a default:
- Who the caller is.
SecurityContextActorProviderreads the validated Genesis security context and uses its user, tenant and roles. A host whose effective roles live in a user document registers its ownIActorProviderbefore this call and the default steps aside. - Person to user.
NoPersonUserResolverresolves none, which is right for a host with no such model. - Default ACL settings.
NoAclSettingsSourcereturns none, so stamping grants the acting user. - Control grants. Read from the JSON file at
DataAccess:ControlGrants:Pathwhen the content passes no list. - Where the grants live.
ControlGrantStoreOptionsis read fromDataAccess:ControlGrants, and every value has a default, so a host that configures none still starts on the compiled list.
Nothing else has to be registered. MinimalHostRegistrationTests pins exactly this: a container
holding only those two services and the content above resolves a working IDataAccessGateway, with
the policy switch in either position.
Configuring it
{
"DataAccess": {
"Policy": { "Enabled": true, // false waives the rules; refused in production
"AllowDisabledInProduction": false }, // true lets a production deployment mean it
"Content": { "ManifestPath": "policy/resource-policy-manifest.json",
"ManifestSha256": "<pin it in staging and production>",
"CapabilitiesPath": "policy/capabilities.json" },
"ControlGrants": { "Path": "policy/control-grants.json",
"TenantId": "", // set it to read the grants from a database instead
"SeedWhenEmpty": true },
"MaxStaleness": "00:05:00",
"PolicyLoadTimeout": "00:00:15",
"RevocationInterval": "00:00:00"
}
}
DataAccess:Policy:Enabled = false waives the entity rules, the field policy and the row ACL for an
authenticated actor in their own tenant, for development. It never waives authentication, tenant
isolation, the control resources or the audit.
In a production environment - one whose name is empty or starts with prod - the host refuses to
start with the policy off, so that no single wrong value opens every row. A deployment that genuinely
intends it sets DataAccess:Policy:AllowDisabledInProduction to true as well. Two keys rather than
one, and the intent is then visible in the settings file to anyone reviewing it.
Administering the control grants
With DataAccess:ControlGrants:TenantId set, the grant table lives in a collection and
IControlGrantAdministration lets an administration UI read it and re-apply it without a restart:
admin.Current(); // the grants live in this process right now, as copies
admin.Apply(); // re-read the store, validate it whole, swap it in or refuse
Two rules make that safe, and neither is optional:
- A stored row may narrow a declared grant; it may not invent one. The host's compiled list is the authority on which grants may exist, exactly as a capability catalogue is. A control grant reads a control resource with neither row ACL nor field policy, so being able to add a row would be being able to grant unfiltered read over identity, policy or secret collections by writing to a collection. Adding an authority stays a code change.
- Applying is all or nothing. The replacement is validated and bound completely before anything is
swapped, so a table with one bad row leaves the running one untouched and
Appliedcomes back false with the reason. A half-applied authority table would fail later, somewhere unrelated.
The stored _id is a GUID, so the collection keys like any other, but it is DERIVED from the grant name
(ControlGrantId, an RFC 4122 version 5 name-based UUID) rather than random. Deriving keeps three things
a random id would cost: two rows can never carry the same grant name, because they would collide on
_id; seeding and re-importing produce the same document, so those paths stay idempotent; and a
generated seed file is stable, so its diffs show real changes. The name itself is always read from the
Name field, never from the id, and a row without one is refused.
Applying is a deliberate call rather than a background poll: an authority table that changes under a
running process with nothing marking the moment is what an audit cannot reconstruct afterwards. Removing
a row is how a grant is turned off, and the result lists what that left Absent.
What stays the host's
The package authorizes operations on your entities; it cannot know what they are. You supply the
resource manifest (which entities exist, where they are stored, whether they carry a row ACL), the
capability definitions, and the control grants. All three are files, so they are deployed and
reviewed rather than compiled - pin them with *Sha256 where a deployment must not be editable.
What it gives you back
IDataAccessGateway- every authorized read and write.IControlPlane- the grant-scoped bootstrap path a host builds its own directories on ("the users of this tenant", "the roles of this feature"). Each call names one control grant and is audited; the implementation stays internal, so nothing a consumer holds can open a database by itself.IIdentityRouting- which resources the identity executor handles, so a misspelled entity key inIdentityEntityKeysis visible rather than silently routing role-bearing rows to the standard one.IServiceAccess/ICapabilityScopeAccessor- entering a named capability, and observing which one is active. While the policy is disabled every operation is attributed toDataAccessPolicyOptions.DisabledCapabilityName, which the audit records.IAclMaintenance- the audited way to change the ACL of an existing row. Ordinary writes may not set the ACL arrays; that is what makes them trustworthy.IControlGrantAdministration- reading the live control grant table and re-applying it from the store, for an administration UI. See below.
Status
10.0.0.4-alpha. The leading 10 is the .NET version, matching SeliseBlocks.Genesis.Framework 10.0.0.x.
The test suite ships with the source: 1821 tests, all passing, covering the ACL predicate and
stamping, the field and entity analysis, the policy store and snapshots, the schema builder,
capabilities, the control plane and the read/write gateway. Most of them run against a real MongoDB;
point SECFIX_MONGO_URI at one (the default is mongodb://localhost:27555/?directConnection=true,
a single-node replica set).
dotnet test
The tooling that generates a resource manifest by scanning a codebase is not part of these packages; the manifest is an input you supply as a file.
No packages depend on SeliseBlocks.Data.Authorization.Genesis.
.NET 10.0
- SeliseBlocks.Data.Authorization (>= 10.0.0.4-alpha)
- Microsoft.Extensions.Caching.Abstractions (>= 10.0.3)
- Microsoft.Extensions.Caching.Memory (>= 10.0.3)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.3)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.3)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.3)
- MongoDB.Driver (>= 3.9.0)
- Newtonsoft.Json (>= 13.0.3)
- SeliseBlocks.Genesis.Framework (>= 10.0.0.2)
- SeliseBlocks.Genesis.Framework.Api (>= 10.0.0.4)
| Version | Downloads | Last updated |
|---|---|---|
| 10.0.0.4-alpha | 3 | 10/31/2026 |
| 10.0.0.3-alpha | 1 | 10/31/2026 |
| 10.0.0.2-alpha | 1 | 10/31/2026 |
| 10.0.0.1-alpha | 1 | 10/31/2026 |