iam

iam-core 1.1 — record wire version 2, identity KDF v1.

Before using IAM: read the security limits, threat model and review provenance. The specification revisions, project reviews, reference code and vectors were developed with Codex agents. These materials do not establish an independent security audit.

IAM is an open protocol for reproducible identity keys and signed ACCEPT and REVOKE records in personal and community membership graphs, with LEAVE for community departure. It defines how these records are expressed, signed, and evaluated. A canonical identity is an Ed25519 public key; graph membership is a state derived from selected records. Runtime policies govern which records are authoritative and how membership is used for operational permissions and access.


Why Identity Must Be Boring, Deterministic, and Offline

Modern identity systems confuse access with identity. Access is a runtime concern: login flows, federation, availability. Identity is a statement about existence and continuity. Archived identity records should remain verifiable without depending on the continued availability of a service or institution. Whether a key has authority to act now depends on the records and policies used by the verifier.

Boring because stable. The moment identity becomes dynamic or adaptive, it becomes policy or product. True identity does not negotiate; it records. Boring systems last: cryptographic hashes, append-only logs, DNS. Identity belongs to this class.

Deterministic because archived evidence should have a repeatable interpretation. Given the same known_trees registry, the same anchored_set, and the same requested tree and context, IAM requires the same evaluated state under the same protocol rules. Runtime policies choose the authoritative records, so different selections can yield different states. Deterministic evaluation makes that interpretation reproducible; agreement on which records to use remains a runtime concern.

Offline because identity must outlive systems. Networks fail. Organizations dissolve. Software rots. IAM’s evaluation uses archived records and a community bootstrap or an implicit personal root without contacting an external service. This establishes a state for those inputs; learning of later revocations or a newer authoritative selection requires runtime distribution. History does not ask permission to be verified.

Most identity architectures solve the wrong problem: how to authenticate users today, federate trust between institutions, or monetize access. Valid problems, but not identity. Identity is the substrate beneath all of them. It must remain valid when none of them exist.


Specification

Version 1.1 uses v = 2 records and IAM2:* hash/signature domains. Identity KDF v1 remains unchanged, so existing derived keys can be retained. Community bootstrap records and tree identifiers migrate explicitly; old records are not relabeled as new ones.

The anchoring profile defines signed snapshots and publisher-fork handling. It authenticates selected history without claiming network consensus or proof of the newest state. The repository README includes commands to run the Python tests and check the generated vectors.

Below is the complete iam-core 1.1 specification:

IAM

m=894715. iam-core 1.1. Published 2026-09-14. Wire version 2.

Identity and trust graphs. IAM defines reproducible identity keys, signed graph operations and deterministic evaluation. JAM is the name used here for a host runtime built on IAM; it supplies transport, storage, application permissions and operational policy.

Before deployment, read the security limits, threat model and review provenance. The published code and vectors are project cross-checks; they are not evidence of an independent security audit.

The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY have the meanings of RFC 2119 and RFC 8174.

Scope and version identity

iam-core 1.1 defines one validation profile, identified by integer v=2 and bound into records, signatures and community tree ids by the IAM2:* domains below. Implementations MUST NOT reinterpret wire-v1 records under these rules or retry failed wire-v2 signatures under a legacy profile.

The document version, record version and identity-derivation namespace are distinct. The identity KDF retains iam:v1:name: and iam/v1/root-ed25519, preserving keys derived with the specified modern KDF. Wire-v2 records, signatures and community tree ids are new. Migration requires new signed records and a new community bootstrap; existing wire-v1 history remains under iam-core 1.0. See CHANGELOG.md.

The trust graph is a directed acyclic graph (DAG), with multiple parents permitted. The core does not define messaging, encryption, application permissions, key rotation, storage, transport, distributed consensus or selection of authoritative history. ANCHORING.md specifies one optional operational selection profile.

Identity and derivation

An identity is its Ed25519 public key. A name is a fixed derivation input, a nick is a mutable runtime display label, and a seal is a four-word visual fingerprint. Names and seals MUST NOT be used as unique identity identifiers.

A name MUST fully match [a-z0-9][a-z0-9._-]{0,31}. An incantation MUST contain 12 through 2^32-1 bytes, all printable ASCII 0x20..0x7e. Validate the entire input, not a prefix before a trailing newline. No normalization, case folding, trimming, quote substitution or other transformation is permitted. Invalid inputs MUST be rejected. Implementations SHOULD allow inspection of the exact entered bytes. Resource refusal MUST be explicit; hosts MUST NOT silently truncate inputs or change derivation parameters.

Two keys may have the same name. Neither name nor nick appears in a core record; runtime metadata outside the envelope is not authenticated by the IAM record signature. Runtimes displaying equal names or seals SHOULD show distinguishing public-key suffixes, extending them to avoid ambiguity in the displayed set. The full key remains the identity.

All strings below are exact ASCII bytes:

name_bytes  = ASCII(name)
inc_bytes   = ASCII(incantation)
salt        = SHA-256("iam:v1:name:" || name_bytes)[0:16]
master_seed = Argon2id(password=inc_bytes, salt=salt,
                      version=0x13, memory=65536 KiB,
                      iterations=3, parallelism=1, tag_length=32,
                      secret=empty, associated_data=empty)
root_seed   = HKDF-SHA256(ikm=master_seed, salt=empty,
                        info="iam/v1/root-ed25519", length=32)
root_key    = Ed25519.keypair_from_seed(root_seed)

Argon2id is v1.3 from RFC 9106. Every HKDF use MUST perform Extract and Expand from RFC 5869. root_seed is the 32-byte Ed25519 seed, not an expanded scalar. Identical valid inputs MUST produce the same root key.

Argon2 memory is 64 MiB total, divided among lanes: p=4 would not require four 64 MiB buffers. IAM retains p=1 without claiming a general security ranking from parallelism alone. Changing the derivation parameters or namespace creates different identities and requires an explicit identity-space migration.

Other purpose seeds MAY use HKDF-SHA256(master_seed, empty, "iam/v1/" || purpose_name, 32). Distinct purposes MUST have distinct names; root-ed25519 is reserved. An untrusted purpose request MUST NOT expose the root seed.

Security and privacy boundary

An attacker who knows or guesses the name can test incantations offline against the public key, without network rate limits. Name-derived salts are shared by equal names. Length alone is not entropy. Users SHOULD choose unpredictable incantations; implementations SHOULD warn about weak phrases.

The same key is linkable across accessible graphs. This does not itself identify a person or prove consent to acceptance. People can create separate identities. IAM does not require public distribution of every graph. LEAVE changes graph state; it does not erase records or replicated copies. Hosts must assess their own disclosure, retention, access and applicable personal-data obligations.

Encoding and cryptographic profile

Keys and SHA-256 ids are 32 bytes encoded as exactly 64 lowercase hex characters, without prefixes or separators. Signatures are 64 bytes encoded as standard RFC 4648 base64: exactly 88 characters ending in ==, with no ignored characters or whitespace. Require base64_encode(base64_decode(sig)) == sig, including zero pad bits. Base64url, missing padding and uppercase hex are invalid.

Domain strings are exact ASCII bytes; \0 denotes one byte 00, not two printable characters. No further terminator is appended.

Ed25519 and valid public keys

Use pure Ed25519 from RFC 8032 §5.1, not Ed25519ph or Ed25519ctx. No extra application prehash or context is added. Let B be the standard base point, L its prime order, and O the identity point.

  1. Canonically decode public key Aenc and signature point Renc using RFC 8032. Reject invalid points, y >= p, and a set sign bit when x=0.
  2. Require [L]A = O and A != O.
  3. Require [L]R = O. R=O is permitted.
  4. Interpret the last 32 signature bytes as little-endian integer S; require 0 <= S < L.
  5. For exact message bytes M, compute k = LE_integer(SHA-512(Renc || Aenc || M)) mod L and require [S]B = R + [k]A.

These public-key rules apply to actor, target, genesis, bootstrap targets and a personal implicit root even with no records. A community tree hash is not a curve point. A library’s default or “strict” verifier is conforming only if its accepted set matches these rules, including valid R=O signatures.

Equivalent algorithms and batch verification MUST produce identical accept/reject results. Subgroup checks add work; no fixed cost multiplier is claimed. Hosts MAY cache valid-key checks by exact canonical key bytes and this wire/profile version, using bounded caches. A cached key does not remove the need to verify each signature’s message binding.

Seal

public_key_bytes = hex_decode(public_key_hex)   // exactly 32 bytes
pub_hash         = SHA-512(public_key_bytes)
seal[i]          = WORDLIST[pub_hash[i]]  for i in 0..3

Four words carry 32 bits. A random collision has roughly 50% probability at about 77,000 uniformly distributed fingerprints. Matching one chosen victim’s fingerprint costs an expected 2^32 independent candidate keys in the generic model; an attack need not pay IAM KDF cost. No GPU timing follows from that bit count. The seal MUST NOT be the sole authenticator when binding an unknown key to a person.

The canonical wordlist and indexes are fixed below. The four words are separate visual tokens. IAM does not define concatenated or voice-only encoding. Longer fingerprints require separately specified runtime displays, not silent replacement of the canonical seal.

Record and envelope schemas

ACCEPT adds a directed actor-to-target edge. REVOKE removes that actor’s edge. Community LEAVE removes the actor’s incident edges and axiomatic status, permanently within that evaluation. All operations are unilateral and signed only by the actor: ACCEPT does not prove target consent, inactivity or inability to sign later.

The stored envelope has exactly record, id, and sig. The inner record has exactly nine fields:

Field JSON type and constraint
v Number, integer 2
kind String ACCEPT, REVOKE, or LEAVE
tree String of 64 lowercase hex characters
context String personal or community
m Number, integer 0..9007199254740991
actor, target Strings encoding valid public keys under the profile above
prev Empty string or 64-character lowercase hex id
body Empty object {}

Missing or additional fields are invalid. id and sig must be strings. Runtime metadata MAY use a separate outer wrapper; it MUST NOT enter the core envelope, record or body. Types MUST NOT be coerced.

Incoming JSON tokens for v and m MUST fully match 0|[1-9][0-9]* and pass bounds checking before rounding. 2.0, 2e0, -0 and unsafe integers are invalid. This is a wire-v2 restriction, not a retrospective rule for 1.0.

Input MUST be UTF-8 I-JSON. Duplicate object names MUST be rejected after escape decoding, before a parser discards duplicates. String values are checked after escape decoding. Whitespace, property order and equivalent string escapes may differ on input. Hashing and signing use UTF-8 JCS of the complete inner record. Unknown fields MUST NOT be discarded before verification.

Basic structure also requires: actor != target for ACCEPT; target == actor for LEAVE; tree == actor for personal records; no personal LEAVE. A personal tree must be a valid public key. Self-REVOKE is rejected semantically. Prev is per (tree, context, actor).

Record identity and signatures

id  = lowercase_hex(SHA-256("IAM2:id\0" || JCS(record)))
sig = base64(Ed25519.sign(actor_root_key,
                         "IAM2:record\0" || JCS(record)))

Signature bytes are not record identity. Different valid signatures over the same canonical record have the same id and count as one logical record, not a fork. Validate each envelope before authenticating that id. An invalid first copy MUST NOT suppress a later valid copy; invalid variants do not invalidate valid variants.

A store MAY retain any verified variant or all variants. Graph state MUST NOT depend on that choice. A canonical export choosing one variant SHOULD choose the lexicographically smallest decoded valid signature it holds; this local export rule is not consensus or logical identity. Later variants can change export bytes without changing graph state.

Never index a claimed id until it matches the recomputed hash. If one matching id identifies different canonical contents, ABORT.

Graphs and bootstrap

Personal tree is the owner’s root public key, which is axiomatically present. Only that key may change the personal graph. A different accepted device key cannot change it. Device keypairs are generated locally; their private keys MUST NOT be transmitted. Devices sign runtime traffic, not structural operations on the owner’s behalf.

Structural actors MUST use their root signing keys. Verification establishes a key’s control and graph role, not its KDF provenance or its use elsewhere. A community record cannot prove global device/root separation.

A community tree is identified by its verified bootstrap hash. Its bootstrap targets are axiomatic; other members need an active path from an axiomatic member. Axiomatic members may have ordinary incoming edges; REVOKE of those edges does not remove axiomatic status.

Genesis creation and descriptor schema

Generate 32 bytes from a cryptographically secure random source, not an incantation, and derive the genesis Ed25519 seed with HKDF-SHA256(seed, empty, "iam/v1/root-ed25519", 32). Select a nonempty ordered list of distinct valid target keys, none equal to genesis, and one non-negative safe-integer timestamp m_b.

A bootstrap descriptor has its own schema of exactly six fields: v, kind, context, m, actor, target. These have the same types, number-token and key constraints as record fields, with v=2, kind="ACCEPT", context="community", m=m_b, the genesis actor and one selected target. Descriptors are intermediate hash inputs, not signed records or envelopes. They have no tree, prev, body, id or sig.

tree_id = lowercase_hex(SHA-256("IAM2:tree\0" || JCS([desc_1, ..., desc_n])))
record_i = desc_i + {"tree":tree_id, "prev":"", "body":{}}

Compute ids and signatures for the full records using the standard IAM2 domains. Publish their ordered envelope list. The creator MUST erase the random seed, derived seed and private key immediately after signing. Remote verification cannot prove erasure. Fixed seeds in public test vectors are fixtures, not live bootstrap instructions.

Bootstrap validity

Verify the complete ordered batch atomically:

  1. It is a nonempty list of complete, basic-structurally valid wire-v2 community ACCEPT envelopes, with matching ids and valid signatures.
  2. All records share one genesis actor and one m.
  3. All prev values are empty and all bodies are {}.
  4. Targets are pairwise distinct and none equals genesis.
  5. All tree fields equal the requested id, recomputed from the ordered six-field descriptors with the formula above.

Every condition is mandatory; hash and signature checking alone is insufficient. Bootstrap is exempt from ordinary actor-membership checks and fork detection. It establishes its targets directly as axiomatic members, with no genesis-to-target edges. Order is part of tree identity. The hash is constant-sized; hashing and verifying the list require work proportional to its contents.

The community’s genesis key is reserved. Ordinary records signed by it have invalid chains and MUST NOT apply. An ordinary ACCEPT targeting it is semantically invalid. This restriction is specific to that community, not a global role assigned to those key bytes. Bootstrap lives exclusively in known_trees, never in an anchored set.

Observation, admission and anchoring

Observation may include malformed objects, duplicate envelopes, mixed graphs and arbitrary arrival order. It has no authority.

Admission is local storage policy. Admit bootstrap only after all bootstrap checks. An ordinary record can be admitted only after basic structure, id and signature verification, recognition of its community tree if applicable, m <= now + 5, and availability of a same-chain predecessor when prev is nonempty. A verified duplicate id adds no logical record. An invalid first signature MUST NOT count as successful replay protection.

Unknown trees, unknown predecessors and future-dated records MAY be quarantined for retry. Every host MUST bound total quarantine bytes, record count and retention time, and define eviction and retry policies. At capacity it may discard or decline new records; it MUST NOT silently promote them. The host must document its limits and resource-refusal reasons. Eviction is local policy, not a mutation of the canonical result for a complete anchor. Prevalidation queues and verification caches also require resource bounds. Unlimited retention is never required.

An anchored set is an externally selected set of admitted logical records for exactly one (tree, context). Multi-graph transport containers must be separated before evaluation. The core does not silently filter a mixed-scope anchor. Only the requested community’s bootstrap is needed; unrelated known_trees entries are irrelevant.

An anchor MUST be closed under prev, exclude bootstrap and preserve record identity. An anchor received from a trusted peer still requires verification; peer trust does not authenticate an unchecked signature. The defensive evaluator below also defines rejection and errors for malformed inputs.

IAM does not choose an authoritative anchor or require anchors to grow monotonically. Different anchors can produce different states. Replacing an anchor may omit a fork branch and its descendants without erasing observation history. ANCHORING.md defines one optional complete policy; it does not claim distributed consensus.

Signer obligations

Before signing, a runtime MUST obtain and validate the selected anchor and current head of the actor’s chain. It MUST use that head as prev (empty only for the first action), choose m >= head.m, and prevent concurrent signing from the same head. Reading a head without coordinating writers is insufficient. If head or coordination state is uncertain, refuse to sign until resolved.

Pending signed records MUST remain part of local head coordination until explicitly reconciled. Signing another child merely because the first has not propagated creates a fork. Recovery using a replacement anchor must explicitly reconcile excluded branches before new signing.

Forks and backwards-time links can invalidate a chain suffix, leaving its earlier valid prefix intact. Recovery selects a different authoritative history; verification never repairs history by choosing a fork winner or skipping an authenticated chain error. These obligations protect honest signers; verification cannot prove clock accuracy, erasure or writer coordination.

Canonical evaluation

evaluate(known_trees, anchored_set, tree, context) -> graph state

This is a pure wire-v2 function. The same complete inputs MUST yield the same state regardless of clocks, receipt order, transport or caches. Wire-v1 evaluation is a different function. State comprises active edges (parent, child), active axiomatic keys and departed keys. Membership is forward reachability from active axiomatic keys over active edges.

Phase A: context, content and authentication

For community context, verify the requested bootstrap and initialize its targets as axiomatic; missing or invalid bootstrap means ABORT. For personal context, require a valid root key and initialize it as axiomatic. Unknown requested contexts are errors. A decoded record carrying an integer wire version other than 2 is an unsupported-version input error: ABORT, never silently convert a legacy anchor into an empty wire-v2 history.

For each supplied envelope:

  1. Validate exact envelope/record shape, types, basic structure, public keys, canonical signature text encoding and matching content id. Individually reject failures without trusting or indexing their claimed ids. Malformed base64 fails here; a canonically encoded signature that fails the Ed25519 equation remains indexable but unauthenticated.
  2. Every remaining record must match the requested tree/context; otherwise ABORT. If its id is in the requested bootstrap, ABORT.
  3. Index canonical content by id. ABORT on conflicting canonical content under one matching id.
  4. Verify every signature copy under the strict profile. Mark an id authenticated when at least one copy verifies. An invalid copy never unmarks a valid one. Invalid signature encodings or values are not fork evidence.

Every indexed record’s nonempty prev must resolve to an indexed predecessor with the same (tree, context, actor), otherwise ABORT. A correctly identified record without a valid signature can establish predecessor existence, not chain validity; its descendants cannot apply. A malformed record or false id cannot establish existence.

An indexed foreign-scope record is an error in this anchor; unrelated records in other containers need no bootstrap lookup. If dependency traversal cannot reach every indexed record because of a cycle, ABORT rather than returning partial state.

Phase B: authenticated forks

Group authenticated indexed records by (tree, context, actor, prev). A group with two or more distinct ids marks all its records as fork children. Multiple signatures for one id count once. Collect evidence before application, independently of traversal order.

A candidate needs its own valid basic structure, id, signature and same-chain predecessor reference. It need not have a semantically successful operation, monotonic time or authenticated ancestor. In particular, an authenticated backwards-time sibling remains double-signature evidence. A forged signature does not.

Phase C: chain validity and application

Traverse indexed records topologically by prev. Empty-prev records are initially ready. Processing a record makes its children ready whether it applies or fails. Always select the ready record with smallest (m, id), with lexicographic lowercase-hex id order.

chain_valid := empty map
while ready is not empty:
    r := remove smallest (m, id) from ready
    enqueue children of r
    chain_valid[r.id] := false
    if r.id is not authenticated: continue
    if r.id is a fork child: continue
    if r.prev != "" and not chain_valid[r.prev]: continue
    if r.prev != "" and r.m < records[r.prev].m: continue
    if community and r.actor == genesis_public_key: continue
    chain_valid[r.id] := true
    if not semantically_valid(r, state): continue
    apply r to state
if some indexed record was not processed: ABORT
return state

Structural, signature, fork, predecessor and monotonicity errors block descendant application. Semantic operation failure leaves chain validity true. m=10 -> m=5 -> m=6 cannot apply its last record through the rejected middle link; REVOKE of a nonexistent edge can still be followed by a valid ACCEPT.

Semantic rules

Every applied operation requires a currently present actor. In addition:

Operation Validity Effect
ACCEPT Neither endpoint departed; target is not this community’s genesis; no active actor-to-target edge exists; adding it creates no cycle. Basic structure already excludes self-ACCEPT. Add that edge.
REVOKE Actor differs from target; active actor-to-target edge exists. Remove only that edge.
LEAVE Community context, target equals actor. Remove all incident edges, remove any axiomatic status, and add actor to departed set.

Cycle prevention considers all active edges, including currently unreachable ones. A remaining alternate path preserves membership after one parent’s REVOKE. Axiomatic membership persists independently until LEAVE. No key that has departed, including a former axiomatic key, can be re-accepted within the same evaluation.

REVOKE does not delete outgoing edges of a member that loses reachability. After A ACCEPTs B, B ACCEPTs C and A REVOKEs B, B-to-C remains active but may be unreachable. Re-ACCEPT of B can restore both B and C. LEAVE instead explicitly removes all incident edges.

Time and cross-actor causality

m = floor(unix_seconds / 60) - 28928160

Epoch is 2025-01-01 00:00 UTC; ticks are minutes. A signer-supplied m is not objective creation-time evidence. Admission applies its local upper bound; canonical evaluation has no clock. Bootstrap validation is timeless and does not authenticate its claimed creation time.

Prev expresses causality only within one actor’s chain. If A ACCEPTs B and B ACCEPTs C in the same minute, B’s record may sort first and fail membership. Cross-actor dependent actions SHOULD use m strictly greater than their dependencies. This does not authenticate time or prevent every cross-actor backdating attack.

Ordering never chooses a winning fork branch, but it affects semantic validity and final membership. Blocking a backwards link from resetting its actor’s chain time fixes that specific loophole, not all timestamp manipulation.

Compromise and recovery

Root-key rotation preserving identity is not provided. Recovery creates a different identity, rebuilds intended acceptance paths and removes every remaining authoritative path to the compromised key where possible. One parent’s REVOKE removes one edge. A valid community LEAVE removes the actor, but chain failure may prevent its application in the selected anchor.

This is an identity-model invariant, not a deferred rotation operation: the identity is the root public key, and changing that key creates a new identity. Existing edges and historical signatures retain their original key endpoints. A runtime may describe a successor identity through separate policy, but that description does not transfer IAM membership. Replacing accepted device keys through personal ACCEPT and REVOKE does not change the owner’s root identity.

Other members cannot remove a compromised bootstrap root from its axiomatic set. If it cannot or will not issue an applicable LEAVE, create a new community bootstrap excluding it. Selecting only harmless records does not remove its old axiomatic status. Multiple roots preserve alternate paths after loss or departure; they do not constrain one compromised root’s independent authority. There is no quorum primitive.

Fork recovery or return after LEAVE can select another authoritative anchor omitting relevant records and required dependents. This changes authoritative history; it is not a RETURN operation or erasure. Hosts must communicate the anchor being evaluated. If every usable bootstrap copy is lost, the community cannot be evaluated; preserve bootstrap as an archival foundation.

Device signatures carry authority only under the verifier’s evaluated personal graph and the runtime’s message rules. REVOKE affects a verifier only after admission, anchoring and successful evaluation. An offline old anchor cannot prove that no newer revocation exists.

Conformance and limits

conformance/vectors.json contains positive and negative conformance examples for wire validation, derivation, bootstrap and graph states. Their expected outcomes are part of this version’s conformance examples, not permission to ignore rules for unlisted inputs. A contradiction between normative text and vectors is a specification defect to resolve, not a license for silent reinterpretation.

Vector fields such as applied and rejected describe record dispositions. Implementations need not expose the same API or diagnostic strings, but must agree on which operations apply, which records fail and the resulting graph state or required input error.

The Python verifier and graph evaluator are inspectable offline public-input reference code, not constant-time private-key tools or production runtimes. Node-generated signed vectors are cross-checked using independent Python arithmetic. Python does not implement Argon2; the Node derivation provider is also checked against RFC 9106’s vector. Repository test instructions state the coverage.

These artifacts were produced in the same project workflow with Codex agents. Independent arithmetic is not independent authorship. Passing a finite vector suite does not prove specification completeness; an outside implementation from the specification is requested as additional evidence.

A deployment must also satisfy signer and bounded-resource obligations. Storage, discovery, replication and authoritative selection remain runtime concerns. Determinism does not imply unique humans, target consent, immutable anchors or distributed convergence.

Wordlist

The canonical wordlist contains exactly 256 words indexed 0 through 255 in the following order. The words and indexes MUST remain exact; changing a word changes the seal space.

amber      anchor     apex       arch       ash        aspen      atlas      azure
bark       basin      beacon     beam       berry      birch      bison      blade
bloom      bolt       bone       boulder    brass      breeze     briar      bridge
brook      calm       canyon     cape       cedar      chain      chalk      cipher
clay       cliff      clock      cloud      coal       coast      cobalt     comet
coral      cove       crag       crane      creek      crest      cross      crown
crystal    curve      cypress    dagger     dale       dance      dawn       delta
depth      dew        dial       dome       dove       draft      drake      dream
drift      drum       dune       dusk       eagle      earth      east       echo
edge       elder      elm        ember      epoch      fable      falcon     fawn
feather    fern       field      finch      fire       fjord      flame      flare
flax       fleet      flint      flora      fog        forge      fossil     fox
frond      frost      gable      gale       garnet     gate       gem        ghost
glade      glass      glen       globe      gold       grain      granite    grove
guild      gull       gust       halo       harbor     hawk       hazel      heart
heath      helm       heron      hill       hive       hollow     honey      horizon
horn       hound      hush       ice        inlet      iron       isle       ivory
jade       jasper     jet        jewel      jungle     juniper    kelp       kindle
knoll      lake       lance      lark       latch      laurel     leaf       ledge
light      lilac      linden     loam       lodge      lotus      lunar      lynx
maple      marble     marsh      meadow     mesa       mint       mist       moon
moss       muse       myth       north      nova       oak        oasis      oat
onyx       orbit      orchid     otter      palm       path       peak       pearl
pine       plume      pond       prairie    prism      pulse      quartz     quill
quiver     rain       raven      reed       reef       ridge      river      robin
rock       root       rose       rune       rust       saber      sage       sand
shard      shell      shore      silk       silver     slate      smoke      snow
south      spark      spire      spring     star       steel      stone      storm
sun        surge      swift      thicket    thorn      tide       timber     tor
torch      trail      vale       vault      vine       violet     vista      void
wake       wave       west       wheat      wild       willow     wind       winter
wolf       wood       wren       yarn       yew        zenith     zephyr     zero

iam-core 1.1 — wire version 2 — identity derivation namespace v1.