NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #2533 most downloaded on pub.dev
Package that implements common logic for onboarding/authenticating an atsign to a secondary server
Last release today
07 Oct 2026
Release timing varies
gaps range from 9 days to 5 months
Nearly every release is documented
notes for 26 of 26 stable releases
2 versions withdrawn
withdrawn after publishing
3 years old
33 releases · first in 2023
One column per quarter.
fix: waiting for an enrollment's approval ends at once, with the atServer's reason, when the enrollment has expired or the atServer has no record of i
AT0028), instead of after the whole retry budget.fix: a keyfile lock left behind by a process that stopped mid-write is released within 5 seconds, instead of blocking every other writer for 30.
…reach a keyfile's flat legacy fields without the deprecated members.
Logging in and managing enrollments moved to at_client (Atsign.open,
Atsign.enroll and client.enrollments); this release removes what they
replace.
AtAuth and its request and response objects (AtAuthRequest,
AtAuthResponse, AuthRequest, AuthResponse, AtOnboardingRequest and
AtOnboardingResponse) are removed. Activate with activateAtSign(...);
log in with at_client's Atsign.open, or check credentials with
Atsign.authenticatesAs. RetryOptions is still exported.AtEnrollment keeps submit, approve and waitForApproval.
deny, revoke, list, generateOtp and setSpp, with Otp and
defaultOtpExpiry, are at_client's client.enrollments; update and
EnrollmentUpdateRequest are at_client's EnrollmentUpdater.activateAtSign requires atLookUp and
AtEnrollment.waitForApproval requires atLookup, each an
AtLookupMuxable it neither builds nor closes.AtEnrollment.approve requires approverKeys, an
ApproverKeyMaterial; approverChops is removed, and approve no longer
writes the APKAM symmetric key into the caller's AtChops.AtKeys.enrollmentToAuthenticateAs(), and a retrofitted keyfile
authenticates as its successor. A keyfile holding several live enrollments
throws, naming them.apkamSymmetricKeyResolver on AtEnrollmentRequest.pq and
AtEnrollmentResponse returns a Stream<String> rather than one key.pending
answer is denied and thrown.AtAuthSession no longer carries atLookUp.httpsProbe, defaultProbe and secureSocketProbe are removed;
the check before an activation uses at_lookup's checkAtSignServer. at_auth
no longer depends on at_server_status.AtKeys.toAtChops and toAtChopsForEnrollment are private; use
AtKeys.authenticationFor, or authenticationKeyPairFor,
encryptionKeyPair and selfEncryptionKey for the material itself.AtKeys.copyWith is removed; use addKey.KeyIOMixin is removed; read and write a .atKeys file with
FileAtKeysIo.read and write, or use AtKeysIo.passphraseCodec for the
passphrase envelope alone.ActivateApiEndpoint and
RegistrarApiEndpoint.login/validate are removed; use
RegistrarApiEndpoint.requestOtp/validateOtp.activateAtSign(...) activates an atSign with its CRAM secret and
answers the new enrollment's id.CryptographicMaterialStatus.pending marks an enrollment's keys between
submission and approval, managed with AtKeys.activatePending,
discardEnrollment and pendingEnrollmentIds.AtKeys.holdsAuthenticationMaterial, authenticationKeyPairFor,
encryptionKeyPair and selfEncryptionKey.AtKeys.fileLegacyMaterial, AtKeys.legacy,
enrollmentSymmetricKey and storedEnrollmentId reach a keyfile's flat
legacy fields without the deprecated members.InMemoryAtKeysIo.holding(atSign, keys), an in-memory store already
holding a key set.FileAtKeysIo writes typed keys into a flat keyfile, it
keeps a <keyfile>.pre-v1 copy."keys": [] again, so an application on
at_auth 3.3.0 can still read it.close(), which now ends a lookup.waitForApproval with logProgress set no longer waits 500 ms before
each attempt.AtKeys.metadata is no longer deprecated.at_lookup ^3.7.0-rc2 and at_commons ^5.18.0.A release candidate: adopt it deliberately. The headline is post-quantum credentials, with an enrollment able to authenticate with ML-DSA-65 while dep
A release candidate: adopt it deliberately. The headline is post-quantum credentials, with an enrollment able to authenticate with ML-DSA-65 while deployed peers still read what it advertises.
package:at_auth/at_auth.dart no longer reaches dart:io.
FileAtKeysIo, and anything else needing a filesystem, a socket or HTTP, is
in package:at_auth/at_auth_io.dart.AtEnrollmentRequest requires signingAlgo.AtOnboardingRequest.atKeysIo no longer defaults to
FileAtKeysIo().authenticatorForChops requires signingAlgo and hashingAlgo..atKeys typed document groups keys by enrollment, role and
algorithm. Legacy keyfiles, and those written by 3.3.0, still read.CryptographicMaterialStatus and KeyEntryStatus read values a newer client
writes rather than refusing them._apsk advertises a list. One active rsa2048 key is still the
bare public key every deployed peer reads; anything else is a JSON array,
which deployed peers cannot read.AtKeys.authenticationAlgorithmFor throws for an algorithm this
build cannot sign with, rather than returning null.AtOnboardingRequest.atKeys, AtAuthRequest.encryptedKeysMap and
AtKeysIo.generateKeyPairs's atSign are removed; the other members marked
for removal in v4 now say v5.AtSelfEnrollmentRequest moves an
enrollment to an ML-DSA-65 APKAM key, and AtEnrollment.update sends the
enroll:update with the possession proof the atServer checks.mintLegacyMaterial opts out of classical keys beside it._apsk; a retired key stays advertised, so what it signed still
verifies.AtAuthenticator: at_lookup is handed an authenticator for a PKAM
key, an AtChops, a CRAM secret or an enrollment, rather than credential
fields.AtEnrollmentRequest.pq(...) has the approver seal the symmetric key
to the request's key package, so nothing RSA-wrapped rides the enrollment.resolveAuthenticatingEnrollment() lists them rather than choosing one.FileAtKeysIo locks across processes, and WrittenAtKeysIo.update is one
operation..atKeys passphrase envelope uses a random salt and carries a
version; files without one still open.FileAtKeysIo.update no longer recreates a keyfile deleted while it
ran, and throws AtKeysSourceAbsentException.waitForApproval stops on a refusal it cannot resolve, counts its
retries as consecutive failures, and opens key records written without an
iv.at_commons ^5.16.0, at_chops ^3.6.0 and at_lookup
^3.7.0-rc1.Supplying neither session nor the deprecated atSign throws ArgumentError. The legacy path (no session, or a read-only AtKeysIo) leaves atAuthKeys popu…
AtAuthSession (exported) — the explicit auth→client hand-off artifact: the confirmed subset of an auth request that client creation actually needs (atSign, rootDomain, namespace, atKeysIo, enrollmentId), promoted to its own type so "request" no longer doubles as "session". Keys cross the boundary as an AtKeysIo source, not as live crypto state: the client derives its own AtKeys via atKeysIo.read(atSign) rather than adopting auth's AtChops/AtLookUp. The session also carries auth's already-authenticated atLookUp so a caller can opt in to reusing that connection (AtClientManager.fromAuthSession(session, reuse: true)) and skip a second PKAM handshake; the default hand-off rebuilds a fresh connection.AtAuthImpl.authenticate(...) and .onboard(...) populate the new AuthResponse.session on success whenever the request supplied an atKeysIo — pass it straight to AtClientManager.fromAuthSession(...). The legacy atAuthKeys-only path has no key source to hand across, so it gets no session and keeps behaving exactly as before.AtEnrollmentRequest now takes a session (the requesting app's atSign, rootDomain and the atKeysIo its new keys will be persisted into) in place of the individual atSign/rootDomain/apkamPublicKey/encryptedAPKAMSymmetricKey params. On approval, waitForApproval(...) flushes the completed keyset into session.atKeysIo (when it is a WrittenAtKeysIo) and hands back a ready-to-use AtEnrollmentResponse.session. Supplying neither session nor the deprecated atSign throws ArgumentError. The legacy path (no session, or a read-only AtKeysIo) leaves atAuthKeys populated for the caller to persist and sets session to null.AtAuthSession hand-off replaces is marked @Deprecated(... 'remove in v4') and still fully functional in 3.3.0 — AuthResponse and its AtAuthResponse/AtOnboardingResponse subclasses, the atAuthKeys/atLookUp/atChops response fields, AtEnrollmentResponse.atSign/.rootDomain/.atAuthKeys, and the AtEnrollmentRequest params listed above. No runtime behaviour changed; this release is additive so consumers can migrate to session before at_auth 4.AtKeysMaterial — the only key type AtKeys's API deals in (addKey, getKey, keysForKeyId, keysForEnrollment, retireKey, the keysList constructor param, ...). It's fully self-describing: keyId/enrollmentId plus keyPartType (an open String — the mechanical crypto role; known tokens in CryptographicKeyType: symmetric encryption/authentication and the public/private halves of encryption, verification/signing, encapsulation/decapsulation and key agreement), keyAlgorithmType (an open String — the algorithm family; known tokens in KeyAlgorithmType: aes256/rsa2048/ecc_secp256r1/ed25519/x25519/mlkem768/mldsa65/xwing, matching the pkam/enrollment signingAlgo literals), bytes, operations, createdAt, and status (active/retired/dead; withStatus(...) copies a material at a new status). Both token fields are deliberately Strings, not enums: unknown tokens are preserved and round-tripped, so a keyfile written by a newer client stays readable — and losslessly flushable — by an older one; whether an algorithm is classical, post-quantum or hybrid is carried by the algorithm token (e.g. xwing), not a separate role axis. The wire's nested keys[].keyParts[] document shape — grouping the materials sharing a keyId (e.g. the public+private halves of a keypair) — is produced/consumed by encodeAtKeysDocument/parseAtKeysDocument (also exported), not a separate model type. Keys produced by one enrollment are grouped by an optional enrollmentId and queried via AtKeys.keysForEnrollment(...); at most one material of a given CryptographicKeyType may share an enrollmentId.AtKeys.toJson()/.fromJson(...) now produce/consume the versioned typed-keys document shape (version, atsign, keys, with legacy fields flat at the top level — upgrading a legacy file to the typed-keys document is additive, not a format swap), replacing the former codec/resolver/document layer. Backward compatible: fromJson accepts json without a version field as the legacy flat shape, and throws AtKeysUnsupportedVersionException on an unknown version. Typed materials are looked up via AtKeys.getKey(keyId, type) and .keysForKeyId(keyId).WrittenAtKeysIo.flush(Atsign, AtKeys) — the runtime persist operation: mutate the in-memory AtKeys (addKey, retireKey, ...), then flush the complete state. On an existing file, flush safety-checks the rewrite (AtKeysAssurance.validateMapUpdate — nothing may be lost: every existing (keyId, keyPartType) must survive with identical fields, though status may move forward active → retired → dead and new materials may be added), then rewrites; flushing a legacy .atKeys file upgrades it in place to the typed-keys document format (legacy fields preserved byte-for-byte). On a missing file, flush creates it. write(...) stays the create-only initial persist. (The append/save methods that existed briefly during this release's development are gone — never published.) FileAtKeysIo writes are atomic (write-to-temp + rename, so a crash can never truncate the keyfile) and a flush over an existing file first preserves it as <file>.bak.AtKeysAssurance is now the single home for all atKeys validation — both the low-level expect*/optional* value/type checks used by AtKeysMaterial.fromJson/AtKeys.fromJson, and the structural invariants (validateKeyMaterials: duplicate keyId, one material of each CryptographicKeyType per enrollment, the flush-safety check validateMapUpdate).AtKeysPassphraseEnvelopeCodec (encode/decode/isEnvelope, argon2id key derivation), and add InMemoryAtKeysIo for in-memory/test flows (both exported).AtKeys.==/hashCode now also cover atsign, metadata (compared structurally — nested maps/lists by value, not identity) and the typed key materials (order-insensitive).at_chops ^3.4.1 for hashing algorithm barrel exports used by AtKeys passphrase handling.RegistrarService now fails loudly on a bad API key instead of reporting
an ordinary negative result. The constructor throws AtException when apiKey
is empty or whitespace-only, and every registrar call that requires
authentication throws AtException naming the endpoint and status code when
the registrar answers 401/403. Previously a rejected key surfaced as
sendActivationOtp() returning false (or an empty atsign list), which is
indistinguishable from a legitimate "no" — callers that treated a falsy result
as an expected outcome will now see an exception (#1909).Nothing published for this version
feat: bound AtAuthImpl.validateAtServer with a single overall deadline so a dead network can no longer hang authentication/onboarding. RetryOptions ga
AtAuthImpl.validateAtServer with a single overall deadline so a
dead network can no longer hang authentication/onboarding. RetryOptions gains
an optional overallTimeout; when null the default depends on the request:
authentication uses AtNetworkTimeouts.effectiveDefault (30s) so a dead network
fails fast, while ONBOARDING uses AtNetworkTimeouts.defaultOnboardingTimeout
(5 min) because a newly-registered atSign can take minutes to be provisioned.
The loop is deadline-driven — it retries every retryDelay until the budget is
spent, then throws AtTimeoutException; each inner network call (the atDirectory
lookup and the connectivity probe) is bounded by the remaining budget and capped
at 60s. RetryOptions.maxRetries no longer bounds this loop (the deadline
does) (#1923). Requires at_commons ^5.13.0.at_lookup: ^3.6.0 — validateAtServer passes the timeout
parameter that SecondaryAddressFinder.findSecondary gained in at_lookup
3.6.0, so this version does not compile against at_lookup ≤3.5.x.refactor: route enrollment RSA (encrypt/decrypt apkamSymmetricKey under the default encryption keypair) through at_chops (RsaEncryptionAlgo) — crypton
apkamSymmetricKey under the default encryption keypair) through at_chops (RsaEncryptionAlgo) — crypton no longer imported in lib and moved to dev_dependencies (only the enrollment test still uses it for RSA keypair fixtures). Same framing, byte-identical by construction.decodeAtKeys() now reliably throws AtDecryptionException on an incorrect passphrase. The jsonDecode of the decrypted bytes now runs inside the decrypt try/catch, so wrong-passphrase garbage no longer escapes as an uncaught FormatException (an intermittent failure in at_keys_io_test).feat: validateAtServer() now emits progress events and probes atSign connectivity before returning
validateAtServer() now emits progress events and probes atSign connectivity before returningdecodeAtKeys() now throws when an invalid passphrase is providedFileAtKeysIO now encrypts the key file with a passphrase when one is availableAtAuthenticationException when the atSign is already onboardedAtKeys (requires at_commons: ^5.9.0)feat: introduce NamespacePermission
AtEnrollmentImplNamespacePermissionrefactor: remove all singletons, injecting dependecies via AuthRequest
AuthRequestAtKeysIo interface which defines interaction between stored/generated keys and at_authFileAtKeysIo class which defines implementationAtLookup and AtChops via AuthResponseAtAuth exposes a ProgressStream to consume status of at_auth- chore(deps): at_commons ^5.5.0
feat: add AtLookUp? atLookUp to the AtAuth interface so that it can be reused (e.g. by AtClient) once auth is complete
AtLookUp? atLookUp to the AtAuth interface so that it can be
reused (e.g. by AtClient) once auth is completefeat: enable callers of AtAuth.onboard to control post-auth activation completion (set the encryption public key on the server, delete the "cram" secr
AtAuth.onboard to control post-auth activation
completion (set the encryption public key on the server, delete the "cram"
secret)fix: potential bug handling atSigns which end in data e.g. @foo_data
data e.g. @foo_datafix: Replace legacy IVs with random IVs for encrypting "defaultEncryptionPrivateKey" and "selfEncryptionKey" in APKAM flow
fix:Enable caching of encryption public key
feat: Add "passPhrase" in "AtAuthRequest" to support password protected atKeys file
build[deps]: Upgraded the following packages:
fix: Add "apkamKeysExpiryDuration" to "EnrollmentRequest" to support auto expiry of APKAM keys
fix: set atChops in atLookup before pkam auth in AtAuthImpl
fix: Add "revoke" to the "AtEnrollmentBase" to support enroll:revoke operation
fix: Add optional parameters to the "atAuth" method in "AtAuthInterface"
fix: set default value for app name and device name if they are not passed in the onboarding request.
fix: deprecate enableEnrollment flag in OnboardingRequest and removed the check in AtAuthImpl
build[deps]: Upgraded the following packages:
Nothing published for this version
build[deps]: Upgraded the following packages:
build[deps]: Upgraded the following packages:
fix: upgrade at_lookup to 3.0.43 since 3.0.42 has breaking change for private key reference
feat: enrollment common code from at_client_mobile and at_onboarding_cli
feat: Introduce "submitEnrollment" and "manageEnrollment" methods for APKAM
Implemented onboard and authenticate methods.
Your coding agent can read these notes before it upgrades. Set up the MCP server →