Appearance
Device inventory
system.devices is the platform-account-facing facade for paired Devices. It unifies durable Host Link records with live runtime presence and exposes the union as ops the dashboard, Edge, and CLI consume.
Ontology contract
Per HIVECAST-DEVICE-ENROLLMENT-SPEC.md:
system.devices = product/account-facing linked-device facade. It must not become the public actor namespace. Actors still mount logically throughsystem.registryaschat,system.inference.openai,director, etc. Logical address != management path.
Three things system.devices is:
- A read facade over Host Links (
system-auth) and runtime registrations (system.runtimes,host.control). - An inventory that survives offline Devices.
- A control surface for management ops: revoke, refresh credentials, list runtimes per Device.
Three things system.devices is not:
- The public actor namespace. Apps mount as
chat,director, etc., notsystem.devices.<deviceSlug>.chat. - A source of truth for runtime state — that is
system.runtimesandhost.control. - A source of truth for pairing — that is
system-auth.
Op surface
The current ops:
| Op | Purpose |
|---|---|
devices.list | List linked Devices for the principal (or for the platform admin scope). |
devices.get | Fetch one Device row by deviceId / deviceSlug. |
devices.heartbeat | Accept a Device heartbeat. Internal: called by _auth/host-link/heartbeat. |
devices.runtimes.list | List runtimes registered under one Device. |
devices.runtimes.register | Register a runtime against a Device. Internal: called by host.control. |
These are a superset of system-auth's auth.hostLink.list / get because they merge link + runtime + heartbeat data into one row.
What devices.list returns
bash
matrix invoke system.devices devices.list \
'{"includeOffline":true}'Returns one row per linked Device:
ts
{
deviceId: 'install_<short>',
deviceSlug: 'richard-laptop',
hostName: "Richard's Laptop",
status: 'online' | 'offline' | 'revoked',
lastSeenAt: '2026-05-05T14:23:00Z',
routeKey: 'alt.stories.ghost-stories.funny',
publicNamespace: 'space.alt.stories.ghost-stories.funny',
spaceId: 'spc_xxx',
authorityRoot: 'SPACE.SPC_XXX',
runtimeHostCount: 1,
runtimeCount: 8,
webappCount: 4,
source: 'merged' | 'durable-only' | 'live-only',
// ...full Host Link fields under 'hostLink' for full-detail views
}source: 'merged' means both a Host Link record and live heartbeat presence agreed. 'durable-only' means the Device has not heartbeated recently. 'live-only' is anomalous (heartbeat without a durable record) and indicates a bug or a stale credential.
Filtering by principal
For platform-operator views, pass principalId:
bash
matrix invoke system.devices devices.list \
'{"principalId":"p_xxx","includeOffline":true}'The current implementation scopes to the calling identity by default (a signed-in user only sees their own Devices). Cross-principal listing is only available to local-client (loopback) callers and operators.
Live proof of the model
Per P1.22 progress notes:
Live authenticated Playwright proof shows
https://hivecast.ai/apps/web/#dashboardrendering the linked Device as Online with 8 runtime hosts and links to/richard-santomauro-gmail/edge/,/richard-santomauro-gmail/director/, and/richard-santomauro-gmail/chat/.
devices.list is what the dashboard's Device cards consume. Each row's runtime count drives the "8 runtimes" pill; webappCount drives the "4 web apps" pill.
Identity merge
Per HIVECAST-DEVICE-ENROLLMENT-SPEC.md, three fields identify a Device:
installId— durable per local install.hostId— durable per pairing.deviceSlug— durable address-safe management key.
devices.list projects deviceId (currently equal to installId for locally-paired flows, equal to the Host Link's hostId for HiveCast-initiated flows) and deviceSlug for URL-safe routing. The two are kept in sync at pairing time; they differ in the schema specifically because one physical machine could have multiple installs (today it doesn't, but the schema allows it).
What is NOT yet in the op surface
Not implemented today, but design space:
devices.rename— changehostName. Workaround: re-pair with--device-name <new>.devices.scopes.update— see Device grants.devices.transfer— move a Device to a different Space (without revoking).devices.bulkRevoke— revoke many Devices at once.- Cross-Space federation views (
devices.list-federated).
These are target state.
How runtime registration ties in
Each Device's runtimes register with system.devices.devices.runtimes.register (called by host.control periodically). The runtime row carries runtimeId, appName, webapp metadata, route info, last heartbeat. devices.runtimes.list exposes them grouped by Device.
The dashboard reads devices.runtimes.list per Device to render the per-app cards under each Device. Discrepancies between devices.runtimes.list and system.runtimes.list are debugging signal — a runtime that registered with system.runtimes but not with system.devices.runtimes indicates the Device's host.control did not propagate the registration. See Reference: Operational runbooks.
See also
- Pairing — how rows get created.
- Device health — what online/offline means.
- Disconnect / unlink — what happens when a Device is removed.
- Reference: Actor surfaces — full op contract.
- Reference: Database ownership — what
system.devicespersists vs. derives.
Source:
WORKSTREAMS/product-launch/HIVECAST-DEVICE-ENROLLMENT-SPEC.mdfor the contract. Thesystem.devicesactor implementation is inprojects/matrix-3/packages/system/src/(the system package merges Host Links and runtime registration data into the facade rows).