Appearance
Reference: Admin actor ops
For the present-state actor surface see Reference: Actor surfaces. This page documents the target admin op extensions and the present-state workarounds.
Present-state cross-principal access
Local-client identity bypasses the per-principal scoping in many ops. From a loopback connection on the platform Host:
bash
matrix invoke system.auth auth.principal.list '{}'
matrix invoke system.devices devices.list '{"includeOffline":true}'
matrix invoke system.auth auth.hostLink.list '{"principalId":"p_xxx"}'
matrix invoke system.auth auth.namespace.list '{"principalId":"p_xxx"}'These work today. They do not work from a remote browser session unless that session has admin privileges (target).
Target: dedicated admin ops
A target naming convention groups cross-principal ops under *.admin.*:
system.auth.admin.*
auth.admin.principals.list— paginated, filterable.auth.admin.principal.suspend/unsuspend.auth.admin.principal.delete(with cascade rules).auth.admin.spaces.list.auth.admin.space.suspend/unsuspend.auth.admin.space.transfer.auth.admin.hostLinks.bulkRevoke.auth.admin.role.assign— set role on a principal.auth.admin.role.list— who has which role.
system.devices.admin.*
devices.admin.list— cross-principal listing.devices.admin.bulkRevoke— multi-Device atomic revoke.devices.admin.fleetSummary— high-level metrics.
system.runtimes.admin.*
runtimes.admin.list— across every Host.runtimes.admin.health— fleet runtime health rollup.
host.control.admin.*
For cross-Host operations from the platform:
host.admin.list— every connected Host.host.admin.invoke— invoke an op on a remote Host.host.admin.restart— remote restart (with permission).
system.audit.*
audit.query— query the audit log.audit.export— export filtered events.audit.retention.set— configure retention.
Authorization on admin ops
Every *.admin.* op gates on the calling principal's role:
ts
if (!isAdmin(callingPrincipal)) {
return { ok: false, error: 'admin role required' };
}Local-client bypass remains for break-glass.
Current op-by-op admin gap
| Today's op | Cross-principal? | Admin-extension status |
|---|---|---|
auth.principal.list | yes (returns all on loopback) | works today; no role gate |
auth.principal.get | yes (any principal id) | works today; no role gate |
auth.principal.suspend | n/a | not implemented |
auth.namespace.list | requires principalId | works per-principal; no list-all |
auth.namespace.claim | scopes to caller | no admin override |
auth.space.list | n/a | not implemented |
auth.hostLink.list | requires principalId | works per-principal |
auth.hostLink.revoke | works on any link | works on loopback; no role gate |
system.devices.devices.list | accepts principalId filter | works per-principal |
system.runtimes.runtimes.list | per-Host | no cross-Host |
host.control.status | per-Host | no cross-Host |
The pattern: per-principal ops exist; cross-principal admin extensions do not.
A minimal admin shim
Implementing the launch-blocking admin ops as a layer on top of existing ops:
ts
// system-auth/admin.ts (new)
import { listPrincipals, ... } from './host-auth.js';
export async function authAdminPrincipalsList(state, options) {
return state.principals.map(p => publicView(p));
}
export async function authAdminSpaceSuspend(state, spaceId) {
const space = state.spaces.find(s => s.id === spaceId);
if (!space) return { ok: false, error: 'not found' };
space.status = 'suspended';
return { ok: true, space };
}
// ...Each is a 20-30 line shim over the existing store. The admin op family is bounded; the gating layer is reusable.
See also
- Reference: Actor surfaces — present-state ops.
- Reference: Admin routes — HTTP wrappers.
- Security: Authorization — permission model.
- Security: Roles — role design.
Source:
projects/matrix-3/packages/system-auth/src/index.tsfor present-state ops. Target ops are not yet specified in code.