Orleans.Lattice.Auth configuration
This page documents Orleans.Lattice.Auth 9.9.0, in the documentation for Orleans.Lattice 9.9.0 (release line 9.9), built 2026-10-04. It is also published as markdown, with every table and list, at configuration.md, and llms.txt lists every page.The package has one public options type, LatticeAuthOptions, which configures the policy store and decision engine: the closed-world fallback and tie-break rules, the durable per-key history retention applied to the reserved sys-auth-policy tree, the optional strict-consistency policy-epoch fence, and the optional audit sink and durable audit trail. It is bound through the AddLatticeAuth registration extension.
LatticeAuthOptions
Configures how the decision engine compiles and evaluates rules, how policy history is retained, and how decisions are audited. Bind it through AddLatticeAuth(configure), or layer an additional configuration delegate after registration with ConfigureLatticeAuth(configure).
| Property | Type | Default | Meaning |
|---|---|---|---|
DefaultEffect |
LatticeEffect |
Deny |
The effect applied when no rule matches a request (the closed-world fallback). Deny is deny-by-default; set to Allow only for an allow-by-default deployment where rules exist purely to carve out denials. It never applies to a control-plane request - the reserved sys-auth-* and sys-tenant-* namespaces, the app-registry sys-app-* namespace, the tenant-administration capability ids, and a cluster-wide capability request on the * sentinel (such as Telemetry or AppInstall) - which is granted only by an explicit matched allow rule and is otherwise denied, even under Allow. |
BootstrapAdministrators |
ISet<string> |
empty ordinal set | Subject ids allowed every operation on every tree - the control plane included, and every capability an Admin grant does not confer (for example Telemetry, Replication, TreeLifecycle, and AppInstall) - short-circuited before the decision engine and the strict epoch fence are consulted. Exists so a policy misconfiguration cannot lock every operator out of the authorization tree itself; keep it to the smallest set of break-glass identities. Entries must be non-null and non-empty. |
AccessAdministrationDelegationEnabled |
bool |
false |
Whether an access administrator may delegate access administration to another subject by authoring a rule on the reserved policy tree. Off by default: no rule may be scoped at the reserved sys-auth-* namespace, so the only access administrators are the BootstrapAdministrators. When true, an existing access administrator may author exactly one narrow rule shape - a whole-tree Admin rule on the sys-auth-policy tree - to delegate access administration to a chosen user or group; every other rule shape on the reserved namespace stays rejected fail-closed. Turning it off stops new delegations but does not revoke an existing grant (remove that rule to revoke). |
AllTreesGrantsEnabled |
bool |
false |
Whether a cluster-wide all-trees rule (scope Tree:*, the LatticeScope.ClusterWideTreeId sentinel) governs every ordinary application tree. Off by default: while off, authoring a data-plane Tree:* rule is rejected at the policy store with an ArgumentException that tells the operator to enable the tier first, so an inert data-plane wildcard grant can no longer be persisted silently (a pre-existing inert rule stays listed for visibility but never grants or denies until the tier is enabled). When true, the decision engine consults the Tree:* bucket for every non-system tree using a four-tier precedence: (1) an all-trees deny is returned outright; (2) else the target tree's own most-specific-wins verdict applies (a specific deny overrides a global allow); (3) else an all-trees allow grants access; (4) else DefaultEffect. The control-plane namespaces - the reserved sys-auth-* namespace, the tenant-registry sys-tenant-* namespace, the app-registry sys-app-* namespace, and the delegated tenant-administration capability namespace (LatticeTenantAdminScope.TenantScopePrefix, _lattice_tenant_admin_) - and a literal request targeting the sentinel * itself are never governed by the tier (fail-closed), and operation-bit separation is preserved so a data-plane grant never confers Telemetry. Telemetry and AppInstall Tree:* grants are unaffected by this flag - a wildcard rule carrying only those scopeless capabilities stays authorable, and in force, with the tier off. The authoring check tests only the data-plane mask (LatticeAuthOperations.All), so a Tree:* rule carrying only Replication and/or TreeLifecycle is also accepted with the tier off, but, unlike telemetry, it grants and denies nothing until the tier is enabled. Turning it off stops new all-trees evaluation but does not delete existing Tree:* rules (remove the rule to retire it). |
UserRuleBeatsGroupRuleAtEqualScope |
bool |
true |
When true, a rule whose subject is the requesting user is treated as more specific than a rule whose subject is one of the user's groups at the same scope, so the user-specific rule wins the tie (including a user-specific allow overriding a group-level deny at equal scope). When false, user and group rules are equally specific at equal scope, so the deny-overrides tie-break decides between them. |
HistoryRetentionMode |
HistoryRetentionMode |
MetadataOnly |
The retention mode for the durable per-key history captured on the sys-auth-policy tree. History is never disabled by default. |
HistoryRetentionWindow |
TimeSpan? |
null |
The age after which a policy history revision row expires, or null for no age bound. Must be strictly positive when supplied. |
EnableDurableHistoryView |
bool |
true |
Whether to create the durable per-key history materialised view over the sys-auth-policy tree so policy changes remain auditable beyond the source write-ahead-log window. |
StrictConsistencyTrees |
ISet<string>? |
null |
The set of tree ids opted into the optional strict-consistency policy-epoch fence. Empty / null is the eventual path: enforcement never consults the fence, so a deployment that does not opt in pays zero added cost and keeps last-writer-wins convergence. When a tree id is listed, a user write to that tree - a request carrying Write, Delete, RangeDelete, CrdtApply, AtomicWrite, BulkLoad, Admin, or Restore - is rejected if the caller stamped a required policy-epoch floor onto the ambient context (LatticePolicyEpochFenceContext.RequireAtLeast) and this cluster's locally compiled policy epoch has not yet caught up. Reads and internal / system-origin / replication-applied writes are never fenced. Entries must be non-null and non-empty. |
EnableAuditSink |
bool |
false |
Master switch for the audit sink seam. When false, a gated decision builds no decision event and dispatches to no audit sink, so auditing is strictly zero-cost on the hot path. Set to true to fan every admissible decision out to the registered sinks. Independent of the observability meter, whose counters and latency histogram are always available when an OpenTelemetry listener is attached. |
AuditVerbosity |
LatticeAuthAuditVerbosity |
DenyOnly |
Which decisions are dispatched to the audit sinks when EnableAuditSink is set. DenyOnly audits refusals only; AllDecisions audits every gated decision, allow and deny, at materially higher event volume. |
AuditSamplingRatio |
double |
1.0 |
The fraction of admissible decisions (those passing the AuditVerbosity filter) actually dispatched to the audit sinks, in the inclusive range 0.0 to 1.0. 1.0 audits every admissible decision; 0.0 suppresses all dispatch even while EnableAuditSink is set; 0.1 samples roughly one in ten. Sampling never affects the observability meter. |
EnableDurableAuditTrail |
bool |
false |
Whether to also append every dispatched decision event to the durable, append-only sys-auth-audit lattice tree. Opt-in and costs nothing until enabled. Requires EnableAuditSink to be set for any event to be produced. |
AuditTrailTimeToLive |
TimeSpan? |
null |
The time-to-live applied to each durable audit-trail row, or null for no age bound. Must be strictly positive when supplied. Only consulted when EnableDurableAuditTrail is set. |
Discovering the effective posture
Both tier flags (AllTreesGrantsEnabled and AccessAdministrationDelegationEnabled) are opt-in and off by default, and a disabled tier is otherwise easy to miss - an all-trees grant is inert and a delegation grant is unauthorable. To make the deployment's opt-in state observable without inspecting configuration, the posture is surfaced on four read paths:
- Start-up log.
AddLatticeAuthregisters a hosted service that logs one informational line at silo start:Lattice authorization posture: DefaultEffect=..., AllTreesGrantsEnabled=..., AccessAdministrationDelegationEnabled=.... It is the first place an operator sees the effective posture. ILatticeAuthAdmin.ExplainAsync. The returnedAuthExplanationcarries aPosture(AuthPolicyPosture) reporting both flags, so an explain of a request that fell through toDefaultEffectshows whether aTree:*rule would have applied had the tier been on.ILatticeAuthAdmin.EffectivePermissionsAsync. The returnedAuthEffectivePermissionscarries the samePosture, so a listing that includes an inertTree:*rule also reports that the tier is off.ILatticeAuthAdmin.GetAccessModelAsync. The returnedAccessModelDescriptorcarriesAllTreesGrantsEnabledandAccessAdministrationDelegationEnabled, which the Explorer's Access area renders as on/off entries in its access-posture banner, beside the authentication mode.
The AuthPolicyPosture record reports only the two opt-in tier flags; DefaultEffect is surfaced separately on AuthExplanation.