jschoubben ac8556c590 baserow: placed directories, the database password from a file, and the build ace runs
The module named /var/lib/baserow and /services/baserow/data, a layout no
definition may carry (ADR 0112). State and data are now placed directories;
bindings and the grant's secret live in the placed state.

The all-in-one image's entrypoint honours DATABASE_PASSWORD_FILE (file_env
in /baserow.sh), so the grant's password is mounted rather than put in an
env-file, and "secrets-in-environment" is gone (ADR 0086). SECRET_KEY is no
longer minted: the image keeps it, and its JWT signing key, in the data
directory (.secret, .jwt_signing_key) and imports them on start, so a moved
data directory carries the keys its sessions and tokens were made with.
DISABLE_EMBEDDED_PSQL makes a missing grant fail loudly instead of starting
an empty embedded database.

BASEROW_PUBLIC_URL was http://localhost. Baserow answers only the host of
that URL - any other Host is looked up as a published builder site and gets
404, /api/_health/ included - so it is now https://${bound:route:name}
(depends on mesh-controller #149).

The runtime's tools could never have worked: its config was "{}", and the
client's Host override was silently dropped by Node's fetch, so calls by
container name would 404 even with credentials. The client now uses
node:http (which sends the Host it is given, with a Content-Length -
Baserow reads a chunked body as empty) and re-authenticates once when a
cached JWT is refused (access tokens last minutes, the runtime weeks). The
password is the accepted `admin` secret; the email is an assignment
setting merged into the same file, the host is the route's name.

Image pinned to the develop-latest build ace runs today (Baserow 2.3.4,
built 2026-09-18). The old pin (built 2026-09-04) is older than ace's data.

Verified: catalogue tests with MESH_CATALOGUE set; tsc -p tsconfig.json in
the mesh-tools build image. In throwaway containers of the pinned image: a
fresh embedded-PG instance with a user, workspace and 5-row table; stopped,
copied, dumped from the copy (start-only-db); restored with --no-owner
--role into a grant-shaped database on the pgvector image the postgres
module pins (PG17); started with this shape (root 0600 password file,
embedded PSQL disabled, copied data dir without postgres/): health 200,
the user logs in, the 5 rows are there, SECRET_KEY and the JWT key are
imported from the data dir. The patched client lists applications and rows
through the container name with the public Host, and recovers from a
refused token. Test containers and data removed.
2026-09-30 12:16:04 +02:00

mesh-catalog

The Novox Mesh catalogue. The modules the mesh builds, provisions and runs — as manifests, one per module under modules/.

This is data, not a control-plane concern. The manifests describe what a module is: what it provides, what it requires, the seats it claims, the resources the host applies for it. The engine that reads them — parsing, eligibility resolution, sealing, declaration emission — lives in the control plane (novox/mesh-controller, internal/catalogue), which consumes this repository as a build source. The host (novox/mesh-host) applies the declarations the control plane emits. Neither is here.

What a module is, and is not

A module is one thing the mesh can run, named once, described completely by its manifest. A manifest names its image (pinned by digest), the resources the host owns for it (directories, files, the container, the private network it joins), what it requires from a provider and what it provides to consumers, and the sealed secrets it needs filled on the machine.

  • Core mesh components are not modules. The node host, the foundation, the control-plane contexts and the surfaces are the mesh itself; they ship as their own repositories (mesh-host, mesh-foundation, mesh-controller, mesh-surfaces, mesh-sdk), not from here.
  • Standalone applications are not here either. A larger application lives in its own repository with its manifest at the root, registered with the mesh as a build source (novox/hq ADR 0010). This repository holds the modules the mesh maintains as its shared catalogue; an application the mesh merely hosts keeps its manifest beside its own code.

So there is one home for the catalogue the mesh owns, and every application that runs on the mesh rather than being of it carries its own — both reach the pipeline the same way, as a registered source.

Layout

modules/<name>.json      one manifest per module

Flat, because the catalogue's shape carries no meaning: a module is found by its name and described by its manifest, and what relates two modules — a shared seat, a claim, a provider/consumer edge — is data inside the manifests, not a directory the tree encodes (novox/hq, the domain-grouping question closed in favour of seats, claims and tags).

The manifest contract

The shape a manifest must satisfy is owned by the control plane's catalogue engine and is what validates a manifest before a machine ever sees it — a stray key, a consumer contributing the wrong provision field, an image that nothing builds. That validation belongs with this repository and is being re-homed here from mesh-controller; until it is, the pipeline is the gate — it builds each module and refuses a manifest it cannot resolve.

Where the reasoning lives

Design and decisions are in novox/hq:

  • 02-DECISIONS/0002-everything-is-a-module.md — one unit, no second mechanism
  • 02-DECISIONS/0010-applications-live-in-their-own-repository.md — why applications are not here
  • 02-DECISIONS/0030-the-repository-structure.md — the repositories, and the open tier-4 question this repository answers
  • 03-DESIGN/00-as-is/10-module-catalogue.md — the catalogue's shape, and what it records
S
Description
Novox Mesh — the catalogue. Module manifests the mesh builds, provisions and runs. Data, not a control-plane concern.
Readme
2.6 MiB
Languages
TypeScript 91.1%
Dockerfile 8.1%
Shell 0.8%