Skip to content

Introduction

Vision — declare the interesting 20%, the platform generates the 80%

Atelier is an ontology-native application-generation platform for civic and operational software. A municipality or operator does not write an application — they declare one: its entities and schema, the actions that can happen to them, the surfaces that render them, the notifications they emit, the identity and authorization rules that govern them, the reports and analytics they expose, and the citizen-facing portal that serves the public. That declaration is data, never code — ontology rows, expressed canonically as a single Vertical Sheet (YAML) or edited live in operator-facing editors. From that declaration Atelier generates the running, multi-tenant experience: a staff admin console, a citizen portal, and the APIs behind both.

This is the same clarity our sibling platform Martha brings to AI agents — "we handle the 80% that makes an agent production-ready, you declare the interesting 20%" — but turned toward apps instead of chat agents. Where Martha's primitives are Workflows, Integrations, Document processing and Delivery channels, Atelier's primitives are Entities, Actions, Surfaces, and Identity. And Martha is not merely an inspiration: it is Atelier's durable-execution backend — every long-running submission and workflow-mode action rides Martha/Temporal.

The commercial promise is compound software: a catalog of building blocks — entity types, widget kinds, action shapes, notification channels, view kinds — that grows without breaking what already composes. Any entity can render in any widget; any action can fire from any surface; a new tenant comes up fully configured by forking one worked example, then diverges by editing its own copy with the exact same editors the platform author used. The unit of leverage is the declaration: author it once on the template plane, and every municipality that forks it inherits a working app — staff console, portal, APIs, authz, and notifications included.

Executive summary

Atelier is built from eleven subsystems that share one substrate and two orthogonal plane-axes.

The substrate is the ontology engine (ontology-core-v2): a runtime schema-evolution database on Postgres/PostGIS/Timescale where entity types, fields, FK-less declarative links, and analytical views are all declared at request time and read through one cursor-paginated GET /api/v1/{code} surface, multi-tenant by an X-Tenant-Id header. The engine is deliberately plane-agnostic — it sees only ordinary tenant-scoped rows; all plane and public-surface semantics live in the BFF (admin-api).

Everything an operator declares is a row class in that engine: entity types and schema (data plane), action_type + six child classes (execution plane), page_template/portal_page/public_entity_surface/widget descriptors (surface plane), notification_event/notification_rule/notification_template, identity and acl_rule policy, and report_template. The canonical authoring artifact that expresses all of these together is the Vertical Sheet, applied by a four-stage pipeline (parse → validate → diff → apply, prepare_sheet_plan at sheet_apply.py:49) in FK-safe APPLY_ORDER.

The first plane-axis is provisioning: a vocabulary plane (tenant system) holding types and registries, a template plane (template_municipality) holding the single forkable worked example, and a tenant plane (one per fork) holding FK-rewired copies. A one-shot 5-phase fork (fork_tenant) copies every row whose type opts in via metadata.forkable (confirmed at fork_plan.py:91-101 — explicitly not the control_plane axis), and the same operator editors then serve every tenant because each endpoint keys on 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).

The second plane-axis is functional (the M10 mental model): data plane (what exists), execution plane (what can happen), surface plane (what is experienced) — the basis of the compound-software thesis.

Authorization runs through the BFF as a UMS-v2 PEP: every entity-proxy read/write resolves the caller's grants under application_id=admin-bff, compiles them to a SQL-WHERE / predicate / Q, fails closed (503) on UMS outage and deny-all (1=0) on no grants. Policy is declared as acl_rule data, never branched in Python.

The honest frontier is consistent across all eleven sections. Note one thing that is not an open frontier: the authorization read-path is already ontology-native and decommissioned. Every read (staff + citizen) resolves under per-app namespaces; the read_path_per_app_namespace flags were retired after the D1 soak (config.py:54, application.py:129), the legacy monolithic admin-bff domain plane is no longer served (#431 CLOSED), _uuid_only is deleted, and citizen tuples/grantees are re-keyed to the root-org UUID. The platform deliberately keeps Pattern A (the BFF resolves under the per-app namespace, compiles a filter, calls the ontology with a service-account token) per ADR-0001 — forwarding the user token to the engine is rejected (it resolves under the wrong ontology-core namespace; "the nav bug"). The only residual — letting the engine resolve under a consumer-supplied app-id so the BFF compiles less — is blocked on one upstream ontology change (resolver.py:67 honoring a consumer app-id), and even then compilation relocates, it does not vanish (spec §5); composite/BFF-native types (kc_*, admin_entity_config, cross-service joins) enforce BFF-side by design. The genuinely open edges are: copy-on-create fork with no live template re-sync (the biggest unaddressed lifecycle edge, surfaced independently by provisioning, authoring, surface, and reports), a handful of fail-open seams in dev/boot paths that are not in CI and rot, and shared-Martha with no per-tenant isolation. None of these block the thesis; all are named in the gaps register.

Atelier — Platform Specification. Internal canonical reference.