Skip to main content
  1. concepts/

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.

NameVectorCanonical study objectSignature failure
Human/semantic namesassigned alias, layer 2 of the motif, namespaced, —, —usernames; Service namesrename; collision; squatting; deleted-name reuse*
Opaque assigned IDsauthority-assigned, layer 1, scoped by mint, —, leaksUUID/ULID/Snowflake; k8s UIDmint hotspot; guessability; time/shard leakage; wrong scope
Content-addressedcontent-derived, self-verifying, global by math, immutable, —Git objects; OCI digestsmutable tag mistaken for digest (versioning); hash-algorithm migration; metadata outside the digest
Location nameslocation-derived, —, physical, —, —URL; host:portmovement breaks references; “a resolution result, not an identity”
Late-bound logical namesalias over resolver, both layers, namespaced, —, —DNS; k8s Service; Envoy clusterstale resolver (routing rungs); wrong namespace; name repointed to incompatible backend (versioning’s envelope)
Versioned/incarnation → lease_fencing, versioningany + epoch, —, —, the fence, —terms; resourceVersion; producer epoch(owned: stale-actor mutation, ABA, mixed versions)
Principal identity → policy.md axis 5attested, credentialed, per-trust-domain, rotated, authority riderSPIFFE; OIDC subject; IAM ARN(owned) + principal deleted/recreated with same name* — the star in its most dangerous costume
Capability names → policy.md axis 1token, —, audience-scoped, expiring, what + permissionsigned URLs; macaroons(owned: leak = access, revocation, confused deputy)
Correlation/intent → retry, telemetrycaller-minted, —, per-operation, —, intent riderrequest/trace/idempotency IDs(owned: missing ID orphans signals; new-ID-per-retry duplicates effects)
Membership/sessionassigned + generation-qualified, —, per-protocol, incarnated, —ZK session; group member IDreconnect ambiguity*; old session alive (lease_fencing); stale ownership inherited*
Hierarchical namespath, inherited scope, canonicalized(?), —, policy riderfilesystem; org/repo; namespacesparent rename; inheritance bugs; traversal; hot prefix (shard); encoding ambiguity
Composite identitymulti-coordinate, —, the coordinates ARE the scope, —, —tenant+object; topic+partition+offsetforgotten 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.