You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tenant ids have no single canonical validator. TenantId::new is infallible and
stores the string verbatim, and upstream there are three divergent charset
checks plus paths with none — so each backend defends individually and
inconsistently, which is how the Elasticsearch case-collision defect (companion
issue) became reachable.
Introduce one canonical constructor — e.g. TenantId::parse(&str) -> Result<…>
with a documented charset — and enforce it at tenant creation and at the REST
tenant-routing boundary. Keep an unchecked internal constructor only for trusted
construction (e.g. SYSTEM_TENANT). This lets each backend state a charset
precondition instead of re-deriving one, and closes the class of cross-tenant
collisions rather than one instance of it.
Summary
Tenant ids have no single canonical validator.
TenantId::newis infallible andstores the string verbatim, and upstream there are three divergent charset
checks plus paths with none — so each backend defends individually and
inconsistently, which is how the Elasticsearch case-collision defect (companion
issue) became reachable.
Spun off from #369 / PR #379.
Evidence
TenantId::newis infallible with no charset constraint —crates/persistence/src/tenant/id.rs:61-63.crates/rest/src/tenant/resolver.rs:283(is_ascii_alphanumeric()…)crates/rest/src/middleware/tenant_prefix.rs:63crates/rest/src/handlers/admin_tenants.rs:98(also permits.and/)escape (
crates/persistence/src/backends/s3/keyspace.rs:383) after S3 tenant registry: a tenant namedtenantspermanently breakslist_tenants()#271, whileElasticsearch still collapses case (companion issue).
Proposed direction
Introduce one canonical constructor — e.g.
TenantId::parse(&str) -> Result<…>with a documented charset — and enforce it at tenant creation and at the REST
tenant-routing boundary. Keep an unchecked internal constructor only for trusted
construction (e.g.
SYSTEM_TENANT). This lets each backend state a charsetprecondition instead of re-deriving one, and closes the class of cross-tenant
collisions rather than one instance of it.