Skip to content

Database ownership

The platform persists state in a small number of stores. Each is owned by a specific actor; cross-store reads require going through the owning actor's ops, not by hand-editing files.

Stores on the platform Host

<host-home>/state/auth-state.json

Owner: system.auth via HostAuthStateStore.

Contents (per IHostAuthState in host-auth.ts:174-187):

ts
{
  version: 1,
  principals: IHostPrincipalRecord[],
  externalIdentities: IHostExternalIdentityRecord[],
  credentials: IHostCredentialRecord[],          // includes principal NATS account seeds
  revokedSessions: { jti, principalId, expiresAt }[],
  spaces: IHostSpaceRecord[],
  publicNamespaces: IHostPublicNamespaceClaim[],
  principalDefaultSpaces: IHostPrincipalDefaultSpace[],
  hostLinks: IHostLinkRecord[],
  deviceLinks: IHostDeviceLinkRecord[],          // pending device-flow records
  pairings: IHostPairingRecord[],                // pending pair-flow records
  googleOauthStates: IHostGoogleOauthStateRecord[]  // in-flight OAuth states
}

This file holds everything system.auth knows. On the platform Host it is the central account directory. On a paired user Device it holds only the principal that owns the Device (a 1-row store, effectively).

Sensitive content:

  • credentials[].value for entries with credentialType: 'nats-account' contains the principal NATS account seed. Per HIVECAST-DEVICE-ENROLLMENT-SPEC.md, this seed never leaves the server.
  • revokedSessions is a delete-list, not a sensitive credential, but its presence is part of audit posture.

<host-home>/runtimes/<runtime-id>.json

Owner: Host Service supervisor via HostStateStore.

One file per runtime. Carries runtimeId, package, mount, env, serve, port, startup, restart, last-start metadata. The supervisor reconciles these against running processes.

hivecast seed self-heals corrupt files (zero-byte from a historical bug).

<host-home>/host.status.json

Owner: Host Service supervisor.

Single file with the live status of the supervisor: PID, NATS PID, uptime, last reconcile.

<host-home>/host.json

Owner: install-time configuration.

Per-Host settings: transport.root, http.host, http.port, auth.sessionSecret, auth.providers.google.*, externalUrl. Operator-edited; not mutated at runtime by the supervisor.

<host-home>/credentials/

Owner: mixed.

  • hivecast-install.json — per-install identity (installId).
  • hivecast-link.json — Host-Link record (post-pair). hostId, hostName, deviceSlug, routeKey, publicNamespace, spaceId, authorityRoot, heartbeatToken, NATS user JWT/seed.
  • Other per-driver credential files owned by system.factotum.

On the platform Host credentials/ typically holds the platform's own identity files (it can be linked to itself as a Device for self-test). On a user Device this is where the per-Device identity lives.

<host-home>/.matrix/packages/

Owner: install-time + hivecast seed.

The package store. Each package's dist/ is laid out under <package-name>/.

<host-home>/logs/runtimes/<runtime-id>.log

Owner: the supervisor (writer) + each runtime (line emitter).

Per-runtime log file. Rotated by supervisor settings.

Why this is mostly JSON files (not Postgres)

Per ARCHITECTURE-PLATFORM-TOPOLOGY.md §11 (Current State vs Target State), Postgres-backed storage is target state for the platform Host. The current implementation uses JSON files served by HostAuthStateStore and similar. This:

  • Works for the launch single-region single-node deployment.
  • Is operator-inspectable (cat the file, jq it).
  • Does not scale to multi-node or multi-region.
  • Requires file locking discipline (HostAuthStateStore does this internally).

Migration to Postgres is non-trivial because the schema is currently the JSON shape; a relational schema needs designing. Target state.

Stores on a user Device

Same layout. The auth-state.json contains exactly one principal (the Device's owner), one Space (their Space), one Host Link (this Device). The runtime records cover the local runtime set. The credentials directory holds per-Device material.

A Device's auth-state.json does NOT contain other principals' Spaces or Host Links — it is per-Device.

Federation does not share storage

When a paired Device connects to the platform, neither side imports the other's state. They federate over NATS. The platform's system.devices aggregates Host Link records (its own) plus heartbeats received from the Device (real-time bus messages); it does not pull state from the Device's auth-state.json.

What system-gateway-http owns

The HTTP gateway is stateless — it is request handling and routing. It reads identity from the request (cookie or local-client signal) and forwards to actors. It does not own a database.

What system.runtimes owns

The RuntimeManagerActor keeps an in-memory registry of runtimes that have called runtimes.register. This is rebuilt at process start from supervisor records. It does not persist its own DB.

Backup/restore strategy

For the platform Host:

bash
# Backup
tar czf hivecast-home-$(date +%Y%m%d).tar.gz <host-home>/

# Restore
hivecast stop
tar xzf hivecast-home-<date>.tar.gz -C /
hivecast start

This captures everything: principals, Spaces, Host Links, runtime records, credentials, packages, logs. The auth-state.json contains principal NATS account seeds — encrypt the backup at rest.

See also

Source: projects/matrix-3/packages/system-auth/src/host-auth.ts for HostAuthStateStore. projects/matrix-3/packages/host-service/src/host-state-store.ts for runtime records.