Mosaic one model, many lenses

The Laws of Mosaic

Mosaic is not a framework and it is not a code generator with opinions. It is a small compiler. Six laws make it what it is. Every law is enforced by an executable artifact — a test, a CI job, or a type signature — not by goodwill. If a law cannot be enforced, it is a slogan and it does not belong here.

Law 1 — Compiler Input

The entire input to mosaic is a finite, declarative set of files:

  • mosaic.yaml — the app (which tessera, which deployments),
  • <tessera>/tessera.yaml — the unit (kind, enums, entities, ops),
  • <tessera>/src/*.rs — hand-written behavior, copied verbatim,
  • deploy/*.yaml — deployments (or inline deploy: sugar in mosaic.yaml).

No plugins, no build scripts, no configuration that depends on the environment. Every key is declared, unknown keys are errors (deny_unknown_fields), and the JSON schema of each file kind is machine-printable: mosaic schema tessera|mosaic|deploy.

Enforced by: the grammar types in crates/mosaic-grammar (serde deny_unknown_fields on every spec struct) and the CI schemas are valid JSON step.

Law 2 — Zero Tax

A capability you do not declare costs you nothing. The type vocabulary is closed (nine primitives, declared entities/enums, one level of lists); the middleware vocabulary is closed; the lens set is closed. There is no expression language and therefore nothing to learn, nothing to sandbox, and nothing to optimize. When a need appears that the vocabulary does not cover, the vocabulary is extended in a deliberate ADR — it is never escaped from.

Enforced by: ADR 0001 and its proofs (mosaic-grammar::ty::tests::rejects_option_and_nested_arrays, accepts_both_list_spellings).

Law 3 — One Model

There is exactly one model: the tessera. Every artifact — REST routes, the client CLI, the OpenAPI document, the Dockerfile, the k8s manifests — is a projection of the same resolved plan. Two lenses can never drift apart, because neither of them owns the truth.

Enforced by: ADR 0002 and its proof (mosaic-conformance::tests::render_is_a_pure_function_of_the_plan).

Law 4 — Thin Renderers

A renderer prints. It does not decide. Anything that requires choosing a fact — a route, a default, a name, a derived op — happens exactly once, in mosaic-core::resolve. Renderers take a ResolvedPlan and nothing else; that signature is the law.

Enforced by: ADR 0004 and its proof (mosaic-render integration test core_never_depends_on_render, which fails the build if core ever depends on render).

Law 5 — Proven Proof

Every ADR names the test or CI step that proves its decision, and that artifact runs on every push. A decision without a proof is a rumor.

Enforced by: the Proof field in docs/adr/*.md and the CI test job, which runs all of them.

Law 6 — Copilot Law

A copilot must be able to work in this repo without tribal knowledge. Everything it needs is in the repository: the JSON schemas (mosaic schema), the golden outputs (every rendering is committed and diff-able), the laws and ADRs (short enough to fit in one context window), and examples that build. If a fact is not written down, it is not a fact.

Enforced by: the examples/ conformance suite — if the committed goldens stop matching the code, CI fails, so documentation can never silently rot.