Files

4.4 KiB
Raw Permalink Blame History

status, opened, located-in, fixed-by, amended-design
status opened located-in fixed-by amended-design
resolved 2026-09-05
mesh-control
mesh-catalog
ADR 0049 (a slug for the login) + a shorter minted secret (mesh-control) 0049-a-consumers-identity-fits-the-tightest-backend.md

The mesh's derived login does not fit every backend's identity rules — S3 rejects it

What was observed

Proving the provider/consumer contract per backend (ADR 0048), redis and postgres passed: a consumer authenticated against the provider with the login the mesh derived and the password the mesh minted. minio failed, and not on the credential — on the name:

mc: <ERROR> Unable to add a new service account. The access key is invalid.
    (access key length should be between 3 and 20).

The mesh derives a consumer's login as mesh_<node>_<module> — here mesh_anchor_bucketuser, 22 characters. That is a valid postgres role and a valid redis ACL user, so those providers create it verbatim. S3 access keys are capped at 20 characters, so minio refuses to create the service account under it, and the provisioner retries forever while the consumer, holding that same too-long access key, could never present it either.

Why it matters beyond this instance

ADR 0048 says a provider creates exactly the login the mesh derived, so that the two ends agree by construction — the mesh hands the same name to the provider (to create) and the consumer (to present). That only holds if the derived name is one every provider can accept. It is not: the mesh's as is a single format with no knowledge of a backend's identity rules, and S3's are stricter than a database's. Any provider whose backend constrains identifiers more tightly than postgres — a length cap, a charset, a required prefix — inherits this, and the failure lands at provision time, per consumer, as an infinite retry rather than a refusal at assignment.

This also shows the seam is real, not cosmetic: as is doing two jobs — a stable per-consumer identity the two ends must agree on, and a literal identifier a specific backend must accept — and those are not always the same string.

The shape of a fix (open, not decided)

  • Constrain the derivation so as is broadly acceptable — short (≤ 20), a conservative charset, deterministic. This keeps "the provider creates exactly what the mesh derived" true everywhere, at the cost of a less legible name, and it is a mesh-wide identity change (every provider that already created the longer name would see it change).
  • Let a provider map as to a backend-valid identifier it derives the same way on create and on the consumer's behalf — but the consumer is generic and cannot run minio's mapping, so this only works if the mapped identifier is delivered back to the consumer. That is the data-provision return path this era keeps meeting (umami's siteId, cloudflare's record) and does not yet have.
  • Declare the constraint on the interface (s3-bucket states its identifier bounds) and have the mesh derive within them — the most honest, the most work.

Open questions

  • Is as meant to be human-legible, or is a short opaque token acceptable — i.e., can the derivation simply be shortened without anyone minding?
  • Do redis/postgres actually want the long name, or did it only survive because they are permissive? If nothing needs it long, the cheap fix is to cap it.
  • Does this fold into the same decision as the data-provision return path, or is it separate?

Resolution

Accepted ADR 0049 (option E): a module declares an optional short slug, and the mesh derives mesh_<node>_<slug|name>, bounded by the tightest backend (an S3 access key's 20) and refused at assignment — naming the slug as the remedy — when it still would not fit. The minio grant e2e proved it: bucketuser declares slug: bkt, so its access key mesh_anchor_bkt (15) is accepted where mesh_anchor_bucketuser (22) was refused.

Proving that surfaced a second S3 length constraint on the same credential — the secret. The mesh minted a 43-character password (32 random bytes, base64url), and an S3 secret key is 8–40. Fixed in mesh-control internal/secrets/seal.go by minting 30 bytes → exactly 40 characters (240 bits, ample), which fits S3 and every other backend. Both halves of an S3 credential — the access key (login) and the secret key (password) — now fit the tightest backend, by the same rule.