The five tiers
Reserved roots
The rootscore, system, app, user, and marfa are reserved. They cannot be claimed as publisher handles.
core.* and system.* are platform-only at registration: only Marfa-platform credentials can register types in these namespaces. Reserved-root claims by ordinary credentials are rejected at POST /types.
App vs publisher
app. separates app trust from publisher trust. A publisher named obsidian cannot impersonate the Obsidian app — the Obsidian app would publish under app.obsidian.* (registered through a system.app identity), while a community publisher publishes under obsidian.* (registered through a publisher handle). Two distinct trust contexts; two distinct namespaces.
That asymmetry is why app.<app-name>.<type> is three segments and <publisher>.<type> is two. The reserved-root rule disambiguates: any first segment that isn’t a reserved root is a publisher handle.
Worked examples
Sibling vs child
A custom type can be a sibling of another type (its own shape, optionally declaringcompatible-with) or a child that inherits.
Both are first-class. The default is sibling. Inheritance is a stronger commitment — children cannot redefine ancestor fields, so a bad inheritance choice is hard to recover from. Sibling is recoverable; you can always add inheritance later.
The rubric: inherit only if every ancestor field is semantically required for your type. Otherwise sibling, optionally compatible-with.
User types are flat by convention but can extend via inheritance where it earns its place. The same applies to publisher and app types — flat is the default; nest when the structural relationship is real.
compatible-with
A sibling type can declare compatible-with: <other-type> to assert that its shape is a structural superset. Optionally with name mappings:
carla.meal_plan doesn’t actually have everything core.task requires (under the declared mappings), the registration is rejected with 400 compatibility_violation.
compatible-with is server-checked, not a free-text tag. Consumers can rely on it.
Inheritance
Single-parent. Additive-only. Children may add fields; cannot redefine or reshape ancestor fields.GET /items?type=core.bookmark returns both parents and children. Writes require the exact type — a credential with write core.bookmark cannot update a readwise.reader_document without that scope.
Domain verification
Domain verification is a badge on a single canonical handle, not a parallel namespace.august.meal_plan and me.cayzer.meal_plan do not coexist as different things. The verified-domain badge sits next to the publisher handle in the marketplace UI; the type identifier stays singular.
Identifiers
Type identifiers use dots only. No forward slashes. Segments are lowercase, snake_case for multi-word components:demo.web_gallery, not demo/web-gallery or demo.WebGallery.