> ## Documentation Index
> Fetch the complete documentation index at: https://docs.afauth.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> What's new in AFAuth across the spec, SDKs, and CLI.

<Update label="June 4, 2026" description="Week of May 30 – June 5">
  ## Changes

  **Unclaimed accounts never expire by default**

  `unclaimed_ttl_seconds` is now optional and **off by default**: an agent operates its account indefinitely whether or not a human ever claims it, and the `EXPIRED` state is opt-in — reached only when a service deliberately advertises a TTL to garbage-collect abandoned accounts or to meet a data-retention mandate. The spec (§4.4, §6.1, §7.3, Appendix A) reframes expiry as opt-in and warns against setting a TTL on the reflex that "inactive accounts should be reaped" — an AFAuth account is bound to a key its agent holds, not to a human who may have wandered off. In the TypeScript SDK, `sweepExpiredAccounts` treats `unclaimedTtlSeconds` as optional and is a no-op when omitted; the published `.well-known` schema raises the TTL floor to 3600s for services that do opt in. See the [account lifecycle](/concepts/ceremony) and the [`.well-known/afauth` reference](/reference/well-known-afauth).
</Update>

<Update label="June 3, 2026" description="Week of May 30 – June 5">
  ## New features

  **Multi-agent accounts — one account, many devices**

  `attested_only` (§9.2) proves a signup carries *some* valid attestation, but a human runs more than one agent — a PC and a phone are two `did:key`s. The SDK now models that directly: an account is keyed on an opaque `account_id` (no longer the agent DID) and holds one or more agent credentials. Because every trust attestation for the same human at one service carries the same pseudonym `sub_h` (§10.4), a human's agents are **grouped onto one account** by `(iss, sub_h)` (§10.4.4) — like signing into one account from several devices. The second device *attaches*; it is not rejected. Bucket your free-tier quota / rate limits / bans on the account and a human's fleet shares one bucket. Agents with no `sub_h` get singleton accounts; key rotation now keeps `account_id` stable; introspection returns `account_id` + `agent_did`. `D1AccountStore` (`@afauthhq/worker`) makes the grouping atomic via a `(iss, sub_h)` UNIQUE index. See the [attestation concept](/concepts/attestation) and [service SDK overview](/sdk/typescript/server/overview).
</Update>

<Update label="May 29, 2026" description="Week of May 23 – May 29">
  ## New features

  **SweepableAccountStore for TTL-driven account expiry**

  Service operators implementing the TypeScript SDK can now use a built-in helper to expire unclaimed and invited accounts that have exceeded their `unclaimed_ttl_seconds`. The new `SweepableAccountStore` interface and `sweepExpiredAccounts` helper move the `UNCLAIMED → EXPIRED` and `INVITED → EXPIRED` transitions out of bespoke service code, closing a v0.1 conformance gap for the §6.1 `EXPIRED` state. The bundled `MemoryAccountStore` and `D1AccountStore` already implement the new interface. See the [account lifecycle](/concepts/ceremony) and [revoke an account](/guides/revoke-an-account) guides.

  **Trust-attestation conformance vectors**

  The optional §10 trust-attestation surface now has a dedicated conformance corpus, documented as §C.7 in the spec. Implementations that consume trust attestations can verify themselves against the same vectors used by the reference implementations. Core §C.1–§C.6 conformance is unchanged. See the [conformance reference](/spec/conformance) and [trust attestor concept](/concepts/trust-attestor).

  **v0.2 implementation milestone published**

  The wire protocol stays at `afauth_version: 0.1`, but the reference implementations have shipped meaningful surface area beyond the original v0.1 scope. The new v0.2 implementation milestone documents what's included: the service [directory](/concepts/service-directory), the [`afauth-trust`](https://trust.afauth.org) service, the SDK trust client and `defineService` API, and CLI v0.4.0.

  ## Updates

  **Worker package: D1 + Durable Object nonce stores**

  The `@afauthhq/worker` package's `DurableObjectNonceStore` and `createNonceDurableObject` exports are now documented. Use these to back the §4.3 replay-protection cache with a Durable Object instead of a single-region store when deploying on Cloudflare. See the [worker SDK overview](/sdk/typescript/worker/overview) and the [Cloudflare Worker deployment guide](/guides/deploy-cloudflare-worker).

  **`Account.createdAt` exposed via introspection**

  `Account` now carries a `createdAt` timestamp, surfaced by the §6.5 introspection endpoint. The response body matches the example in the spec, so introspection clients no longer need to special-case a missing field.

  ## Bug fixes

  **Binary request bodies now verify correctly (`@afauthhq/server@0.1.1`, `@afauthhq/agent@0.1.1`, `@afauthhq/worker@0.1.1`)**

  Verification of requests with non-UTF-8 bodies — multipart uploads, ZIPs, protobuf — was failing with `401 invalid_signature` against any RFC-9421-conformant agent. Servers read bodies via `arrayBuffer()` now, and `signRequest` / `Verifier.verify` accept `Uint8Array` bodies directly. String-body callers are unaffected. Update with `npm update @afauthhq/server @afauthhq/agent @afauthhq/worker`. See [verify a request](/guides/verify-a-request).

  **CLI v0.4.0: correct trust binding path in `--help`**

  `afauth trust link --help` previously printed `~/.config/afauth/trust.json` for the binding token, but the binding is written to `~/.afauth/trust.json`. The help text now matches behaviour, and `afauth --version` on source builds reports `0.4.0` instead of the stale `0.3.1`. See the [trust command reference](/cli/commands/trust).
</Update>
