Installable apps
This page is part of 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 single-silo tour of the installable App concept: an embedded manifest, a version-pinned operator consent, generated app-owned authorization rules, and activation / teardown through the Apps API facade.
What it shows
One in-process Orleans silo runs the control-plane stack:
- Membership (
AddLatticeMembership) resolves the ambient caller credential into a subject and group membership. - Auth (
AddLatticeAuth) installs the fail-closed enforcement gate. - Apps (
AddLatticeApps) registers an in-image app source, registry and activation pipeline. - Apps API (
AddLatticeAppsApi) adds the operator facadeILatticeAppsControl.
The program walks five acts:
- Inspect before trust. The embedded manifest is loaded with
AppManifestResources, then described throughDescribeAsyncbefore install. Both paths expose requested trees, roles and operations without activating app code. - Install as an operator. A bootstrap administrator installs version
1.0.0, binds the app role to a membership group, and pins a structural ceiling. A caller withoutAppInstallis denied before any app metadata is touched. - Enable and use the app tree. Activation creates the structural tree
a/sample-crm/records, compiles rules whose ids start withapp:, and lets a member of the bound group write and read while a non-member is denied. - Guard rails. Direct operator writes to an app-owned rule id are rejected
with
LatticeAppOwnedRuleException. Reducing consent below the manifest's requested operations records a structured activation failure and withdraws the app rules without stopping the silo. - Disable and uninstall. Disable and uninstall each withdraw whatever app-owned rules remain - none do by this point, because the failed activation in act 4 already withdrew them - and uninstall soft-deletes the app tree. Uninstall does not purge the data: the tree stays recoverable until its soft-delete window (30 minutes in this manifest) elapses.
Run it
dotnet run --project samples/InstallableApps
Expected tail:
== Act 5: disable and uninstall ==
DisableAsync -> Disabled (changed: True)
UninstallAsync -> Uninstalled (changed: True)
app-owned rules after uninstall -> 0
app tree after uninstall -> registered: True; soft-deleted: True
[OK] installable app lifecycle ran end-to-end; consent and app-owned rule guards stayed fail-closed.
The process exits 0 on success and 1 if any guard fails to hold.
How authorization works here
The gate runs default-deny. platform-operator is configured as a bootstrap
administrator and therefore holds the cluster-wide AppInstall operation that
every Apps API verb except the advisory capability probe requires. The manifest's
writer role is bound to the membership group sample-crm-writers; activation
compiles that binding into ordinary authorization rules over
a/sample-crm/records. Apart from the bootstrap administrator, only alice, the
user placed in that group, can read and write the app tree.
The sample intentionally reduces the app's consent to Read after a successful
enable. The manifest still requests Read and Write, so reconciliation fails
with CeilingExceeded, withdraws the compiled rules, reports the app as failed,
and leaves the silo healthy.
Where to go next
- App manifests, installation, consent and activation: docs/lattice.apps.
- The transport-independent app-control facade: docs/lattice.api.apps.
- Exposing app-declared MCP tools: docs/lattice.api.mcp.apps.
- Driving the facade remotely over gRPC: docs/lattice.api.apps.grpc.