Skip to content

The plane model

The two plane axes — read them together

Atelier has two orthogonal plane vocabularies. They are not the same axis and must never be conflated; a row has a position on both.

Axis 1 — Provisioning planes (where a config row lives; distinguished only by ontology tenant_id)

PlaneTenant codeHoldsForked?
Vocabularysystementity TYPES/schema, platform meta-types, KC vocab, notification_event vocabulary, action_surface/page_template/public_entity_surface registries, the org treeNo — shared by all tenants
Templatetemplate_municipalitythe forkable worked example: application rows, application_entity_membership, action_type + children, action_placement, notification rules/templates, admin_entity_configIt IS the fork source
Tenantper fork (e.g. lisbon)the same row classes, copied + FK-rewired by the one-shot full-catalog forkcreated by fork

The distinction is data, never a code branch — a row's plane is just its tenant_id. After fork, a tenant admin edits their copy with the same editors and zero special-case code, because every config endpoint keys reads/writes by the caller's resolved tenant. The only cross-plane bridge is one header, X-Author-Tenant, honored solely for callers holding the right UMS tier grant (authoring_update_allowed, auth.py:275). Fork copies exactly the rows whose type opts in via metadata.forkable (fork_plan.py:91-101) — not the control_plane axis, which marks shared infra/vocab a fork must never copy.

Axis 2 — Functional planes (what a thing IS; the M10 mental model)

PlaneOwnsPrimitive
Dataentities, properties, relationships, states — "what exists"entity type + ResolvedSchema
Executionactions, preconditions, edits, side-effects — "what can happen"action_type + 6 child classes → ActionDefinition
Surfacewidgets, layouts, data-bindings, interaction patterns — "what is experienced"Block descriptor + WidgetKind + page_template

How they compose

A single action_type row sits at (template plane, execution plane) before fork and (tenant plane, execution plane) after. A portal_page is (tenant plane, surface plane); its shared page_template shape is (vocabulary plane, surface plane). An entity type is (vocabulary plane, data plane) — never forked, because schema is shared; only its config (placements, dashboards, ACL) forks.

The clean rule: Axis 1 says whether a row is copied on fork; Axis 2 says which subsystem owns it. The ontology engine is blind to Axis 1 entirely — it sees only tenant_id on ordinary rows; the BFF supplies all plane semantics.

Atelier — Platform Specification. Internal canonical reference.