Appearance
Registry vs catalog
Four different authorities use the words "registry" or "catalog" in this codebase. This page is the disambiguation table. The single most common documentation drift in Matrix is treating these as one thing.
The four authorities
1. Artifact registry — the binary store
Question it answers: "Where do I download the bytes for @open-matrix/chat@0.2.3?"
Backing store:
- Cloud product: a Gitea instance at
registry.hivecast.ai, exposing the npm-compatible API at/api/packages/<scope>/npm/. - Local install: the bundled package store seeded by
hivecast installinto<host-home>/packages/{system,global}/node_modules/....
Implementation today: Gitea is provisioned by projects/deploy-cloud/setup-aws.sh and proxied by projects/deploy-cloud/Caddyfile.bare. Local seeding is seedBundledHostPackages in projects/matrix-3/packages/hivecast/bin/hivecast.mjs.
Does not own: package descriptions, search, version ranges semantics, runtime state, mount claims.
2. Package catalog — system.packages
Question it answers: "What can I install? What does this package describe itself as?"
Backing store: A discovery-index.json written next to the Gitea artifacts (or under <host-home>/registry/ for local mode). The catalog is a key-value projection of every package's matrix.json discovery metadata across versions.
Implementation today: SystemPackageRegistryActor at projects/matrix-3/packages/system-catalog/src/SystemPackageRegistryActor.ts. Mounted as system.packages. Single op: registry.search.
Does not own: the artifact bytes themselves, the running mount inventory, or whether anything is currently mounted.
Note: The op is named
registry.search(notpackages.search). That is a v1 naming wart — the actor mounts atsystem.packages, but its single op uses theregistry.prefix. New code should keepregistry.searchfor compatibility; future revisions may add apackages.searchalias.
3. Live actor registry — system.registry
Question it answers: "Which logical mounts are currently claimed by which providers, and which providers are alive right now?"
Backing store: in-memory in the system runtime. State is rebuilt from provider heartbeats; there is no on-disk truth.
Implementation today: ServiceRegistryActor at projects/matrix-3/packages/system-platform/src/ServiceRegistryActor.ts. Mounted as system.registry. Ops: registry.register, registry.heartbeat, registry.unregister, registry.list, registry.resolve, registry.children, registry.providers. Compatibility ops service.register / service.resolve / service.list / service.deregister remain for older callers.
Does not own: package availability, package metadata, downloadable artifacts.
4. System catalog — system.catalog
Question it answers: "Give me a unified read-only view of every mount in this Host, what runtime serves it, what ops it accepts, and what its providers declare."
Backing store: none. system.catalog is a read projection that builds its result on every call by joining system.registry.registry.list, system.runtimes.runtimes.registered, system.gateway.http.gateway.http.status, and (for filtered searches) live $introspect calls against each provider.
Implementation today: SystemCatalogActor at projects/matrix-3/packages/system-catalog/src/SystemCatalogActor.ts. Mounted as system.catalog. Ops: catalog.list, catalog.resolve, catalog.roots, catalog.children, catalog.tree, catalog.search.
Does not own anything. It is purely derived. Two consequences:
- If
system.registryis wrong,system.catalogis wrong. Fixsystem.registry. system.catalogis safe to recompute aggressively; it has no write surface.
Authority table
| Question | Authority | Writeable? |
|---|---|---|
| Where are the bytes? | artifact registry (Gitea / local store) | yes (publish flow) |
| What can I install? | system.packages (discovery-index.json) | yes (publish flow updates index) |
| What is currently mounted? | system.registry (ServiceRegistryActor) | yes (register/heartbeat/unregister) |
| What is the unified view? | system.catalog (SystemCatalogActor) | no — read projection |
| What URL serves an app? | system.gateway.http.gateway.http.status (out of scope here, see docs-gateway) | no — derived from runtime records |
Why this matters
Treating "registry" as one concept causes three classes of bug:
- Stale catalog. Code asks
system.registryfor "available packages."system.registryonly knows about running mounts; the answer omits anything not started. The right authority issystem.packages. - Phantom mounts. Code writes to
system.catalogto "register a package."system.catalogis read-only; nothing happens. The right authority issystem.registry(for live mounts) or the publish flow (for the artifact registry). - Cross-Host bleed. Code assumes the artifact registry is per-Host. It is not — the cloud-product artifact registry is
registry.hivecast.ai, shared across every linked Device. Per-Host state lives insystem.registry, not in the artifact registry.
See also
Source: This separation is enforced by the directory structure. Each authority lives in its own package and exposes its own actor mount. There is no shared state between them on disk; all coupling is through declared request/reply ops.