Orleans.Lattice.Api.Auth
This page documents Orleans.Lattice.Api.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 README.md, and llms.txt lists every page.A configuration and control facade for the Orleans.Lattice authorization system - administer the membership directory and the authorization policy store, and introspect policy (why a subject is or is not authorized, and what rules are in effect for them), over a single transport-agnostic surface.
What is it?
Orleans.Lattice.Api.Auth is the control plane of a lattice cluster's authorization system. The core data plane is reached through .NET grain interfaces; the Orleans.Lattice.Membership package adds the membership directory, and the Orleans.Lattice.Auth package adds the policy store and the enforcing access gate. This package adds the administrative surface an operator dashboard, a language-agnostic control tool, or an internal admin service needs to manage membership and policy and to explain authorization decisions - without embedding the Orleans client.
It is the authorization sibling of the read-only Orleans.Lattice.Api.State and the read-write Orleans.Lattice.Api.Data packages, and is built the same way, in two layers:
- A transport-agnostic facade.
ILatticeAuthAdmin(a public contract in the sharedOrleans.Lattice.Api.Abstractionspackage) exposes membership CRUD, policy CRUD,ExplainAsync,EffectivePermissionsAsync, and identity-directory search and validation over plain request/response records. The facade has no wire dependency, so the same surface serves an in-process consumer and a remote one. - A code-first gRPC binding (the sibling
Orleans.Lattice.Api.Auth.Grpcpackage). That binding projects this facade onto a remotely callable service. Its RPC messages carry these facade DTOs, but the gRPC contract wraps most of them in that package's own code-first request/response envelopes (for example a group read travels as anAuthGroupRef, a rule write as anAuthPutRule), all marshalled with the Orleans binary serializer; the wire types are the contract records, not the facade DTOs verbatim. This package intentionally ships no transport of its own; it is the contract every binding adapts over.
Core properties
- Opt-in and absent by default. Nothing registers unless the host calls
AddLatticeAuthApi()on the silo. A cluster that does not add the package has no admin surface, and once added the facade performs no background work until a method is called. - Administrator-gated, fail-closed. This is a control plane, so every operation - read or write - first authorizes the caller as an administrator through the same enforcement primitive the in-cluster data path uses, anchored on the authorization package's bootstrap root-of-trust. A non-administrator or anonymous caller is refused, and nothing is mutated. The facade adds no bespoke, un-authorized write path to the membership or policy trees.
- Explain parity with the gate.
ExplainAsyncproduces its verdict by consulting the same access gate the data plane consults, so for the subject it evaluates the verdict is the decision enforcement would reach. That subject is rebuilt from the membership directory - the named id plus its transitive directory group closure - so groups a caller's token asserts (or thatLatticeMembershipOptions.ClaimToGroupsprojects) are not part of it, and under theTokenOnlygroup-merge mode, where enforcement ignores directory groups, the explained closure can differ from a live caller's. The gate also runs in the explain call's own ambient context, not one the subject would supply: withOrleans.Lattice.Tenancyinstalled, tenant isolation checks the explaining caller's active-tenant assertion (the gRPC binding stamps none on this call), so a verdict on a tenant-ownedt/...tree can differ from the decision the subject would receive acting as its own tenant. The reported matched rules are advisory debugging detail layered on top of that verdict. - Transport-agnostic. The facade is the contract; a gRPC binding is one adapter. The same records flow to an in-process consumer and a remote one.
Ordering
AddLatticeAuthApi() must be called after AddLatticeAuth(...): the authorization registration is the source of truth for the policy store and the access gate this facade administers and introspects, and it in turn requires AddLatticeMembership(), which supplies the membership directory. Calling it first fails fast at registration with an actionable message rather than failing obscurely at silo start.
Surface (v1)
Membership administration
| Operation | Facade method |
|---|---|
| Create / replace a group | UpsertGroupAsync |
| Read a group | GetGroupAsync |
| Remove a group | RemoveGroupAsync |
| List groups (paged) | ListGroupsAsync |
| Add a membership edge | AddMemberAsync |
| Remove a membership edge | RemoveMemberAsync |
| List a group's direct members | ListGroupMembersAsync |
| List a subject's transitive groups | ListSubjectGroupsAsync |
When LatticeIdentityDirectoryOptions.ValidationRequired is set and a real identity-directory provider is active, UpsertGroupAsync and AddMemberAsync resolve every id they reference after the administrator check and before any write, and reject an unresolvable or mis-kinded id with LatticeDirectoryValidationException (an ArgumentException); see Fail-closed create validation.
Policy administration
| Operation | Facade method |
|---|---|
| Create / replace a rule | PutRuleAsync |
| Read a rule | GetRuleAsync |
| Remove a rule | RemoveRuleAsync |
| List all rules (paged) | ListRulesAsync |
| List a tree's rules (paged) | ListRulesForTreeAsync |
PutRuleAsync and RemoveRuleAsync go through the authorization policy store, which refuses a rule id in the app-owned app: namespace (LatticeAppRuleIds.Prefix): those rules belong to installable apps and are written only by the app compiler, so the call throws LatticeAppOwnedRuleException (an ArgumentException), even for a bootstrap administrator. Author a separate rule outside the prefix to narrow what an app's users may do.
ListRulesForTreeAsync(MCP toollattice_auth_list_rules_for_tree) returns a tree's own rules and every rule in the cluster-wide*bucket (scopeTree:*, authored withLatticeScope.ClusterWide()): the all-trees rules that govern it, and any scopelessTelemetryorAppInstallgrant alongside them. All-trees rules are stored under the reserved*tree id and carryScope.TreeId == "*", so you can tell them apart from exact-tree rules; listing the reserved*tree itself returns only its own bucket. WhenAllTreesGrantsEnabledis on (see All-trees grants below) these rules actively grant or deny across every application tree. While the flag is off, a new data-planeTree:*rule cannot be authored at all - the policy store rejectsPutRuleAsyncwith anArgumentException- so any data-planeTree:*rule you see was authored while the tier was enabled and is now inert (listed for visibility only, granting or denying nothing until the tier is re-enabled or the rule is removed). UseExplainAsync/EffectivePermissionsAsyncfor the resolved verdict a subject's access actually receives.
Policy introspection
| Operation | Facade method | Purpose |
|---|---|---|
| Explain a verdict | ExplainAsync |
Returns the gate's allow/deny verdict for a subject / operation / scope, plus the authored rules that apply (including cluster-wide Tree:* wildcard rules that govern the target tree) - for debugging policy. Pass subjectKind: LatticeSubjectSelectorKind.Group to explain the decision for a group (evaluated as a member of that group and its ancestors); the default is User. |
| Resolve effective permissions | EffectivePermissionsAsync |
Returns every authored rule that names the subject directly or through one of its groups - allow and deny alike, capped at MaxExplanationRules - for dashboards and UX. It lists rules rather than resolving a verdict: a listed rule can be overridden by a more specific one, or be a Tree:* rule that is inert while AllTreesGrantsEnabled is off, so use ExplainAsync for the decision a request actually receives. Pass subjectKind: LatticeSubjectSelectorKind.Group to resolve the rules for a group evaluated as a member of itself and its ancestor groups (its transitive group closure), not the named group alone; the default is User. |
Identity directory and access model
| Operation | Facade method | Purpose |
|---|---|---|
| Search or browse principals | SearchDirectoryAsync |
Searches the configured identity directory for matching users and groups. |
| Resolve one principal | ResolveDirectoryPrincipalAsync |
Resolves a single directory principal by id, returning no principal when none exists. |
| Read access-model posture | GetAccessModelAsync |
Returns the cluster's best-effort access model descriptor, including the live all-trees and access-administration-delegation posture flags. |
Access administration delegation
By default the only subjects who can administer access (manage groups, membership, and policy rules) are the cluster's bootstrap administrators - the statically-configured LatticeAuthOptions.BootstrapAdministrators root of trust. "Access administration" is the Admin capability on the reserved policy tree sys-auth-policy (its id is the public constant LatticeAuthReservedTrees.PolicyTreeId); every call to this facade requires a whole-tree Admin verdict on that tree from the enforcement gate.
You can delegate access administration to another user or group by authoring one narrow rule: a whole-tree Admin rule on the sys-auth-policy tree for that subject. The effect is unconstrained: an Allow delegates access administration to the subject, and the store equally permits a Deny of the same shape (a whole-tree Admin Deny on sys-auth-policy) to revoke a delegated subject through policy. Bootstrap administrators are the root of trust and are never affected either way. This is off by default and must be enabled per deployment:
- Set
AccessAdministrationDelegationEnabled = truein theAddLatticeAuth(options => ...)configuration. Existing clusters are unchanged until they opt in. - With the flag on, an existing access administrator (a bootstrap administrator, or a subject who already holds the delegated grant) may author exactly the whole-tree
Admindelegation shape onsys-auth-policy- of either effect (anAllowto delegate, or aDenyto revoke through policy). No other rule shape on the reservedsys-auth-*namespace becomes authorable: another reserved tree, a key/prefix scope, or any operation set that is not exactlyAdminis still rejected fail-closed by the policy store. With the flag off, authoring any rule on the reserved namespace is rejected, exactly as before. - The subject then satisfies the same administrator check every facade call makes (
PutRuleAsync,ListRulesAsync, membership CRUD, and the rest), because the gate honours the matchedAllowon the reserved namespace. Bootstrap administrators remain the root of trust and are never affected by policy.
In the Explorer's Access area, the rule editor offers an Access administration (delegation) scope once the cluster reports delegation enabled: pick the target user or group, choose that scope, tick Admin, and save. The editor supplies the reserved sys-auth-policy tree and the whole-tree scope, so you never pick the reserved tree from the catalog, and the rule tables show a delegated grant's scope as access administration so it is easy to tell apart from an ordinary whole-tree rule. See Managing access from the Explorer.
Security caveat. A delegated access-administration grant confers full authority over membership and policy, including the ability to delegate further. It also passes every check that defines a platform operator as whole-tree Admin on sys-auth-policy - notably the tenant-administration facades of Orleans.Lattice.Api.TenantAdmin, so where that package is registered a delegate can create, suspend, delete, and set quotas for any tenant. Grant it sparingly. Turning AccessAdministrationDelegationEnabled back off stops new delegations from being authored but does not revoke a grant that already exists - remove that rule (via RemoveRuleAsync, or the Explorer rule list) to revoke the delegation.
All-trees grants
An all-trees grant is a rule whose scope is the cluster-wide sentinel Tree:* (authored with LatticeScope.ClusterWide()). When enabled, it governs every ordinary application tree at once, so an operator can grant (or deny) a subject a capability across the whole cluster without authoring one rule per tree. This reuses the existing * sentinel and is off by default:
- Set
AllTreesGrantsEnabled = truein theAddLatticeAuth(options => ...)configuration. Existing clusters are byte-for-byte unchanged until they opt in. While the flag is off, authoring a new data-planeTree:*rule is rejected fail-closed - the policy store throws anArgumentExceptionfromPutRuleAsyncrather than silently persisting a rule that does nothing - and a data-planeTree:*rule authored earlier (while the tier was enabled) stays inert, listed for visibility but never granting or denying, until the tier is re-enabled. A pureTelemetryorAppInstallwildcard rule is unaffected and remains authorable, and in force, while the flag is off, because a scopeless cluster-wide capability resolves against the*bucket regardless of the tier flag. ATree:*rule carrying onlyReplicationand/orTreeLifecycleis also accepted while the flag is off - the authoring check tests only the data-plane mask,LatticeAuthOperations.All- but it grants and denies nothing until the tier is enabled. - With the flag on, the decision engine consults the
Tree:*bucket for every non-system tree using a four-tier precedence (most authoritative first):- All-trees deny - a matched
Tree:*deny is returned outright; a global deny is never overridden by a specific-tree allow. - Specific-tree verdict - the target tree's own most-specific-wins verdict (a specific deny overrides a global allow, and a specific allow stands).
- All-trees allow - a matched
Tree:*allow grants access when the target tree has no matching rule of its own. - Default effect - otherwise the cluster's
DefaultEffectapplies.
- All-trees deny - a matched
- System-tree exclusion (fail-closed). The all-trees tier is never consulted for a control-plane namespace - the reserved authorization namespace (
sys-auth-*,LatticeAuthReservedTrees.IsReserved), the tenant-registry namespace (sys-tenant-*), the installable-apps namespace (sys-app-*: the app registry, activation status andsys-app-treestree ownership ledger), or the delegated tenant-administration capability namespace (_lattice_tenant_admin_*,LatticeTenantAdminScope.TenantScopePrefix) - or for a literal request targeting the sentinel id*itself. ATree:*allow therefore can never satisfy a control-plane admin check or leak into access or tenant administration. - Operation-bit separation is preserved. A widened data-plane
Tree:*grant never confersTelemetry, and a telemetryTree:*grant never confers a data-plane operation; the operation mask semantics are unchanged. - A real tree literally named
*is never creatable: the core lattice grain rejects user-origin creation or mutation of a tree whose id is exactly*, so the sentinel can only ever be an authorization scope.
In the Explorer's Access area, the rule editor's All trees (cluster-wide) scope supplies the Tree:* scope: pick the target user or group, choose that scope, the operations, and the effect, and save. While all-trees grants are off, the scope hint says that data operations in a cluster-wide rule are refused and that the App install and Telemetry capabilities can still be granted. A data-plane all-trees rule can only be authored once an operator has enabled all-trees grants on the silo - the save is rejected otherwise - and it takes effect immediately while the tier is on; the rule tables show its scope as all trees (cluster-wide) so it is easy to tell apart from an ordinary whole-tree rule. See Managing access from the Explorer.
Security caveat. An all-trees grant is broad by design - it applies to every application tree, including trees created after the rule was authored. Grant it sparingly, and prefer a specific-tree deny to carve out an exception. Turning AllTreesGrantsEnabled back off stops new all-trees evaluation but does not delete existing Tree:* rules - remove the rule to retire it.
Wire model
Every request / response record is Orleans-serialized with a stable, compact alias (the oli. prefix). Group records are the facade's own serializable DTOs (AuthGroup, which like every facade DTO ships in the shared Orleans.Lattice.Api.Abstractions package); rules are surfaced as the durable LatticeAuthorizationRule policy model directly, so a binding sees the same rule shape the store persists. Only the catalog list endpoints - ListGroupsAsync, ListRulesAsync, and ListRulesForTreeAsync - page with an exclusive continuation-token cursor (AuthPageRequest / Auth*Page, see Paging and group DTOs), mirroring the Orleans.Lattice.Api.State catalog paging convention. The membership lookups ListGroupMembersAsync and ListSubjectGroupsAsync are not paged: each returns the full IReadOnlyList<string> of member (or group) ids in a single call.
Facade method signatures
All 18 ILatticeAuthAdmin methods, exactly as declared in the shared Orleans.Lattice.Api.Abstractions package. Every method takes a trailing CancellationToken cancellationToken = default.
| Method | Signature |
|---|---|
UpsertGroupAsync |
Task UpsertGroupAsync(AuthGroup group, CancellationToken cancellationToken = default) |
GetGroupAsync |
Task<AuthGroup?> GetGroupAsync(string groupId, CancellationToken cancellationToken = default) |
RemoveGroupAsync |
Task RemoveGroupAsync(string groupId, CancellationToken cancellationToken = default) |
ListGroupsAsync |
Task<AuthGroupPage> ListGroupsAsync(AuthPageRequest request, CancellationToken cancellationToken = default) |
AddMemberAsync |
Task AddMemberAsync(string groupId, string memberId, MembershipMemberKind memberKind = MembershipMemberKind.User, CancellationToken cancellationToken = default) |
RemoveMemberAsync |
Task RemoveMemberAsync(string groupId, string memberId, CancellationToken cancellationToken = default) |
ListGroupMembersAsync |
Task<IReadOnlyList<string>> ListGroupMembersAsync(string groupId, CancellationToken cancellationToken = default) |
ListSubjectGroupsAsync |
Task<IReadOnlyList<string>> ListSubjectGroupsAsync(string memberId, CancellationToken cancellationToken = default) |
PutRuleAsync |
Task PutRuleAsync(LatticeAuthorizationRule rule, CancellationToken cancellationToken = default) |
GetRuleAsync |
Task<LatticeAuthorizationRule?> GetRuleAsync(string treeId, string ruleId, CancellationToken cancellationToken = default) |
RemoveRuleAsync |
Task<bool> RemoveRuleAsync(string treeId, string ruleId, CancellationToken cancellationToken = default) |
ListRulesAsync |
Task<AuthRulePage> ListRulesAsync(AuthPageRequest request, CancellationToken cancellationToken = default) |
ListRulesForTreeAsync |
Task<AuthRulePage> ListRulesForTreeAsync(string treeId, AuthPageRequest request, CancellationToken cancellationToken = default) |
ExplainAsync |
Task<AuthExplanation> ExplainAsync(string subjectId, LatticeOperation operation, LatticeScope scope, LatticeSubjectSelectorKind subjectKind = LatticeSubjectSelectorKind.User, CancellationToken cancellationToken = default) |
EffectivePermissionsAsync |
Task<AuthEffectivePermissions> EffectivePermissionsAsync(string subjectId, LatticeSubjectSelectorKind subjectKind = LatticeSubjectSelectorKind.User, CancellationToken cancellationToken = default) |
SearchDirectoryAsync |
Task<DirectorySearchResult> SearchDirectoryAsync(DirectorySearchRequest request, CancellationToken cancellationToken = default) |
ResolveDirectoryPrincipalAsync |
Task<DirectoryPrincipalDescriptor?> ResolveDirectoryPrincipalAsync(string principalId, CancellationToken cancellationToken = default) |
GetAccessModelAsync |
Task<AccessModelDescriptor> GetAccessModelAsync(CancellationToken cancellationToken = default) |
ListGroupsAsync, ListRulesAsync, and ListRulesForTreeAsync return a page record (AuthGroupPage / AuthRulePage) carrying the items plus a continuation cursor; ListGroupMembersAsync and ListSubjectGroupsAsync return the full id list unpaged.
Result and DTO types
AccessModelDescriptor (returned by GetAccessModelAsync)
| Field | Type | Meaning |
|---|---|---|
AuthenticationMode |
AccessAuthenticationMode |
Best-effort in-silo authentication posture (see the enum below). |
RulesEnforced |
bool |
Whether the access gate actually enforces authorization rules. |
DirectoryAvailable |
bool |
Whether an identity directory is configured for validating candidate ids. |
DirectoryProviderId |
string |
The configured directory provider's stable id (for example "entra" or "static"); the no-op provider's "null" when no directory is configured. |
DirectoryExplanation |
string |
The active provider's operator-facing description of what a valid principal id is (its DescribeEntry text for a group), rendered as create-form guidance; the no-op provider's text says ids are accepted without validation. |
LocalMembershipEffective |
bool |
Whether locally-administered group membership (the groups and member edges this facade manages) contributes to a subject's effective groups at authorization time; false under the token-only group-merge mode, where groups come solely from the identity-provider token and local membership administration is inert. |
AllTreesGrantsEnabled |
bool |
The live all-trees-grants tier flag. |
AccessAdministrationDelegationEnabled |
bool |
The live access-administration-delegation tier flag. |
AuthExplanation (returned by ExplainAsync)
| Field | Type | Meaning |
|---|---|---|
SubjectId |
string |
The subject the verdict was resolved for. |
GroupIds |
IReadOnlyList<string> |
The subject's transitively-expanded group closure as the membership directory resolves it, ascending (for a Group subject it includes the named group itself). Token-asserted and claim-projected groups are not included. |
Operation |
LatticeOperation |
The operation the verdict was resolved for. |
Scope |
LatticeScope |
The scope the verdict was resolved for. |
Allowed |
bool |
The gate's verdict (possibly partial - see Filtered). |
Filtered |
bool |
true when the allow is partial: a per-key filter applies to a tree- or prefix-scoped request. Always false for a point (key-scoped) request. |
Reason |
string? |
A human-readable reason, or null for a plain unqualified allow. |
DefaultEffect |
LatticeEffect |
The closed-world default effect applied when no rule matches. |
MatchedRules |
IReadOnlyList<LatticeAuthorizationRule> |
The authored rules whose subject, operations, and scope overlap the request, from the target tree and the cluster-wide * bucket, capped at MaxExplanationRules (advisory; Allowed is authoritative). The list is assembled independently of the verdict: it is empty when no authored rule matches, but it can cite a rule that did not decide the verdict - for example one naming a bootstrap administrator, whose allow comes from the bypass, or a data-plane Tree:* rule that is inert while AllTreesGrantsEnabled is off (see Posture). |
Posture |
AuthPolicyPosture |
The cluster's opt-in posture (both tier flags), so a caller can tell an in-force all-trees rule from an authored-but-inert one. |
AuthEffectivePermissions (returned by EffectivePermissionsAsync)
| Field | Type | Meaning |
|---|---|---|
SubjectId |
string |
The subject the permissions were resolved for. |
GroupIds |
IReadOnlyList<string> |
The subject's transitive directory group closure, ascending, resolved exactly as for AuthExplanation.GroupIds. |
Rules |
IReadOnlyList<LatticeAuthorizationRule> |
Every authored rule whose subject is the subject itself or one of its groups, allow and deny alike, read from the live policy store, capped at MaxExplanationRules, and ordered by (governed tree id, rule id). A listing rather than a verdict; see EffectivePermissionsAsync above. |
Posture |
AuthPolicyPosture |
The cluster's opt-in posture (both tier flags). |
AuthPolicyPosture
| Field | Type | Meaning |
|---|---|---|
AllTreesGrantsEnabled |
bool |
The live all-trees-grants tier flag. |
AccessAdministrationDelegationEnabled |
bool |
The live access-administration-delegation tier flag. |
Paging and group DTOs
AuthPageRequest (input to ListGroupsAsync, ListRulesAsync, and ListRulesForTreeAsync):
| Field | Type | Meaning |
|---|---|---|
PageSize |
int |
Maximum entries per page. Defaults to AuthPageRequest.DefaultPageSize (100); a value below 1 falls back to that default and a value above AuthPageRequest.MaxPageSize (1000) is clamped to it. EffectivePageSize reports the size actually applied. |
PageToken |
string? |
The exclusive continuation cursor - the previous page's NextPageToken - or null to start from the beginning. |
ActiveTenantOnly |
bool |
When true, ListRulesAsync lists only the rules whose governed tree is one of the caller's active tenant's own trees (t/{tenant}/{name}, or a bare tree id for the reserved default tenant). Cluster-wide Tree:* rules and rules on platform trees belong to no tenant and are never listed; read them with ListRulesForTreeAsync for *. The tenant is never taken from the request: it is the caller's validated active-tenant assertion, or the default tenant when the call asserts none, and an assertion the caller may not make is refused, never defaulted. The narrowing happens before the page is cut, so every page but the last is full. false (the default) lists the whole catalogue. Ignored by ListGroupsAsync and ListRulesForTreeAsync. |
AuthGroupPage (returned by ListGroupsAsync) and AuthRulePage (returned by ListRulesAsync and ListRulesForTreeAsync):
| Field | Type | Meaning |
|---|---|---|
Entries |
IReadOnlyList<AuthGroup> / IReadOnlyList<LatticeAuthorizationRule> |
The page's groups, ordered by group id, or its rules, ordered by (governed tree id, rule id). |
NextPageToken |
string? |
The cursor to pass back as the next request's PageToken, or null on the final page. |
Tenant |
string? |
AuthRulePage only. The tenant a narrowed listing (ActiveTenantOnly) was narrowed to, or null for a page of the whole catalogue. A caller that asked for a narrowed page and reads null here was answered by a server that predates the narrowing, which ignores the flag and lists the whole catalogue. |
AuthGroup (input to UpsertGroupAsync; returned by GetGroupAsync and inside AuthGroupPage):
| Field | Type | Meaning |
|---|---|---|
GroupId |
string |
The stable group id (the directory key). |
DisplayName |
string? |
An optional human-readable display name. |
Identity-directory DTOs
DirectorySearchRequest (input to SearchDirectoryAsync):
| Field | Type | Meaning |
|---|---|---|
Term |
string |
The typeahead / browse term (defaults to empty for a browse). |
Kind |
DirectoryPrincipalKind? |
Restrict to users or groups, or null for both. |
PageSize |
int |
Requested page size. |
ContinuationToken |
string? |
Opaque cursor for the next page, or null for the first. |
DirectorySearchResult (returned by SearchDirectoryAsync):
| Field | Type | Meaning |
|---|---|---|
Principals |
IReadOnlyList<DirectoryPrincipalDescriptor> |
The matching principals. |
ContinuationToken |
string? |
Opaque cursor for the next page, or null when exhausted. |
Available |
bool |
false (with an empty result) when no directory is configured, rather than erroring. The static DirectorySearchResult.Unavailable is this state. |
DirectoryPrincipalDescriptor (returned by ResolveDirectoryPrincipalAsync and inside a search result):
| Field | Type | Meaning |
|---|---|---|
Id |
string |
The exact principal id. |
DisplayName |
string |
The principal's display name. |
Kind |
DirectoryPrincipalKind |
Whether the principal is a user or a group. |
Claims |
IReadOnlyDictionary<string, string>? |
Optional provider claims, or null. |
AccessAuthenticationMode (enum)
Best-effort classification of what the in-silo identity registrations reveal, surfaced on AccessModelDescriptor.AuthenticationMode. It is not a claim about every transport in front of the cluster (a transport-terminated scheme is refined by the capability probe layered above this facade).
| Value | Meaning |
|---|---|
Unknown (0) |
Posture could not be determined: no credential authenticator (not even the anonymous fallback) is registered. |
Anonymous (1) |
Only the anonymous fallback authenticator is registered, so every caller resolves to the anonymous subject and no caller is ever authenticated. |
Claims (2) |
At least one real credential authenticator (for example a JWT / claims authenticator) is registered, so the silo can authenticate a caller from its token claims. |
Basic (3) |
Reserved for a flat username / password (Basic) scheme. Never reported by this facade - the flat-Basic authorizer lives at the transport layer, out of this facade's view - but reserved so the transport capability probe above can surface it. |
Explicitly deferred
The following are not in v1 and are deliberately left out so a caller cannot mistake their absence for a bug:
- A condition / attribute predicate language. Rules carry an opaque, reserved condition string that is not evaluated in this version, matching the policy model the store persists.
- Bulk import / export of policy or membership. Administration is per-record; a caller composes bulk workflows over the CRUD surface.
Reference
- Configuration - every public options property, its type, and its default.
See also
Orleans.Lattice.Auth- the policy store and enforcing access gate this facade administers.Orleans.Lattice.Membership- the user / group directory backing subject resolution.Orleans.Lattice.Api.StateandOrleans.Lattice.Api.Data- the read-only and read-write data-plane facades this control facade is modelled on.