mailu: the manifest matches the machine, provides smtp, and carries automx
Five gaps between the draft and what actually runs, each verified live before being written down: - front published bare 80 — the machine port Traefik holds; now the predecessor's own mappings (7080:80, 7443:443) plus the 110/143/995 parity ports the draft dropped. Pruning legacy protocols is its own deliberate change, not a cutover side effect. - TLS_FLAVOR said cert, which nothing supplies; live is letsencrypt — mailu runs its own certbot, state already on disk, HTTP-01 answered through a path-scoped route contribution (priority above the web one). - the web route said http:7080, the redirect-loop shape; it now says what the hand-authored file always knew: https 7443, insecure. - automx was absent entirely: the autoconfig responder is now a second artifact (its Containerfile moved in from the predecessor's images dir, base declared per ADR 0097), a container on a real data dir — the anonymous-volume loss of 2026-08-10 stays fixed — and the three public names are route contributions. - and the reason this moved ahead of de-spiegel: mailu now provides smtp. A consumer contributes the account it sends as; the provisioner creates <account>@<domain> via the admin API and applies the minted password every reconcile (ADR 0048). The domain is served on the binding so a consumer composes its own login from mesh facts. route-adapter learns to say no: a contribution over https, scoped to a path, or carrying a policy is skipped aloud rather than written into a file shape that cannot say it — plain http into a TLS listener was the concrete wrong file this prevents. The hand-authored files keep covering those routes until the mesh's own proxy takes over, exactly as today.
This commit is contained in:
@@ -151,6 +151,24 @@ export function routesFrom(document: unknown, machine: string): { routes: Route[
|
||||
skipped.push(`${from} asked for ${JSON.stringify(name)}, which is not a name this can write`);
|
||||
continue;
|
||||
}
|
||||
// What this adapter's one file shape cannot say, it skips aloud rather than approximating:
|
||||
// a backend over its own TLS (the file would send plain http into a TLS listener), a
|
||||
// path-scoped or refusing or redirecting rule (the file routes whole hosts). The mesh's own
|
||||
// proxy serves all of these the day it takes over; until then the predecessor's hand-authored
|
||||
// files keep covering them, exactly as they do today.
|
||||
const scheme = typeof entry.values?.["scheme"] === "string" ? (entry.values["scheme"] as string).trim().toLowerCase() : "";
|
||||
if (scheme !== "" && scheme !== "http") {
|
||||
skipped.push(`${from} asked for route ${name} over ${scheme}, which this file shape cannot say`);
|
||||
continue;
|
||||
}
|
||||
if (typeof entry.values?.["path"] === "string" && (entry.values["path"] as string).trim() !== "") {
|
||||
skipped.push(`${from} asked for route ${name} scoped to a path, which this file shape cannot say`);
|
||||
continue;
|
||||
}
|
||||
if (entry.values?.["deny"] === true || typeof entry.values?.["redirect"] === "string") {
|
||||
skipped.push(`${from} asked for route ${name} with a policy this file shape cannot say`);
|
||||
continue;
|
||||
}
|
||||
const port = asPort(entry.values?.["port"]);
|
||||
if (port === undefined) {
|
||||
skipped.push(`${from} asked for route ${name} and gave no usable port`);
|
||||
|
||||
Reference in New Issue
Block a user