Issue 010 — the mesh's derived login does not fit every backend's identity rules
Found doing the per-backend provider e2e: redis and postgres accept the mesh's `as` (mesh_<node>_<module>) verbatim, but minio's S3 access key is capped at 20 chars and `as` is 22, so the provisioner cannot create the service account. `as` is doing two jobs — a stable identity the two ends agree on, and a literal identifier a backend must accept — and those are not always the same string. Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
This commit is contained in:
@@ -0,0 +1,63 @@
|
|||||||
|
---
|
||||||
|
status: open
|
||||||
|
opened: 2026-09-05
|
||||||
|
located-in: [mesh-control, mesh-catalog]
|
||||||
|
fixed-by:
|
||||||
|
amended-design:
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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 0053), 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 0053 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?
|
||||||
Reference in New Issue
Block a user