Resolves the ArcadeDB database name for a :context-multitenant resource +
tenant. The name reaches a URL path, so it must be a valid Arcadic.Identifier
(letter-first, ≤128 bytes), injective (distinct tenants → distinct databases — a
hard isolation invariant), and deterministic.
Default two-branch encoder:
- passthrough — a tenant whose stringified form is
[A-Za-z0-9_]+becomes"t_" <> tenant(thet_supplies the letter start; a leading digit is fine). Keeps ULID/integer/slug tenants readable. - encode — anything else becomes
"g" <> Base.encode32(tenant, :lower, no-pad); alphabet[a-z2-7], thegguarantees a letter start.
Branch A always starts t, branch B always starts g → disjoint namespaces;
each branch is a constant prefix over an injective input. Anything that will not
fit 128 bytes fails closed with a value-free error (steer to tenant_database).
The encoder keys on to_string(tenant), so distinct tenant terms that share a
string form collide — integer 42 and string "42" both map to "t_42". This is
harmless in a homogeneous tenant space; a space that mixes term types for the same
logical tenant must set tenant_database to disambiguate. The default also assumes
a String.Chars tenant: a non-String.Chars term (tuple/map/struct) raises rather
than encoding — steer such tenants through tenant_database.
NOTE: the derived name is operator-visible (server logs, Arcadic.Server.list_databases).
The passthrough branch echoes the tenant id into that surface — a tenant space whose
id is itself classified should set tenant_database to hash it (see usage-rules).
Summary
Functions
The ArcadeDB database name for resource + tenant, or a value-free raise (fail-closed).
Functions
@spec database_name(Ash.Resource.t(), term()) :: String.t()
The ArcadeDB database name for resource + tenant, or a value-free raise (fail-closed).