iam-anchor1, for iam-core 1.1, record wire version 2.
This optional sister profile specifies one concrete way to select authoritative IAM records. One publisher signs a sequence of complete snapshots. It provides deterministic selection from the same authenticated evidence, not network consensus, guaranteed delivery, or proof that an offline snapshot is the newest.
MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY have the meanings used in IAM.md. Implementing IAM core does not require implementing this profile.
The verifier receives the following immutable configuration through a trusted offline exchange. Its authenticity is an external prerequisite; a downloaded manifest cannot establish its own authority.
| Configuration field | Required value |
|---|---|
profile |
String "iam-anchor1". |
wire |
Integer 2. |
publisher |
One Ed25519 public key, 64 lowercase hex characters, valid under IAM 1.1’s key profile. |
epoch |
Integer in 0..9007199254740991, chosen when establishing this profile instance. |
tree |
The exact IAM tree identifier, 64 lowercase hex characters. |
context |
String "community" or "personal". |
genesis_id |
The exact id of the trusted sequence-zero manifest, 64 lowercase hex characters. |
The publisher need not be a graph member. Its authority selects snapshots; it does not grant additional authority to sign IAM structural records. The first manifest is this profile’s trust root, distinct from the community’s bootstrap and its ephemeral genesis signer.
epoch is a pinned instance label, not a clock or automatically selected
generation. A different epoch, publisher, tree, context, wire version, or
genesis id requires a new trusted configuration. Verifiers MUST NOT choose a
new configuration by the largest advertised epoch.
Other inputs are an unordered collection of manifest envelopes, IAM record
envelopes, and, for community context, the complete bootstrap registered under
known_trees[tree]. Transport and discovery are not specified. Input sources
need not be trusted.
An envelope has exactly three fields: manifest, id, and sig. The manifest
has exactly the eleven fields below. Unknown or missing fields are invalid.
This illustrates the shape; angle-bracket placeholders are not test vectors.
{
"manifest": {
"v": 1,
"wire": 2,
"publisher": "<publisher public key>",
"epoch": 0,
"tree": "<tree identifier>",
"context": "community",
"seq": 0,
"prev": "",
"bootstrap": "<same tree identifier>",
"records": [],
"reason": ""
},
"id": "<manifest id>",
"sig": "<canonical base64 signature>"
}
| Manifest field | Rule |
|---|---|
v |
Integer 1, the anchor format version. |
wire |
Integer 2, the IAM record format selected by this profile. |
publisher, epoch, tree, context |
Equal the pinned configuration values, including their JSON types. |
seq |
Integer in 0..9007199254740991. |
prev |
Empty string for seq = 0; otherwise the preceding manifest id. |
bootstrap |
Equal tree for community context; empty string for personal context. |
records |
Array of ordinary record ids, each 64 lowercase hex characters, strictly ascending in ASCII order; no duplicates. Empty is permitted. |
reason |
String of 0 to 512 printable ASCII characters, bytes 20..7e. |
All integer tokens MUST match 0|[1-9][0-9]* and satisfy their stated range.
Objects MUST reject duplicate member names after decoding JSON escapes. Field
values and types MUST be checked before canonicalization. JSON parsing and JCS
canonicalization follow IAM 1.1’s requirements; the envelope itself is not the
signed object. Input member order and insignificant JSON whitespace do not
select a different manifest.
Using UTF-8 JCS bytes of the complete manifest object:
id = lowercase_hex(SHA-256("IAM-ANCHOR1:id\0" || JCS(manifest)))
sig = base64(Ed25519.sign(publisher_secret,
"IAM-ANCHOR1:manifest\0" || JCS(manifest)))
Each \0 is one zero byte. id is 64 lowercase hex characters. sig is the
canonical padded base64 representation of 64 signature bytes, verified with
the strict Ed25519 profile specified in IAM 1.1. Signature bytes are not part
of the manifest id. Multiple valid signature envelopes for one manifest id
are duplicates, not equivocation; at least one valid envelope is sufficient.
First validate each manifest’s exact schema, pinned values, id, and signature. An invalid signature or malformed envelope supplies no fork evidence. Keep authenticated manifests by id and preserve the evidence establishing a frozen boundary; retaining every redundant conflicting descendant is not required.
The pinned genesis_id MUST authenticate with seq = 0 and prev = "".
Another sequence-zero manifest with a different id is outside this stream,
even if the same publisher signed it. It cannot replace the pinned trust root.
For subsequent manifests, follow prev back to that root. Every link MUST
have child.seq = parent.seq + 1. A gap or missing predecessor is pending,
not a valid shorter path. The sequence MUST NOT wrap at its maximum value.
Records, timestamps, and arrival order MUST NOT be used to order manifests.
An authenticated child whose list removes any record id from its parent’s
list MUST have a nonempty reason. This is a signed explanation, not a
machine-verifiable claim that the replacement is socially justified. An
append-only change or unchanged list MAY also carry an explanation. Changes
to reason are changes to the manifest and therefore change its id.
For every candidate snapshot:
known_trees[tree]. The bootstrap field references
this registry entry; it is not a replacement for verification. Personal
context instead uses the implicit root identified by tree.2 and the pinned (tree, context). Reject a
mismatched id, invalid envelope, or bootstrap record offered as an ordinary
record. Alternative invalid transport copies do not replace an already
verified envelope. Unlisted records cannot enter this snapshot.prev, chain scope, and all core preflight checks. Missing
records or dependencies leave the snapshot unavailable. Do not silently
reduce its record list to the available or successful subset.An empty ordinary record collection is valid: community bootstrap members or the implicit personal root still determine its initial state. Local clocks do not change canonical snapshot verification. Network admission freshness rules do not establish that a signed snapshot is current.
A complete prefix consists of manifests from sequence zero through sequence
n, with every link authenticated, every replacement explanation satisfying
section 3, and every snapshot in that prefix fully verified under section 4.
Without equivocation, select the highest sequence in a complete prefix. If no
such prefix exists, report that no anchor is available. Pending later data
does not change the selected state. Cache verified snapshots and identifiers
so older arrivals cannot roll a verifier back silently.
Two distinct authenticated manifests that name the same authenticated parent reachable from the pinned root and have the required successor sequence are proof of publisher equivocation. Check this using manifest evidence before waiting for either snapshot’s record payloads. An unavailable or invalid snapshot, including a missing replacement explanation, does not erase the publisher’s authenticated double signature.
On discovering such a fork, the stream MUST be frozen at the shared prefix ending with that parent. If several forks are known, use the earliest fork boundary reachable from the pinned root. No descendant beyond that boundary may remain active, including a branch activated before the evidence arrived. Select the highest complete prefix at or before the boundary; if unavailable, report no active anchor. Report the frozen condition and preserve the fork evidence. Never select a fork branch by hash, signature bytes, sequence depth, timestamp, or arrival order.
A verifier’s retained evidence is part of its input. Over the same evidence and complete data, this procedure yields the same result independent of arrival order. Peers with different evidence can temporarily report different states; this profile provides no consensus or availability guarantee. Later single- branch messages do not unfreeze a stream. Resuming requires an explicit new trusted profile instance through the same external trust process.
The publisher MAY issue a later, linked manifest whose record list shrinks. It MUST include the replacement reason required above, and the replacement snapshot MUST satisfy all core input requirements. For an actor’s record fork, this can select a branch while omitting the other branch and its dependent records. For LEAVE recovery it can select history excluding that departure and any records that cannot remain under core closure rules. Both are explicit changes of authoritative history, not automatic graph repairs or new IAM operations. Previously signed manifests remain evidence of earlier selections.
Reanchoring does not provide permanent eviction of a compromised axiomatic community member: its membership originates in the unchanged bootstrap. The community must migrate to a new tree/bootstrap to remove that axiom, with a new trusted anchoring configuration. An anchor publisher also cannot repair a compromised identity key or make earlier signatures unforgeable.
Publisher-key compromise or a frozen publisher stream requires external re-establishment of trust. In case of key compromise, pin a new publisher key and a new profile instance. A successor signed only by the compromised key MUST NOT automatically replace the trusted configuration.
Hosts MUST bound manifest and record queues, payload sizes, retained pending dependencies, and processing work, with an explicit retry/eviction policy. Resource exhaustion means unavailable data, not permission to activate a partial snapshot. Publishers SHOULD distribute the manifests, bootstrap, and all referenced records together and preserve earlier snapshots for audit and recovery. This profile defines their verification, not a network transport.
Offline verification authenticates a publisher’s historical selection. It does not prove that no later snapshot or conflicting signature exists. Operational decisions requiring freshness need an additional distribution and freshness policy.