Skip to content

Namespace claims

A namespace claim is the binding between a public Space path (the part of the URL the user sees) and a Space record (the durable entity). Every product URL on hivecast.ai resolves through a namespace claim.

Why a separate concept

Spaces own durable identity (spaceId, authorityRoot). Namespace claims own public addressability (spacePath / routeKey, publicNamespace). Splitting them keeps Space identity stable across rename/transfer while letting the public path be edited or moved.

A Space without a public namespace claim is a private Space — its content cannot be reached via hivecast.ai/<path>/. A namespace claim without a Space is a reservation (today this case is rare; the schema permits it via status: 'reserved').

Schema

Source: projects/matrix-3/packages/system-auth/src/host-auth.ts:71-85.

ts
export interface IHostPublicNamespaceClaim {
  readonly routeKey?: string;            // v1 alias: e.g. "alt.stories.ghost-stories.funny"
  readonly publicNamespace: string;      // canonical: e.g. "space.alt.stories.ghost-stories.funny"
  readonly canonicalRouteKey?: string;
  readonly canonicalNamespace?: string;
  readonly spaceId: string;
  readonly authorityRoot: string;
  readonly canonical: boolean;
  readonly claimType: 'space' | 'domain' | 'system';
  readonly parentNamespace?: string;
  readonly verificationLevel: 'self' | 'org-admin' | 'dns' | 'platform';
  readonly status: 'active' | 'reserved' | 'suspended' | 'released';
  readonly createdAt: string;
  updatedAt: string;
}

Claim types

claimTypeUseImplemented?
spaceDefault — a personal/team Space path.Yes.
domainDNS-verified ownership of a domain. The parentNamespace would be the DNS namespace the claim attaches under.Schema only — DNS verification not implemented.
systemPlatform-internal namespaces.Schema only.

Verification levels

verificationLevelTrust sourceImplemented?
selfThe user claimed the path themselves on first login. No external proof.Yes — the only level today.
org-adminAn organization admin verified the claim.Schema only.
dnsDNS TXT proof at _matrix.<domain>.Schema only.
platformPlatform operator verified manually.Schema only — manual workaround possible by editing state.

Aliases: routeKey and publicNamespace

Per CLAUDE.md (Public Space identity, canonical):

FieldWhat it carriesWhere it appears
spacePath (v2 user-facing term)dot-delimited public pathURLs as /<spacePath>/<appName>/
routeKey (v1 wire field)same value as spacePathevery system-auth op that takes/returns a path
publicNamespacetyped namespace = space.<spacePath>internal routing/claim records

The wire ops emit both routeKey and publicNamespace. New code reads publicNamespace; old callers still read routeKey. Storage carries both.

Canonical vs. alias

A Space can have one canonical namespace claim and zero or more alias claims pointing at the same Space. The canonical claim is the one the platform uses when generating URLs back to the user. Aliases let a Space be reached via multiple public paths during rename or rebranding.

Today the canonical/alias distinction is implemented in the store but not surfaced via UI — there is no "set this alias as canonical" op pair. The first claim a principal makes is canonical by default.

Op surface

auth.namespace.check

Source: system-auth/src/index.ts:555-569.

Checks whether a path is available for claim. Accepts routeKey or publicNamespace.

bash
matrix invoke system.auth auth.namespace.check '{"routeKey":"alt.stories.ghost-stories.funny"}'
# Returns { ok: true, available: true } or { ok: false, error: "..." } if taken.

auth.namespace.claim

Source: index.ts:571-608.

Claims a path for a principal. The principal must own a Space (typically their default).

bash
matrix invoke system.auth auth.namespace.claim '{
  "principalId": "p_xxx",
  "routeKey": "alt.stories.ghost-stories.funny"
}'

The op:

  1. Validates the path format.
  2. Inserts an IHostPublicNamespaceClaim record.
  3. Stamps verificationLevel: 'self' and claimType: 'space'.
  4. Returns { routeKey, publicNamespace, canonicalRouteKey, canonicalRoute, namespaceRole, spaceId, authorityRoot, canonical: true, claim, space }.

auth.namespace.resolve

Source: index.ts:610-641.

Resolves a path to its Space. This is what system-gateway-http calls on every public-URL request.

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

If the path is an alias, namespaceRole: 'alias' is returned along with the canonical alternative.

auth.namespace.list

Source: index.ts:643-653.

Lists every claim owned by a principal.

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

Returns one row per claim, each carrying spaceId, routeKey, publicNamespace, canonical, status.

Path format

routeKey / spacePath is lowercase, dot-delimited, kebab-case segments:

  • Valid: alt.stories.ghost-stories.funny, richard-santomauro-gmail, acme.engineering.
  • Invalid: Alt.Stories, richard_santomauro, richard santomauro.

Per the URL grammar in P1.22:

Public routeKey segment: lowercase, /^[a-z0-9][a-z0-9-]*$/
Joined with dots for multi-segment paths.

The grammar is intentionally narrower than actor mount grammar. Internal mounts can carry any character; public URL paths are restricted.

Reservation and suspension

status: 'reserved' and status: 'suspended' are schema-supported but operator-only today. Used for:

  • Reserved: holding a path for a future organization (e.g., acme.* reserved before the org pays for it).
  • Suspended: claim exists but is offline (e.g., terms-of-service violation).

Both transitions require direct state-file edit. Target state.

Released claims

A status: 'released' claim is freed; the path is available for re-claim. Today claims are never automatically released — even when a Space is deleted (which is itself target state). Operator workaround: edit state.

See also

Source: projects/matrix-3/packages/system-auth/src/host-auth.ts:71-85 for the schema, index.ts:555-653 for the ops.