Appearance
Mount claims
A mount claim is a record in system.registry that says: "this runtime, identified by providerRuntimeId, is currently serving the logical mount <X>." Claims are how the registry turns logical names into concrete providers.
Source:
projects/matrix-3/packages/system-platform/src/ServiceRegistryActor.tslines 17–31 (entry shape) and 118+ (handler implementations).
The claim record
A claim is an IRegistryEntry (verbatim from ServiceRegistryActor.ts line 17):
typescript
interface IRegistryEntry {
logicalMount: string; // public name, e.g. 'chat.conversation'
componentId: string; // the actor instance id
componentType: string; // class name
authorityRoot: string; // owning Space / account root
scope: string; // optional sub-scope
providerRuntimeId: string; // process serving this claim
runtimeWireRoot: string; // wire prefix of that runtime
localMount: string; // mount inside that runtime
packageName: string; // owning package
metadata: Record<string, unknown>;
registeredAt: number;
lastHeartbeatAt: number;
heartbeatTtlMs: number; // how long until the claim is "stale"
}Read view (IRegistryView) extends this with:
typescript
interface IRegistryView extends IRegistryEntry {
status: 'live' | 'stale';
expiresAt: number;
}Lifecycle
1. Register
A runtime registers a claim when it mounts an actor at a logical mount:
op: registry.register
payload: {
logicalMount: 'chat.conversation',
componentId: 'chat-conversation-01',
componentType: 'ChatConversationActor',
providerRuntimeId: 'rt-chat-dev-01',
runtimeWireRoot: 'COM.NIMBLETEC.RICHARD-SANTOMAURO',
localMount: 'chat.conversation',
packageName: 'chat',
metadata: { ... },
heartbeatTtlMs: 30000
}system.registry stores the entry, emits registry.registered on $events, and returns { ok: true, entry }.
2. Heartbeat
While the runtime is alive, it must heartbeat the claim before heartbeatTtlMs elapses. The default TTL is 30 seconds (ServiceRegistryActor.ts line 119: private static readonly DEFAULT_HEARTBEAT_TTL_MS = 30_000).
op: registry.heartbeat
payload: { providerRuntimeId: 'rt-chat-dev-01' }
OR { logicalMount: 'chat.conversation', providerRuntimeId: 'rt-chat-dev-01' }Heartbeats refresh lastHeartbeatAt. The registry emits registry.heartbeat on $events. A claim is live while now - lastHeartbeatAt < heartbeatTtlMs, stale otherwise.
3. Resolve
Callers that want the claim ask the registry:
op: registry.resolve
payload: { logicalMount: 'chat.conversation' }The registry returns the live providers (or all providers including stale if includeStale: true). Each provider entry contains runtimeWireRoot and localMount, which the caller uses to address the actual provider.
4. Unregister
On graceful shutdown:
op: registry.unregister
payload: { providerRuntimeId: 'rt-chat-dev-01' }This removes all claims for that runtime. Emits registry.unregistered on $events.
Stale claims
If a runtime crashes without unregistering, its claims go stale after heartbeatTtlMs. The registry does NOT auto-evict stale claims today — they remain in the table marked status: 'stale'. Resolution defaults to filtering them out (includeStale: false). Callers that want to inspect post-crash state pass includeStale: true.
A future eviction sweep would clean these up; today the stale records remain visible in registry.list and serve as forensic state.
Status: target state. Automatic stale-claim eviction is on the docker-npm-parity workstream backlog. Current behavior leaves stale records in place; producing a cleanup is a follow-up.
Multiple providers per mount
A single logical mount can have multiple providers (multi-provider mount). Each provider's claim is keyed by providerRuntimeId, so they are distinct entries. registry.providers { logicalMount: '...' } returns the list. Resolution policy is up to the caller.
For singleton mounts (system.runtimes, system.registry, system.devices, system.auth, host.control), only one provider per authority root is allowed. Today the registry does not actively reject a second registration; the second writer silently shadows the first. The authority-model rules require that ops policy enforce the singleton invariant — see Singleton claims.
Local mount vs logical mount
A claim has both:
| Field | Example | Meaning |
|---|---|---|
logicalMount | system.inference | what consumers ask for |
localMount | system.inference.openai | what the provider serves internally |
In most claims they are equal. They diverge when a provider runtime offers a logical service through a sub-mount (e.g., the OpenAI inference provider mounts at system.inference.openai but claims the public system.inference mount).
Authority scope
authorityRoot and scope together define the claim's namespace. A caller from a different authority root cannot resolve another root's claims (the cross-tenant invariant from MATRIX-AUTHORITY-MODEL.md).
See also
- Mounts — what a logical mount is.
- Registry vs catalog — authority registry vs read projection.
- Mount claims (registry) — detailed registry-side reference.
- Singleton claims — one-owner mounts.
- Consumer groups — multiple providers per logical mount.