Skip to content

Spaces (operator workflow)

For the conceptual introduction, see Overview / Spaces. This page is the operator-facing workflow: how to create, inspect, default, and suspend Space records.

Schema recap

ts
export interface IHostSpaceRecord {
  readonly id: string;            // spaceId, e.g. spc_7f3a9b2c
  readonly authorityRoot: string; // bus root, e.g. SPACE.SPC_7F3A9B2C
  readonly ownerPrincipalId?: string;
  readonly ownerType?: 'principal' | 'organization' | 'system' | 'service';
  readonly status: 'active' | 'suspended';
  readonly createdAt: string;
  updatedAt: string;
}

A Space's id is permanent. Its authorityRoot is immutable. Its ownerPrincipalId can be transferred (op exists in scope; today it requires direct state-file edit). Its status toggles between active and suspended.

Creating a Space

Op: auth.space.create (system-auth/src/index.ts:655-682).

bash
matrix invoke system.auth auth.space.create '{
  "principalId": "p_xxx",
  "authorityRoot": "SPACE.SPC_NEW"
}'

If authorityRoot is omitted, it falls back to (in order):

  1. principal.addressRoots[0].root
  2. principal.workspaceRealm
  3. services.authorityRoot (the configured platform-wide default)

Per P1.23f the v2 target is for new Spaces to derive authorityRoot = SPACE.<UPPER(spaceId)> automatically — that is target state. Today new Spaces inherit the principal's authority root by default, which means renaming the user's email-derived root would break new Spaces. Pin authorityRoot explicitly when creating Spaces in scripts.

The first Space created for a principal becomes their default automatically.

Getting a Space

Op: auth.space.get.

bash
matrix invoke system.auth auth.space.get '{"spaceId":"spc_7f3a9b2c"}'
# Returns { ok: true, space: { ... } } or { ok: false, error: "Space not found: ..." }

Default Space per principal

Op: auth.space.default (index.ts:684-704). Without spaceId, returns the current default. With spaceId, sets it (the Space must be owned by the principal).

bash
# Read current default
matrix invoke system.auth auth.space.default '{"principalId":"p_xxx"}'

# Set a new default
matrix invoke system.auth auth.space.default '{
  "principalId": "p_xxx",
  "spaceId": "spc_7f3a9b2c"
}'

The default Space is what auth.principal.authorityRoot returns first, what auth.hostLink.create uses when spaceId is omitted, and what the platform shell renders as the active workspace.

Suspending a Space

Target state. The schema supports status: 'suspended', but no op exposes the transition. Direct state-file edit on the platform Host is the operator workaround. A auth.space.suspend / auth.space.unsuspend op pair is needed for the admin dashboard.

When suspended, a Space's:

  • public namespace claims should resolve to a 503 Suspended page.
  • Host Links bonded to it should refuse new heartbeats.
  • existing sessions can keep reading until token expiry.

None of those enforcement paths exists today. Suspension is purely a database flag for now.

Transferring a Space

Target state. ownerPrincipalId can be edited in the state file but no op enforces the transfer (it should: revoke existing Host Links if the old owner is being removed, re-issue with the new owner's account credentials). Until the op exists, transfer is a multi-step operator procedure not safe for self-service.

Listing all Spaces

There is no auth.space.list op today. Per-principal namespace listing exists (auth.namespace.list) and returns the Spaces backing those namespaces. A platform-wide auth.space.list is target state for the admin dashboard.

Workaround:

bash
# Inspect raw state on the platform Host
ls /var/lib/hivecast/host-home/state/auth-state.json
# Look at "spaces" array.

Common operator tasks

Find a Space by routeKey / spacePath

bash
matrix invoke system.auth auth.namespace.resolve \
  '{"routeKey":"alt.stories.ghost-stories.funny"}'
# Returns spaceId, authorityRoot, claim, space.

Find a Space's owner

bash
matrix invoke system.auth auth.space.get '{"spaceId":"spc_xxx"}'
# Look at ownerPrincipalId, then auth.principal.get on that.

Find a principal's Spaces and routes

bash
matrix invoke system.auth auth.namespace.list \
  '{"principalId":"p_xxx"}'

This returns the public-namespace claims, each carrying spaceId, routeKey, publicNamespace, authorityRoot. To enumerate Spaces without public namespaces, you need direct state inspection — that combination is rare today (most Spaces are created with a public namespace at first OIDC login).

See also

Source: projects/matrix-3/packages/system-auth/src/index.ts:655-717 for the auth.space.* ops. The schema is at host-auth.ts:61-69.