The manifest named /services/plex/{config,transcode} with owner and mode.
On ace /services/plex is a link to /mnt/plex, plex's 133 GB of state, so
a take would have chmod'ed 0700 the top of the one directory the operator
ruled must never be re-moded or re-owned. The directories are now pathless
(config, data, transcode), placed by the mesh; on an adopted machine they
must be placed where the data is (hq 153) before plex is ever taken.
- The container sees exactly the paths ace's plex sees today: /config,
/data (HAL mounts it; the catalogue did not), /transcode and all eight
libraries, including sport-games, live-shows and formula-1. A library
whose mount disappears is emptied by Plex's automatic trash emptying,
taking its watch state with it.
- Libraries are mounted read-only, as the accesses already said.
- Owner 1000:1000 and mode 0755: plex runs as uid 1000 (the image reads
PLEX_UID, not the PUID HAL passes), pms-docker leaves its dirs 0755, and
ace's /mnt/plex is 1000:1000 0755 - so placing adopted data is a no-op.
- Image pinned to what ace runs, 1.43.4.10903; the old pin was 1.43.3.
- ADVERTISE_IP comes from the route's own public name through an env-file
(${bound:route:name}); it depends on mesh-controller #149, and without
it the declaration is refused, not applied.
- The server is routed (label plex) and declares its four GDM discovery
ports, which LAN players use.
- No token secret: a minted one is not a Plex token and the sidecar
preferred it. The sidecar reads PlexOnlineToken from Preferences.xml
through its read-only config mount, and dials ${port:32400}.
Verified: catalogue tests with MESH_CATALOGUE (parse, mounts); a scratch
resolution with ace's assignment on the #149 controller renders
ADVERTISE_IP=https://plex.zurag.be/, both route names and 32400/tcp +
GDM/udp open to anywhere; on main it is refused naming "name". A
throwaway pms-docker at the pinned digest on empty dirs answered
/identity, wrote customConnections from the env-file and ran as 1000;
client.ts typechecks strict and found the token in a Preferences.xml.
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 mechanism02-DECISIONS/0010-applications-live-in-their-own-repository.md— why applications are not here02-DECISIONS/0030-the-repository-structure.md— the repositories, and the open tier-4 question this repository answers03-DESIGN/00-as-is/10-module-catalogue.md— the catalogue's shape, and what it records