@zanii/succession
v0.1.0
Published
Agent lifecycle and key rotation with signed continuity - the owner attests 'B succeeds A', so reputation and CV history transfer verifiably instead of dying with a key. A compromise succession REQUIRES the compromise timestamp, bracketing the trusted win
Readme
@zanii/succession
Agent lifecycle: key rotation with signed continuity. An agent's did:key IS its key, so rotating a compromised key normally kills its reputation, CV history, and counterparty trust. Succession fixes it: the owner — the same root authority whose delegation empowered the old key — signs "agent B is the successor of agent A", and verifiers follow the lineage instead of starting from zero.
npm install @zanii/succession @zanii/core @zanii/a2a-directoryimport { buildSuccessionBody, signSuccession, assembleSuccession, verifySuccession, verifyLineage, combinedSummary } from '@zanii/succession';
// planned rotation — old key still safe, so it countersigns (the strong form)
const body = buildSuccessionBody({ predecessor: oldAgent.did, successor: newAgent.did, owner: owner.did, reason: 'rotation', ts: now });
const s = assembleSuccession(body, [
signSuccession(body, owner.did, ownerKey), // REQUIRED — the trust anchor
signSuccession(body, oldAgent.did, oldAgentKey), // optional — sets `cosigned`
]);
verifySuccession(s); // { ok, reasons, cosigned }
// after a compromise, compromised_at is REQUIRED — it brackets the trusted window
buildSuccessionBody({ ..., reason: 'compromise', compromisedAt: '2026-07-20T00:00:00Z' });
// walk a chain A→B→C and aggregate reputation across it (conservatively)
verifyLineage(links, currentDid); // { ok, lineage: [oldest…newest] }
combinedSummary(links, trusts, currentDid); // sums + explicit caveatsPython: from zanii.succession import build_succession_body, verify_lineage, combined_summary, ...
— byte-identical JCS objects and hashes.
The rules that keep it honest
- No owner, no succession — anyone can claim to succeed anyone; only the owner's signature makes it real. After a compromise the predecessor's signature is deliberately NOT required (the attacker holds that key).
compromiserequirescompromised_at— history transfers, but receipts after that instant under the old key may be the attacker's;combinedSummarysays so in itscaveatsinstead of silently inheriting them. Pair with a revocation of the old delegation: succession records continuity, revocation kills the old authority.- One lineage, one owner — a lineage spanning owners is refused; an ownership transfer is a sale, not a succession, and conflating them would launder history.
- Conservative aggregation — combined receipt counts are an upper bound and say so; counterparties are deliberately not summed (overlap is unknowable).
The limit, stated up front
Succession proves continuity of authority — the owner vouches that B carries A's
mandate. It does NOT prove B runs the same code or behaves like A (@zanii/attest is
for which-code-ran). And it is the owner's attestation: a lying owner's lie is signed
and permanent — attributable, not impossible.
