Sketches the options for issue 010: the mesh's identityLimit (63, postgres's) is not the shortest among the backends the derived name reaches — S3's is 20 — so CheckIdentity lets an over-long access key through and minio fails at provision time. Options: bound by the true minimum and refuse at assignment (recommended, with a compact fallback held in reserve), per-interface bounds, or a provider-generated identity (rejected — breaks "the mesh says the identity once"). Links issue 010 to it. Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
68 lines
3.6 KiB
Markdown
68 lines
3.6 KiB
Markdown
---
|
|
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?
|
|
|
|
The options are sketched in **ADR 0054 (proposed)** — bound the identity by the true minimum and
|
|
refuse early (recommended), a compact fallback for overflow, per-interface bounds, or a
|
|
provider-generated identity (rejected). Awaiting ratification.
|