// minio's provisioner — the adapter that makes minio a provider of the mesh `s3-bucket` interface // (the name in module.json's `provides`). The reconcile loop, the contributions file, and reading // the mesh's minted secret are the sdk harness's; this writes only the per-service half: how minio // creates and removes a consumer's bucket and its scoped access key (novox/hq ADR 0039/0040/0048). // // The `s3-bucket` interface: a consumer connects to an S3 endpoint with an access key confined to // its own bucket. It depends on `s3-bucket`, not on minio, so any S3-compatible provider could serve // it. // // **The access key and its secret are the mesh's, not the provisioner's (ADR 0048).** The mesh // derives the login (the access-key id) and hands it to both ends, and mints the secret key. minio // creates the service account under exactly that access key with exactly that secret — a credential // the provisioner invented is one the consumer could never present. // // **The bucket name is the mesh's too (ADR 0202).** It used to be computed here, from the login, // and every consumer transcribed the same rule into its own definition by hand — two copies of // one rule with nothing comparing them, and one of three was wrong for months. Now the rule is a // line of this module's manifest (`serves.s3-bucket.bucket: ${consumer:as:dns}`), the mesh fills // it per consumer, and the same filled value reaches this provisioner and the consumer's own // configuration. There is no second computation to disagree with. import { runProvisioner, type Provision } from "@novox/mesh-sdk/provisioner"; import { emit } from "@novox/mesh-sdk/events"; import { MinioClient } from "../client.js"; import { ensureLinkKey } from "../links.js"; import { handlers } from "./handlers.js"; const minio = MinioClient.fromEnv(); // minio's own link keys (issue 1594): the secrets live under the state directory, nowhere else. const linksDir = process.env.MESH_MINIO_LINKS ?? ""; // At start every bucket that exists gets its link key too, those made before link keys were (best effort: // a bucket that fails is said, the provisioner still serves). void (async () => { if (linksDir === "") { console.error("[minio] MESH_MINIO_LINKS is not set: no link keys made"); return; } try { for (const b of await minio.listBuckets()) { try { await ensureLinkKey(minio, linksDir, b.name); } catch (err) { console.error(`[minio] link key for ${b.name}: ${err}`); } } } catch (err) { console.error(`[minio] could not list buckets for link keys: ${err}`); } })(); runProvisioner("s3-bucket", handlers({ minio, linksDir, announce })); /** Emit best-effort: a broker hiccup is logged and dropped, never allowed to throw back and fail a * bucket that was made. */ async function announce(type: string, body: unknown): Promise { try { await emit(type, body); } catch (err) { console.error(`[minio] could not emit ${type}: ${err}`); } }