Identity / Naming #
identity = what something is
name = how we refer to it
binding = how a name resolves to a thing
Role in the catalog: the substrate of substrates — tier zero. Every coordinate, token, key, and ID the catalog has minted is an instance of this block:
cache keys → cache.md axis 4
idempotency keys → retry_idempotency axis 1
partition keys → shard.md axis 1
fencing epochs → lease_fencing axis 4
binding coordinates → checkpoint_replay*
correlation IDs → telemetry's join key
digests → index_structures.md, versioning.md
principals → policy.md axis 5
policy.md said “you cannot authorize what you cannot name.” The generalization is this block’s charter:
you cannot cache, dedupe, route, fence, audit, or garbage-collect
what you cannot name.
Central tension:
human-meaningful, stable, mutable handles
vs
machine-verifiable, immutable, recyclable-never references
Design Axes (the core module) #
Axis 1 — The Source of Identity (the structural cleave — the ninth ladder) #
Ordered by stability:
content-derived: identity IS the thing — SHA digest, Git object ID,
OCI layer, Merkle root. cannot be forged, moved,
or recycled; works ONLY for immutable facts.
the catalog's fourth encounter with content-
addressing, and each time it DISSOLVES a problem:
tearing (snapshot), replication conflict, memoization
keys (checkpoint_replay's off-axis seat), and now —
recycling (the star*).
authority-assigned: UUID, ULID, Snowflake, surrogate keys, k8s UID —
stable, but only as trustworthy as the MINT.
the tradeoff table is the mint's engineering:
UUID decentralized, large, unordered
Snowflake ordered-ish, compact, needs clock +
worker-ID discipline (a tiny
lease_fencing problem inside the mint)
ULID sortable, leaks creation time
guessability and time/shard leakage are the mint's
side channels (boundary.md's concern riding along)
location-derived: URL, path, host:port, IP — and the source doc's
best line demotes it correctly:
LOCATION IS A BAD IDENTITY BUT A GOOD RESOLUTION
RESULT. movement breaks the reference; the LB hides
the owner; the path renames.
Interrogation:
Which source mints this identity — and is the referent immutable enough
for the top rung? (facts vote digest; mutable things need a mint)
What does the ID leak — time, shard, sequence — and who reads it?
Is anything load-bearing built on a location? (it will move)
Axis 2 — Binding and Resolution (the crown motif) #
The name→thing arrow. Late binding is the workhorse:
logical name → resolver / control plane → endpoint set
(DNS, k8s Service, Envoy cluster)
The resolver is a cache — routing.md axis 3 already priced its staleness rungs. What is NATIVE here is the two-layer scheme:
STABLE OPAQUE ID + MUTABLE HUMAN ALIAS
user ID + username; k8s UID + name; inode + path
each layer fails independently:
the alias renames freely; the ID never moves.
collapse them into one name, and every rename is a data migration
and every reuse is the star*.
Interrogation:
Two layers, or one doing both jobs badly?
Which layer do REFERENCES hold? (durable references hold the ID;
UIs hold the alias; getting this backwards is the star* in waiting)
What happens when resolution is stale — and who owns that rung?
Axis 3 — Scope #
global vs namespaced collision is a scope failure, not bad luck
hierarchical paths, org/repo, tenant/user/resource —
inheritance is policy.md's rider (permission
inheritance bugs live at the seam); hot prefixes
are shard.md's skew; canonicalization and
case/encoding ambiguity are where "same name"
becomes a judgment call (and an attack surface:
path traversal is a canonicalization failure)
composite tenant_id + object_id; topic + partition + offset;
metric + labels — boundary.md's tenant-scope
motif, generalized. "forget one coordinate" is
cache axis 4's key-incompleteness, everywhere:
partial uniqueness assumed, cardinality riding
the label set (telemetry axis 3).
Interrogation:
Unique WITHIN WHAT? (say the scope out loud; collisions hide in the
unstated part)
Composite: enumerate the coordinates — which one does some code path
forget?
Is canonicalization defined — one spelling per name — before comparison?
Axis 4 — Incarnation (arrows) #
Versioned names — generation, epoch, term, resourceVersion, snapshot ID:
name + generation → fenced identity
This is lease_fencing’s token discipline and versioning’s stamp, restated — pure imports. The one seam worth naming: an identity WITHOUT an incarnation is ABA bait (retry’s CAS rung), and an incarnation without universal checking is a fence with holes (lease_fencing axis 3).
Axis 5 — Riders (arrows) #
What travels with the name:
authority capability names (signed URL, macaroon) → policy.md
axis 1, whole. "reference ≠ authority" is the confused
deputy at the naming layer: a normal name says WHAT;
a capability says WHAT + PERMISSION.
principal who is acting → policy.md axis 5 (attestation, the mint
for actors)
intent correlation ID, idempotency key, trace ID → retry axis 1
+ telemetry axis 2's join key: one intent ID, carried by
every effect, log, and retry it causes.
Technical Bottleneck: The Recycled Name* #
a name freed and reassigned:
the deleted-and-recreated principal, deleted-name reuse, squatting,
the ABA problem, the reconnecting member who inherits stale ownership.
The failure’s epistemics earn the star:
the reference RESOLVES, the operation SUCCEEDS, and it is WRONG —
a lie delivered through a successful lookup.
kin to torn visibility (the never-true) and resurrection (GC's ghost),
but in the namespace: the name outlived the object,
and old references silently rebound to a stranger.
Known recipes:
the dual-layer motif (flagship) k8s name + UID: the alias may
recycle; the UID is never minted
twice. every reference that MATTERS
holds the UID — so a recreated
namespace/pod/principal is visibly
a stranger, not silently a successor.
tombstoned names grace before reuse — GC's phase two,
applied to the namespace. versioning's
`reserved` field numbers are exactly
this star's recipe, already written:
a tombstone for meaning IS a tombstone
for a name.
generation-qualified references the epoch rides the name (axis 4):
session ID + generation, member ID +
incarnation — the reconnect is a NEW
identity by construction
content-addressing axis 1's top rung dissolves the star
outright: content cannot be reassigned
to different content. immutability
makes recycling meaningless.
A strong design says explicitly:
the source of every identity and what its mint guarantees (axis 1),
the two layers and which one references hold (axis 2),
the scope, spelled out, and every coordinate of composite keys (axis 3),
the incarnation that rides fenced identities (axis 4),
the riders — authority, principal, intent — and their owners (axis 5),
and for every deletable name: the grace, the tombstone, or the UID —
because a lookup that succeeds is not a lookup that told the truth.
The Big Questions (kept nearly whole — the best interrogation set in the source corpus) #
Who assigns it?
Is it human-meaningful or opaque?
Is it stable across rename / move / restart?
Is it globally unique or scoped — within what?
Is it mutable or immutable?
Does it include version/incarnation?
Does it carry authority?
Can it be reused after deletion? ← the star's question
Can it be guessed?
Can it be resolved offline?
What happens if resolution is stale?
Canonical Motifs (kept, with owners attached) #
stable opaque ID + mutable alias the crown motif (axis 2; star* flagship)
logical name + resolver + endpoints late binding (axis 2; routing.md rungs)
content digest + manifest axis 1's top rung (Git, OCI, Nix)
name + epoch/generation fenced identity (→ lease_fencing)
principal + credential + policy → policy.md axes 5 and 1
correlation ID + idempotency key → retry axis 1; telemetry's join
hierarchical namespace + inheritance axis 3 (+ policy.md's rider)
Named Configurations (lookup table) #
Vector = {source, layers, scope, incarnation, riders}. Rows marked → are owned elsewhere.
| Name | Vector | Canonical study object | Signature failure |
|---|---|---|---|
| Human/semantic names | assigned alias, layer 2 of the motif, namespaced, —, — | usernames; Service names | rename; collision; squatting; deleted-name reuse* |
| Opaque assigned IDs | authority-assigned, layer 1, scoped by mint, —, leaks | UUID/ULID/Snowflake; k8s UID | mint hotspot; guessability; time/shard leakage; wrong scope |
| Content-addressed | content-derived, self-verifying, global by math, immutable, — | Git objects; OCI digests | mutable tag mistaken for digest (versioning); hash-algorithm migration; metadata outside the digest |
| Location names | location-derived, —, physical, —, — | URL; host:port | movement breaks references; “a resolution result, not an identity” |
| Late-bound logical names | alias over resolver, both layers, namespaced, —, — | DNS; k8s Service; Envoy cluster | stale resolver (routing rungs); wrong namespace; name repointed to incompatible backend (versioning’s envelope) |
| Versioned/incarnation → lease_fencing, versioning | any + epoch, —, —, the fence, — | terms; resourceVersion; producer epoch | (owned: stale-actor mutation, ABA, mixed versions) |
| Principal identity → policy.md axis 5 | attested, credentialed, per-trust-domain, rotated, authority rider | SPIFFE; OIDC subject; IAM ARN | (owned) + principal deleted/recreated with same name* — the star in its most dangerous costume |
| Capability names → policy.md axis 1 | token, —, audience-scoped, expiring, what + permission | signed URLs; macaroons | (owned: leak = access, revocation, confused deputy) |
| Correlation/intent → retry, telemetry | caller-minted, —, per-operation, —, intent rider | request/trace/idempotency IDs | (owned: missing ID orphans signals; new-ID-per-retry duplicates effects) |
| Membership/session | assigned + generation-qualified, —, per-protocol, incarnated, — | ZK session; group member ID | reconnect ambiguity*; old session alive (lease_fencing); stale ownership inherited* |
| Hierarchical names | path, inherited scope, canonicalized(?), —, policy rider | filesystem; org/repo; namespaces | parent rename; inheritance bugs; traversal; hot prefix (shard); encoding ambiguity |
| Composite identity | multi-coordinate, —, the coordinates ARE the scope, —, — | tenant+object; topic+partition+offset | forgotten coordinate (cache axis 4); label cardinality (telemetry); partial uniqueness |
Vocabulary #
identity name binding resolution referent
mint opaque alias canonical redirect
digest content-addressed self-verifying tag vs digest
namespace scope hierarchy canonicalization traversal
composite key coordinate partial uniqueness
incarnation generation epoch ABA
recycled name tombstone grace squatting
capability principal correlation intent
dual layer UID + name late binding
Deep Lesson #
Identity bugs come from confusing pairs the whole catalog inherits:
name vs object (axis 2: the alias is not the thing —
the dual layer exists because they diverge)
object vs version (axis 4: which incarnation? — lease_fencing's
question, asked at the naming layer)
identity vs location (axis 1: where it is today is not what it is)
reference vs authority (axis 5: a name that grants is a capability,
and must be treated like one — policy.md)
Design procedure: choose the source per referent (facts get digests, mutable things get a mint), run the dual-layer motif and put the UID in every durable reference, spell out the scope and every composite coordinate, let the epoch ride anything fenceable, hand the riders to their owners — and never free a name without a tombstone, because the most dangerous lookup in the catalog is the one that succeeds. The named types are recognition shortcuts, not the design space.