The registry's public name is a second module beside the store, locked by the registry itself

The predecessor serves the registry under a public name, behind htpasswd basic auth, with a
twenty-gigabyte body limit for layer pushes. The mesh's registry has no name, no lock and no
limit — by design inside the mesh, where the private network is the boundary and every node
pulls without an account (hq ADR 0082). Taking the name over must not change that.

A route on `distribution` itself would: contributing a route is requiring one, and the store
is raised at genesis on a node with no proxy. So the public door is `distribution-gate`, a
second registry process on the same volume, behind the registry's own htpasswd (the
predecessor's realm, the predecessor's file, carried in with `secret accept`), with the
route and its limit. It requires the store's storage as a node-scoped provision, so it can
only land beside the store. The store's own door is untouched — no auth, no htpasswd — which
is what keeps the builder's pushes and every node's pulls working.

Both processes read the predecessor's configuration where it changed behaviour: delete
enabled, which tag retention depends on; no per-process descriptor cache, which two
processes over one store cannot share; the CORS headers for the retired interface dropped.

route-adapter writes the limit as the predecessor's own buffering middleware, named after
the router, only when asked for — and skips a route whose limit it cannot read rather than
carrying what the module said not to.

hq ADR 0082/0104, the registry hand-over.
This commit is contained in:
2026-09-23 23:19:12 +02:00
parent 9f2c678355
commit 3249b9a0cc
5 changed files with 220 additions and 6 deletions
+19 -1
View File
@@ -5,6 +5,10 @@
{
"name": "artifact-store",
"scope": "mesh"
},
{
"name": "artifact-storage",
"scope": "node"
}
],
"claims": [
@@ -25,6 +29,9 @@
"serves": {
"artifact-store": {
"port": 5000
},
"artifact-storage": {
"volume": "mesh-registry-data"
}
},
"listens": [
@@ -42,6 +49,13 @@
"path": "/var/lib/mesh/registry",
"mode": "0700"
},
{
"id": "config",
"type": "file",
"path": "/var/lib/mesh/registry/config.yml",
"mode": "0644",
"content": "# The registry's configuration, written by the mesh from the module's manifest.\n#\n# Carried over from the predecessor's registry.yml where it changed behaviour (novox/hq ADR 0082,\n# the registry hand-over):\n# - storage.delete.enabled: the image's default refuses DELETE on a manifest; the predecessor\n# enabled it, and tag retention and garbage collection depend on it.\n# - no storage.cache: the image's default keeps an in-memory blob-descriptor cache, which is\n# right for one process and wrong for two on one store — the mesh door and the public door\n# are two registry processes sharing this filesystem, and a descriptor cached by one and\n# deleted through the other would say a blob exists that does not.\n# Dropped: the CORS headers, which served the browser interface that is being retired.\nversion: 0.1\nlog:\n fields:\n service: registry\nstorage:\n delete:\n enabled: true\n filesystem:\n rootdirectory: /var/lib/registry\nhttp:\n addr: :5000\n headers:\n X-Content-Type-Options: [nosniff]\nhealth:\n storagedriver:\n enabled: true\n interval: 10s\n threshold: 3\n"
},
{
"id": "store",
"type": "container",
@@ -51,7 +65,11 @@
"5000:5000"
],
"volumes": [
"mesh-registry-data:/var/lib/registry"
"mesh-registry-data:/var/lib/registry",
"/var/lib/mesh/registry/config.yml:/etc/docker/registry/config.yml:ro"
],
"restart-on": [
"config"
]
}
]