Username Allocation (Koder ID)

mandatory

Regras de alocação de usernames no Koder ID: reservas, padrões proibidos, migração. Depende de RFC-012 (account models) e RFC-013 (invite chain). Status: Draft (proprietário: Koder ID team).

Policy — Username Allocation for Koder ID

  • *wner:*Koder ID team
  • *epends on:*platform/id/v2/docs/rfcs/RFC-012-account-models.md, platform/id/v2/docs/rfcs/RFC-013-invite-chain.md
  • *ate:*20260411
  • *tatus:*Draft

Scope

This policy governs the allocation, format, reservation, transfer, and reclamation of user handles in the Koder ID individual account namespace. Every handle h in this namespace becomes the email address h@koder.dev and the public identifier @h throughout the Koder ecosystem.

Workspaceowned email addresses (ana@crescer.com.br, rodrigo@vivver.com.br, etc.) are *ot*governed by this policy — they are issued by the workspace admin under the workspace's own domain. See RFC012 for the distinction.

Format rules

A handle is a string satisfying all of:

  1. *ength:*2 to 20 characters
  2. *haracters:*lowercase ASCII letters (az), digits (09), hyphens (-), dots (.)
  3. *ust start*with a letter
  4. *ust not end*with a hyphen or a dot
  5. *o consecutive special characters*— foo..bar, foo--bar, foo-.bar are invalid
  6. *o leading digits*— 2rodrigo is invalid (digit in any other position is fine: rodrigo2, r2d2)
  7. *o RFC5321 localpart edge cases*— anything that would require quoting in an email local part is forbidden, even if technically legal

*anonicalization:*handles are stored and compared in lowercase ASCII; Unicode is not permitted in the current version. A user who types Rodrigo@koder.dev gets routed to the same identity as rodrigo@koder.dev.

*onfusable check:*on allocation, the candidate handle is checked against a confusables table (similar to IDN homograph detection). rodrlgo (lowercase L instead of i) is rejected if rodrigo already exists. The confusables set is versioned and enforced only at allocation — existing handles are never broken by adding new confusables.

Length tiers and tier-based reservation

Handles are partitioned into *ength tiers*with different allocation rules:

Tier Length Allocation rule
*2* 2 chars *eserved*for Koder staff (roles staff or board). Allocated during Phase 0 only. Cannot be claimed by external users.
*3* 3 chars *eserved*for trust-score ≥800 during Phases 0 and 1; opens to general allocation in Phase 2 if still available
*4–T6* 4–6 chars First-come, subject to the reservation dictionary
*7+* 7+ chars First-come, subject to the reservation dictionary

Tier T2 is the scarcity anchor — the whole namespace knows that 2letter handles are staffonly forever. This is the strongest visual marker we can give without breaking the singledomain rule from RFC012.

Reservation dictionary

Certain handles are reserved at all times and cannot be allocated to any user via the normal flow. The dictionary has the following categories:

1. System handles (locked forever)

These are used by the Koder ID service itself and by Koder system features. Examples:

admin         root          system        koder        support       help
noreply       postmaster    abuse         security     hostmaster    webmaster
mailer-daemon  info         contact       privacy      legal         billing
api           auth          id            oauth        sso           webhook
mail          ns            dns           www          ftp           smtp

The full list lives in platform/id/v2/services/identity/reserved_system.txt and is loaded at service startup.

2. Product names (locked unless Koder-owned)

Every Koder product slug is reserved — these can only be used by system accounts owned by the Koder workspace:

kruze         kortex        flow          talk          jet          kall
kode          koda          koder         store         wallet       kdb
dok           grid          kompass       kmd           apis         hub

Renames are handled by adding the new name and keeping the old. The dictionary is append-only.

3. Brands and trademarks (locked)

Global brand names and registered trademarks are pre-reserved to prevent squatting. Categories include:

  • *ig tech:*google, apple, microsoft, amazon, meta, facebook, twitter, x, tiktok, netflix, openai, anthropic, ...
  • *anks and payments:*visa, mastercard, paypal, stripe, nubank, itau, bradesco, santander, ...
  • *overnments:*gov, governo, fed, eu, un, nato, ...
  • *eo:*names of countries, states, capital cities, and top-50 cities globally (one list per language)

A brand reservation means the handle is held by the Koder ID system account, not assigned to anyone. If the trademark owner wants to claim it, they go through the reclamation process (below). The initial list has ≈5000 entries; it is maintained quarterly.

4. Profanity and hate speech (locked)

Handles that would be offensive or promote hate are reserved. The list is multilingual and curated by the Koder trust & safety team. Exact contents are not public to avoid providing a blocklist users can test against; contents are versioned and updated as needed.

5. Ambiguous / confusing (casebycase)

Handles that would be routinely mistaken for system handles (e.g., admln, r00t, postmast3r) are reserved even if they pass the confusables check for existing handles. Added ad-hoc to the dictionary.

Allocation during rollout phases

The allocation rules depend on the rollout phase from RFC-012.

Phase 0 — Internal alpha (closed)

  • *ho allocates:*Koder ID admin, manually, on behalf of each staff member
  • *ier availability:*all tiers (T2, T3, T4+) open to staff
  • *taff handle preferences:*collected via an internal form; allocated in order of seniority for conflicts, then alphabetical
  • *eservation dictionary:*enforced (staff cannot take admin or google, even during Phase 0)
  • *udit:*every Phase-0 allocation is logged with actor, reason, and handle

Phase 1 — Invite-only (seed)

  • *ho allocates:*the invitee, at redemption time
  • *ier availability:*T4+ open to all invitees; T3 only to invitees with starting trust score ≥800 (i.e., invited directly by staff)
  • *eservation dictionary:*enforced
  • *onfusables:*enforced; the signup form suggests alternatives if the chosen handle is a confusable of an existing handle
  • *eclaim path:*trademark owners can initiate reclamation (see below) even during Phase 1

Phase 2 — Public signup

  • *ho allocates:*the signup user, at signup time
  • *ier availability:*T3 opens to general allocation (for handles not already taken); T2 remains staff-only forever
  • *eservation dictionary:*enforced
  • *raud detection:*bulk handle registration patterns (many handles from same IP, same payment method, etc.) trigger review

Transfer rules

Handles are *pt-in only*transferable. There is no involuntary reassignment during normal operation.

Voluntary transfer

A user can transfer their handle to another user (both must consent) via the admin UI. The transfer:

  1. Requires both users to be in status = 'active'
  2. Requires the source user to have a secondary handle already allocated (nobody ends up identity-less after transfer)
  3. Is logged in the audit trail with both actor IDs
  4. Cannot be used to bypass the reservation dictionary (a transferred handle must have been validly owned — the dictionary check happens on allocation, not on every transfer)

Deletion and release

When a user deletes their account:

  • The users row is soft-deleted (deleted_at set)
  • *he handle is NOT released.*It remains bound to the soft-deleted user row
  • Rationale: releasing the handle allows an attacker to register @rodrigo@koder.dev after the real Rodrigo deletes his account, and impersonate him in third-party systems that cached Rodrigo's handle as an identity

Reclamation (handle release after long dormancy)

After *8 months*of continuous inactivity (no login, no API activity, no email delivery), a handle *ay*be released through a formal process:

  1. The identity service flags the user as dormant at 12 months
  2. At 15 months, an email is sent to the registered recovery address warning of pending release
  3. At 18 months, the handle enters pending_release state for 30 days with a public listing
  4. During the 30-day window, the owner can reactivate by logging in (reclaim is instant) OR any other user can apply to claim the handle
  5. After the window, if unclaimed, the handle is released and returned to the general pool; if claimed by another user, a dispute review is triggered

*his process does not apply to staff handles or to T2/T3 handles ever allocated to staff.*Once staff-tagged, a handle stays in the staff namespace even after the staff member leaves (their alumni record retains the handle).

Reclamation (trademark and impersonation disputes)

A third party may request reclamation of a handle they believe belongs to them legally (trademark) or factually (impersonation).

Process

  1. Submit a reclamation request via https://id.koder.dev/reclaim or via email to abuse@koder.dev
  2. Provide: the disputed handle, proof of trademark registration or documentation of identity, a contact email, a clear statement of what the claimant wants (transfer, take-down, suspension)
  3. Koder ID trust & safety team reviews within 10 business days
  4. If the claim is valid and the current handle holder is not a Koder staff member:
    • The current holder is notified and given 14 days to respond
    • If no response or the response does not establish a legitimate claim, the handle is suspended and transferred to the claimant (or parked in the reservation dictionary if the claimant only wanted take-down)
  5. If the claim is invalid, it is denied with a written explanation
  6. Disputes about the decision can be escalated to Koder legal (not in scope for this policy)

Limitations

  • Trademark reclamation applies only to handles that could plausibly be confused with the trademark — mcdonalds is reclaimable by McDonald's, mcdonaldspt may or may not be, iloveeatingatmcdonalds is not
  • Impersonation reclamation requires evidence of actual impersonation (the holder is actively pretending to be the claimant), not just name similarity
  • Celebrities and public figures can request reclamation of their own name handles if the current holder is inactive or clearly impersonating them
  • Staff-held handles are not reclaimable via this process — they are resolved through internal HR/legal channels

Handle lifecycle

             ┌──────────────┐
             │  (unclaimed) │
             └──────┬───────┘
                    │ allocation
                    ▼
             ┌──────────────┐
             │    active    │◄────────────────┐
             └──────┬───────┘                 │
                    │                         │ reactivation
                    │ 12 months no activity   │
                    ▼                         │
             ┌──────────────┐                 │
             │   dormant    │─────────────────┘
             └──────┬───────┘
                    │ + 6 months
                    ▼
             ┌──────────────┐
             │pending_release│
             └──────┬───────┘
                    │ + 30 days
                    ▼
             ┌──────────────┐
             │   released   │─────► back to unclaimed pool
             └──────────────┘

Orthogonal to lifecycle:

  • *uspended*— handle is held by the user but they cannot login or use the account. Reason logged. Cleared manually by admin.
  • *isputed*— handle is held but frozen pending reclamation review. Cleared by decision.
  • *eserved*— handle is in the dictionary and unallocable.

Staff handle policy

Special rules apply to handles used by Koder staff (role staff in the Koder workspace):

  1. *nce staff, staff-marked*— a handle that was ever allocated to a staff member is tagged in the system as staff_allocated = true, and this tag is permanent
  2. *lumni retain their handle*— when a staff member leaves Koder and transitions to alumni, they keep the handle; it never goes back to the pool
  3. *2 handles are staffonly forever*— even in Phase 2, 2letter handles are not offered in the signup flow
  4. *taff cannot take brand reservations*— even staff cannot allocate google or apple; the dictionary applies equally
  5. *taff cannot selftransfer to external accounts*— a handle that was staffallocated cannot be transferred to a non-staff individual outside the alumni flow

Audit and transparency

  • Every allocation is logged in users_audit with {handle, user_id, phase, allocator, reason}
  • Every transfer, reclamation, suspension, and release is logged
  • Aggregate statistics (number of allocated handles, number of suspended, number of reserved) are published on a public status page; individual allocations are not
  • The reservation dictionary is *ppendonly*and versioncontrolled; additions are reviewed by ≥2 members of trust & safety; removals are disallowed without RFC

Decisions — hyperscalealigned (202604-11)

These items are resolved in favor of the 100M+ tenant hyperscale target. The shape of the policy is now frozen; only cosmetic adjustments remain.

Unicode in handles — forbidden, forever (subject to new RFC)

*SCII lowercase only*in the current version and all foreseeable versions. Enabling Unicode would reintroduce:

  • *omograph attacks*at massive scale (Cyrillic а vs Latin a, Greek ο vs Latin o, etc.) — the IDN homograph problem has been a source of phishing for 20 years and is unsolvable at the registry level
  • *orting and indexing complexity*— collation rules vary by locale and break global uniqueness guarantees
  • *endering inconsistency*— different fonts render the same Unicode codepoint differently; users cannot reliably distinguish handles visually
  • *ength ambiguity*— grapheme clusters vs codepoints vs bytes, each with different answers

The lesson from DNS, email localparts, IRC nicks, and every global identifier system is the same: *owercase ASCII is the Schelling point for global identity* Users who want nonASCII displays can set a display_name with any Unicode they want — the handle stays ASCII. A future RFC may revisit this, but it is a binding "no" for v1.

Handle resale — forbidden, period

No monetary transfer of handles, ever, by any mechanism. Reasons:

  1. *revents handle squatting markets*— the whole reason we have a reservation dictionary and a strict allocation policy is to prevent handles from becoming financial assets
  2. *revents pressure on the trust & safety team*— if handles had dollar values, every dispute would involve economic damages claims; the dispute process becomes litigation
  3. *revents disparate access*— wealthy users cannot buy @ceo or @admin from the current holder even if both agree
  4. *ligns with Koder's brand*— the Koder identity is a credential of membership, not a tradeable asset. Selling it would contradict "todos somos dev".

Voluntary transfers between users (no money involved) remain permitted through the normal transfer flow, but the trust & safety team audits transfers for implicit compensation patterns (off-platform payments disguised as free transfers) and can reverse suspicious transfers.

Public handle registry — yes, rate-limited

A public endpoint GET https://id.koder.dev/u/:handle is provided and returns:

{
  "handle": "rodrigo",
  "taken": true,
  "display_name": "Rodrigo P.",
  "has_avatar": true,
  "badges": ["verified", "developer"],  // badge kinds only, not signatures
  "created_year": 2026                    // year granularity, not exact date
}

*ate limits:*

  • *nauthenticated:*30 requests per minute per IP, 500 per hour per IP
  • *uthenticated:*300 requests per minute per user, 5 000 per hour per user
  • *lobal:*1M requests per hour across the entire endpoint (circuit breaker)

These limits prevent bulk handle enumeration (scraping the whole namespace) while supporting legitimate uses: signup form availability checks, profile previews, handle mention autocomplete. Suspicious patterns (sequential handle scans, randomname fuzzing) trigger perIP backoff.

The endpoint does *ot*return: email address (always derivable from handle), phone number, login methods, billing info, workspace memberships, invite chain, trust score.

Dormancy period — tiered by identity value

Revised from the single "18 months" to a tiered schedule based on identity value:

Account class Inactive trigger Pending release window
*nverified, no paid activity, T4+ handle* 24 months 60 days
*erified (KYC badge) OR paid transaction history* 60 months (5 years) 90 days
*3 handle (3 chars)* Never auto-releases n/a
*2 handle (2 chars, staff-only)* Never auto-releases n/a
*lumni* Never auto-releases n/a
*taff* Never auto-releases n/a

The tiering recognizes that at hyperscale, some handles are much more valuable and represent real people with sunk investment. Five years of inactivity is roughly the Gmail industry standard for "serious accounts." Shorter tiers for low-value accounts keep the namespace fresh.

The 18-month general cap from the earlier draft is *eplaced*by these tiers.

Staff handle after death — never reuse without nextofkin

Confirmed as policy:

  1. A staff member's handle is never automatically released or repurposed, even after confirmed death
  2. The workspacemembers row transitions to status = 'deceased' (a new distinct status) with `deceasedat` timestamp
  3. A memorial badge may be added with nextofkin consent
  4. The handle can be transferred to a named beneficiary *nly*if the staff member left explicit written instructions and nextofkin and Koder trust & safety agree
  5. Absent instructions, the handle stays indefinitely in the Koder workspace reservation namespace — neither released nor actively used

This same policy extends to any verified public figure whose death is confirmed — the handle is preserved as a matter of dignity, not recycled for namespace efficiency.

Machine identities — separate namespace entirely

Bots, service accounts, API integrations, webhook senders, and other non-human identities do *ot*consume human handle slots. They live in a distinct namespace with its own rules:

  • *andle format:*<name>.bot@koder.dev — the .bot suffix is reserved and may not be claimed by any human handle
  • *o trust score*— machines have trust_class instead (from system, verified_org, third_party, untrusted)
  • *o invites*— machines are provisioned by workspace admins, not invited
  • *o badges*— machines carry service_attestation instead (also cryptographically signed, but a different issuer key)
  • *tored in a separate table*service_identities with its own schema (to be specified in a companion RFC)

This isolation means a human on @rodrigo@koder.dev and a machine on @rodrigo.bot@koder.dev can coexist without ambiguity — the .bot suffix is an unforgeable marker because humans cannot register handles ending in .bot.

Reservation dictionary versioning at hyperscale

At 10⁸ identities, adding entries to the reservation dictionary has operational impact: handles that were valid allocations yesterday cannot be re-queried as valid today, which breaks assumptions. Policy:

  • *ppend-only*— entries are added, never removed (even if a reservation was a mistake, it stays)
  • *ever retroactive*— adding acme to the reservation dictionary does *ot*affect any user who already owns @acme@koder.dev prior to the addition. Existing allocations are grandfathered.
  • *eviewed by ≥2 members of trust & safety*for every addition — four-eyes principle
  • *ersion-stamped in KDB*— the dictionary has a version column so replay and audit are deterministic

Handle allocation writes at hyperscale

The allocation path uses the singlewriterperprefix pattern described in RFC012: 36 writers (one per az, one per 09) elected via KDB leader election. Per-prefix throughput targets:

  • *ustained:*1 000 allocationssecond per prefix × 36 prefixes = 36 000s cluster-wide
  • *urst:*10 000 allocations/second per prefix for up to 60 seconds

These numbers are well above expected real signup rates even at peak (no SaaS in history has sustained >100/s signup in steady state without going viral) but give us headroom for viral events and abuse spikes.

Remaining open questions

Items for empirical calibration or UX iteration during Phase 0/1.

  1. *eservation dictionary size and maintenance cadence*— the initial ≈5 000 entries need review. Quarterly update cadence is the starting point.
  2. *ate limit fine-tuning for the public handle registry*— if legitimate use patterns exceed 30minIP, we'll raise; if scrapers find workarounds, we'll lower
  3. *isplayname Unicode limits*— separate from the handle ASCII rule, the display_name field is UTF8; max length, allowed scripts, and confusable filtering in display names are still to be specified

Changelog

  • 20260411 — Initial draft

Source: ../home/koder/dev/koder/meta/docs/stack/policies/username-allocation.kmd