All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Witness server (
crates/auths-core/src/witness/server.rs) — P-256 witnesses now supported end-to-end.WitnessServerInner.{seed, public_key}replaced withsigner: TypedSignerKey(curve-tagged);WitnessServerConfig::with_generated_keypair(db_path, curve: CurveType)accepts curve parameter; DID derivation usesauths_crypto::{ed25519,p256}_pubkey_to_did_keyper curve (no morez6Mkhardcode). CLI layer defaults to P-256 witnesses. - KERI event-submission validator now parses
k[0]viaKeriPublicKey::parse(CESR-aware); dispatches signature verify on parsed curve. Hex-encodedk[0]retained as legacy back-compat branch for Ed25519-only. - CESR strict parser —
KeriPublicKey::parserejects legacy1AAJP-256 verkey prefix (CESR spec's1AAJis the P-256 signature code, not a verkey code).1AAIis the only accepted P-256 verkey prefix. Pre-launch posture — no on-disk v1 identities to protect. - Typed newtypes for non-signing 32-byte fields:
auths_crypto::Hash256(re-exported viaauths_verifier::Hash256) for content digests.ApprovalAttestation.request_hashmigrated.auths_pairing_protocol::X25519PublicKeyfor X25519 ECDH keys.CompletedPairing.initiator_x25519_pubmigrated.- Both use
#[serde(transparent)]— byte-identical wire format.
SeedSignerKeynow holdsDevicePublicKey+curve: CurveTypeinstead of[u8; 32]. Sign path dispatches viaTypedSignerKey::sign(curve-aware).RotationSignertype alias deleted — all workspace callers migrated toTypedSignerKey.did_key_to_ed25519anded25519_to_did_keywrappers deleted fromauths_id::identity::resolve. Callers useauths_crypto::did_key_decode+DecodedDidKeyvariants. Deny-list entry removed from all 7clippy.tomlfiles.ED25519_PUBLIC_KEY_LENno longer used outsideauths_crypto—wasm.rsmigrated toCurveType::from_public_key_lenfor curve-aware length validation.- Doc comment sweep —
auths-core/src/ports/{network,transparency_log}andpackages/auths-pythondocstrings updated to not claim Ed25519-specificity in curve-agnostic functions. - Pairing-protocol test helper —
generate_ed25519_keypair_syncno longer byte-slices ring PKCS8 internals; routes throughauths_crypto::parse_key_material(curve-detecting).
- RFC 5656
ecdsa-sha2-nistp256SSH support landed. Agent-mode signing,add_identity,request_identities,sign,remove_identity, OpenSSH PEM export (export_key_openssh_pem), and.publine export (export_key_openssh_pub) all curve-dispatch.SeedSignerKey::kind()reports the correctSshAlgorithm::Ecdsa { curve: NistP256 }for P-256 seeds;SeedSignerKey::sign()produces DER-encoded(r, s)signatures viatyped_sign. AgentError::P256SshUnsupportedvariant deleted (was error codeAUTHS-E3026, introduced in fn-116.18 as a loud-fail placeholder). P-256 identities now work with the SSH agent flow with no caller-visible errors.AgentCorestores curve alongside seed (StoredKey { seed, curve }) so the sign path dispatches on the curve of the key that was registered — no more inference from public-key length.- macOS system agent registration (
register_keys_with_macos_agent_with_handle) propagates curve through to PEM conversion; both Ed25519 and P-256 keys can bessh-added via the platform agent.
TypedSignatureenum graduation (variant-per-curve) — deferred. Current newtype covers the 64-byte coincidence (Ed25519 = P-256 r||s). Full enum becomes load-bearing when a curve with a different signature length arrives (ML-DSA-44 = 2420 bytes).- B3 typed-wrapper sweep (
Ed25519PublicKey/Ed25519Signaturestruct fields across ~20 production files) — deferred alongside the enum graduation. - Per-site migration of remaining banned-API call sites across production crates. Workspace clippy green via the crate-level transitional allows that fn-115 was scoped to remove.
- xtask: Removed
cargo xt ci-setup. Useauths ci setup(orjust ci-setup) instead.
auths-python: Unified Python SDK package — consolidatedauths-verifier-pythonandauths-agent-pythoninto a singlepackages/auths-pythoncrate. Shared FFI runtime, module registration, and type definitions insrc/runtime.rsandsrc/types.rs.auths-python:Authsclient class — Stripe-style client withrepo_pathandpassphraseconstructor, resource services (auths.identities,auths.devices), and typed error hierarchy (AuthsError,CryptoError,KeychainError,StorageError,NetworkError,IdentityError,VerificationError).auths-python: Identity lifecycle FFI —create_identity,provision_agent,link_device_to_identity,revoke_device_from_identityRust FFI functions with PyO3 bindings.IdentityServiceandDeviceServiceresource classes expose these asauths.identities.create(),auths.identities.provision_agent(),auths.devices.link(),auths.devices.revoke().auths-python: Keychain-backed signing —sign_as_identityandsign_action_as_identityFFI functions resolve DID-or-alias to a keychain key and sign bytes or action envelopes. Exposed asauths.sign_as()andauths.sign_action_as().auths-python: Capability-scoped verification —verify_attestation_with_capabilityandverify_chain_with_capabilityFFI functions. Python wrappers on theAuthsclient.auths-python: Getting Started README — quickstart example covering identity creation, device linking, signing, and verification.
auths-python: Time-pinned verification —verify_at_timeandverify_at_time_with_capabilityFFI functions accept an ISO 8601 timestamp string, enabling "was this valid at time T?" queries for audit and compliance.auths-python: Witness chain verification —verify_chain_with_witnessesFFI function accepts witness receipts, threshold, and public keys for k-of-n quorum verification.auths-python: Key rotation —rotate_identity_ffiFFI function andauths.identities.rotate()Python method.IdentityRotationResultdataclass withcontroller_did,new_key_fingerprint,previous_key_fingerprint,sequence.auths-python: Device authorization extension —extend_device_authorization_ffiFFI function andauths.devices.extend()Python method.DeviceExtensiondataclass.auths-python: Attestation query service —list_attestations,list_attestations_by_device,get_latest_attestationFFI functions.AttestationServiceresource class withauths.attestations.list(),auths.attestations.by_device(),auths.attestations.latest().auths-python: Artifact attestation signing —sign_artifactandsign_artifact_bytesFFI functions.auths.sign_artifact()andauths.sign_artifact_bytes()Python methods.ArtifactSigningResultdataclass.auths-python: Git commit signing —sign_commitFFI function andauths.sign_commit()Python method.CommitSigningResultdataclass.auths-python: Policy engine —compile_policyFFI function,PyCompiledPolicyandPyEvalContextclasses.PolicyBuilderfluent API for constructing policies in Python.auths-python: JWT validation —AuthsClaimsdataclass and JWKS client helper for validating Auths-issued JWTs.
auths-sdk: Identity creation function renames —setup_developer()→create_developer_identity(),quick_setup()→create_developer_identity_quick(),setup_ci()→create_ci_identity(),setup_agent()→create_agent_identity(),build_agent_proposal()→build_agent_identity_proposal(). Naming now conveys identity lifecycle semantics ("create" = inception) rather than generic "setup".auths-sdk: Config type renames —DeveloperSetupConfig→CreateDeveloperIdentityConfig,CiSetupConfig→CreateCiIdentityConfig,AgentSetupConfig→CreateAgentIdentityConfig(with corresponding builder renames).auths-sdk: Result type renames —SetupResult→CreateIdentityResult,CiSetupResult→CreateCiIdentityResult,AgentSetupResult→CreateAgentIdentityResult.auths-sdk: Rotation type renames —RotationConfig→IdentityRotationConfig,RotationResult→IdentityRotationResult. Clarifies these operate on KERI identities (did:keri:), not device keys.auths-python: Agent operation split —provision_agent()replaced with two distinct operations:create_agent_identity()(standalonedid:keri:identity) anddelegate_agent()(delegateddid:key:under a parent). Python API:auths.identities.create_agent()andauths.identities.delegate_agent().auths-python:Agentdataclass replaced — split intoAgentIdentity(standalone,did:keri:) andDelegatedAgent(delegated,did:key:).auths-python:Identity.public_key→Identity.key_alias— field name now matches the Rust SDK terminology.auths-python:RotationResult→IdentityRotationResult— consistent with Rust SDK rename.auths-cli: Updated call sites —init.rsandid/identity.rsupdated to use renamed SDK functions and types.
auths-core: SSH agent abstracted behindSshAgentPorttrait —Command::new("ssh-add")subprocess calls extracted fromruntime.rsinto a newports::ssh_agentmodule withSshAgentPorttrait andSshAgentErrortyped error.MacOsSshAgentAdapterinauths-cliimplements the trait. Enables testing and alternative SSH agent backends without subprocess shell-outs.auths-core/auths-sdk:#![deny(clippy::unwrap_used, clippy::expect_used)]enforced — allunwrap()/expect()calls in production code replaced with proper error propagation (?,map_err,unwrap_or_elsefor poisoned mutexes).allow-unwrap-in-testsandallow-expect-in-testsset in.clippy.tomlto preserve test ergonomics.witness/server.rscreate_receiptandsign_payloadnow returnResultinstead of panicking.auths-core:CommitSigningContextdependency struct — lightweight struct holdingkey_storage,passphrase_provider, andagent_signingtrait objects, replacing scattered parameter passing in the signing pipeline.
- CI:
Cargo.locknow committed — the blanket*.lockgitignore pattern was preventingCargo.lockfrom being tracked, causingcargo auditin CI to fail. Replaced with specific JS lock file patterns (package-lock.json,yarn.lock,pnpm-lock.yaml). - CI: Platform-gated dead code in
passphrase_cache.rs—PASSPHRASE_SERVICE,encode_secret, anddecode_secretnow gated with#[cfg(any(target_os = "macos", ...))]to eliminate dead-code warnings on Linux CI builds.
These releases were bumped while resolving circular dev-dependency cycles that blocked
cargo publish --workspace. Key fixes: distributed theauths-test-utilsmonolith into per-cratetest-utilsfeatures, removed theauths-infra-gitupward dev-dependency fromauths-id, and moved git-storage implementations fromauths-idtoauths-storage. Seedocs/plans/dependency-architecture-refactor.mdfor full details.
-
auths-crypto:CryptoProvidertrait and native/WASM abstraction — new asyncCryptoProvidertrait abstracting Ed25519 operations (sign, verify, generate keypair, derive public key from seed).RingCryptoProviderimplements the trait for native targets usingring.WebCryptoProviderstub scaffolded forwasm32targets. Feature-gated:nativeenables ring+tokio,wasmenables the WASM path.SecureSeed(zeroize-on-drop) is now the canonical key representation across all crates. -
auths-crypto:key_materialmodule — canonical key parsing functions (parse_ed25519_seed,parse_ed25519_key_material,build_ed25519_pkcs8_v2) consolidated from scattered implementations across auths-core and auths-cli. -
auths-test-utils:MockCryptoProvider— deterministic mock for testing crypto operations without ring dependency. -
Type Safety Audit — comprehensive replacement of stringly-typed fields with semantic newtypes across the entire workspace:
auths-verifier: AddedResourceIdandRolenewtypes;Ed25519PublicKeynewtype replacingVec<u8>(32-byte fixed array,Copy);Ed25519Signaturenewtype replacingVec<u8>(64-byte fixed array)auths-id: AddedSealTypeenum,KeriSequencenewtype (wrapsu64),GitRef/BlobNamenewtypes for storage layout; typed witness and receipt fieldsauths-verifier:BridgeErrorandVerifyResultnow use structured reason enums instead of opaque stringsauths-core:ResolvedDidconverted from struct+DidMethodenum to a two-variant enum (Key/Keri) with accessor methods;DidMethoddeleted. Same pattern applied toResolvedIdentityin network portsauths-sdk:SetupParams,DeviceRegistration,SigningConfigfields useIdentityDID,DeviceDID,Vec<Capability>instead ofString/Vec<String>auths-id:StoredIdentityData.controller_did,AgentIdentityBundle.agent_did→IdentityDID;MemberViewfields →Role,Vec<Capability>,IdentityDID,ResourceId;MemberFilter→HashSet<Role>/HashSet<Capability>;MemberInvalidReasonfields →DeviceDID/IdentityDID;OrgMemberEntry.org→IdentityDIDauths-core: AddedBase64UrlEncodednewtype for pairing types withencode()/decode()/Deref<Target=str>/#[serde(transparent)]/JsonSchema;CreateSessionRequest.ephemeral_pubkey→Base64UrlEncoded;SubmitResponseRequestfields →Base64UrlEncoded/DeviceDID- All newtypes use
#[serde(transparent)]— wire format unchanged, zero migration needed
-
auths-verifier: Refactored to useCryptoProvider— all Ed25519 verification now routes through theCryptoProvidertrait instead of callingringdirectly.ringis feature-gated behindnative(default). WASM builds use--no-default-features --features wasmto avoid pulling tokio/ring. -
auths-core: Removedringfrom production dependencies —ringmoved to dev-dependencies (test-only). All production crypto operations route throughauths-crypto::CryptoProvidervia a sync bridge (provider_bridge.rs). Key storage changed from raw PKCS#8 bytes toSecureSeed. -
auths-core:AgentCorekeys stored asSecureSeed—HashMap<Vec<u8>, SecureSeed>replaces previousZeroizing<Vec<u8>>storage. PKCS#8 bytes rebuilt on-demand viabuild_ed25519_pkcs8_v2when needed for macOS agent registration. -
auths-registry-server: Stripe integration and api endpoints. -
auths-registry-server: Repo-per-tenant isolation — introduced aTenantResolverport trait with two adapters:SingleTenantResolver(existing single-tenant deployments, unchanged behaviour) andFilesystemTenantResolver(multi-tenant SaaS, one Git repository per tenant under{base}/tenants/{id}/).FilesystemTenantResolvercaches openPackedRegistryBackendinstances in a bounded moka LRU cache (capacity configurable); errors are never cached.invalidate(tenant_id)andinvalidate_all()allow callers to evict stale entries after suspension or deprovisioning. Path traversal is blocked viacanonicalizeof the tenants root followed by astarts_withcheck on the computed tenant path (symlink hardening). ATenancyModeKindenum (Single/Multi) is exposed by every resolver so middleware can gate multi-tenant routes without reaching into config. All existing routes are re-mounted under/v1/t/:tenant_idvia aTenantBackendaxum extractor; single-tenant mode routes continue to work as before.POST /v1/admin/tenantsprovisions a new tenant registry; the endpoint is idempotent — first provisioning returns201 Created, subsequent calls return200 OKwith"already_provisioned". The endpoint is protected byRequireAdminToken(strictBearerprefix parsing, constant-time token comparison,501 Not Implementedwhen no admin token is configured). ADR-001 (docs/adr/ADR-001-repo-per-tenant-isolation.md) documents the design decisions and rejected alternatives. Edge cases covered intests/cases/tenant_http.rs: reserved tenant IDs → 400, unknown tenant → 404, single-tenant mode rejects/v1/t/...→ 404, bad/missing admin token → 401/501, moka cache eviction and re-resolution correctness. -
auths-index:identitiesandorg_membersSQLite tables — new schema tables with WAL mode.IndexedIdentity(prefix, current keys, sequence, tip SAID) andIndexedOrgMember(org/member/issuer DIDs, rid, revoked/expires timestamps) types withupsert_*,query_identity, andlist_org_members_indexedmethods. -
auths-id:rebuild_identities_from_registryandrebuild_org_members_from_registry— free functions (feature:indexed-storage) that walk the packed Git registry and repopulate a freshAttestationIndex, enabling full index reconstruction from Git without downtime. -
auths-oidc-bridge: GitHub Actions OIDC cross-reference (github-oidcfeature) — newgithub_oidcmodule fetches GitHub's JWKS, validates RS256 tokens, and extracts actor/repository claims.JwksClientimplements in-memory caching with configurable TTL,tokio::sync::Mutex-based request coalescing (thundering herd protection), circuit breaker (5 failures → 60s cooldown), exponential backoff with jitter, and stale-cache fallback on fetch failure. -
auths-oidc-bridge: Actor cross-reference module —cross_reference.rsverifies the GitHubactorclaim matches the expected KERI identity holder before JWT issuance, creating a two-factor proof (KERI chain + CI/CD environment). -
auths-oidc-bridge: AWS STS integration tests —tests/aws_integration.rswith realAssumeRoleWithWebIdentitytest (requiresAWS_ROLE_ARN+AUTHS_BRIDGE_URLenv vars) and LocalStack fallback test. Both#[ignore]by default for CI safety. -
auths-oidc-bridge:claims_supportedin OpenID Configuration —/.well-known/openid-configurationnow includes the full list of supported JWT claims (iss,sub,aud,exp,iat,jti,keri_prefix,capabilities,witness_quorum,github_actor,github_repository). -
docs/oidc-enterprise-guide.md— enterprise security documentation covering trust boundaries, STRIDE threat model (8 attack vectors), key rotation procedure (90-day cadence), Break Glass incident response playbook (<15 min RTO), AWS IAM integration guide, Terraform and CloudFormation IaC templates, and GitHub Actions workflow examples.
-
auths-registry-server: Migrated pairing and tenant metadata stores from SQLite to PostgreSQL —SqlitePairingStoreandSqliteTenantMetadataStoreand theirrusqlitedependency have been removed. Replaced byPostgresPairingStoreandPostgresTenantMetadataStorebacked by sqlx 0.8 with compile-time query verification. BothPairingStoreandTenantMetadataStoretraits are now fully async viaasync-trait. Schema managed via sqlx migrations (migrations/001_pairing_sessions.sql,migrations/002_tenant_metadata.sql). A single sharedPgPool(max 10 connections) is injected into both stores at startup; setREGISTRY_POSTGRES_URLto a PostgreSQL connection string. sqlx offline query cache (.sqlx/) committed for builds without a live database (SQLX_OFFLINE=true). -
auths-cli:setuprenamed toinit;statuspromoted to primary surface —auths setupis nowauths init(same profiles:developer,ci,agent).auths statusis now a top-level command alongsideinit,sign, andverifyinstead of living underauths advanced. Witness flags (--witness,--witness-threshold,--witness-policy) are removed from the onboarding path; useauths advanced witnessfor witness management. -
auths-cli:auths advancednesting removed — all subcommands are now top-level:auths device,auths id,auths key,auths policy,auths emergency, etc. Theauths advanced <cmd>prefix no longer exists.auths --helpstill shows only the four primary commands; the rest are discoverable viaauths <cmd> --help. -
auths-oidc-bridge: Exchange handler refactored for composable validation —token_exchangehandler now performs GitHub cross-reference as a decoupled pre-step (SRP) before callingOidcIssuer::exchange(). Structured tracing events emitted for every exchange:auths.exchange.github_cross_reference.success,.failure, andkeri_only.exchange()accepts an optionalCrossReferenceResultto populategithub_actorandgithub_repositoryclaims in the minted JWT. -
auths-oidc-bridge:ExchangeRequestexpanded — accepts optionalgithub_oidc_tokenandgithub_actorfields (feature-gated behindgithub-oidc). -
auths-oidc-bridge:BridgeConfigexpanded — new fieldsgithub_oidc_issuer,github_expected_audience, andgithub_jwks_cache_ttl_secsfor GitHub OIDC configuration. -
auths-index: Renamedrebuild_from_git→rebuild_attestations_from_git— updated all callers inauths-idandauths-cli. -
auths-id:PackedRegistryBackendnow wires SQLite index writes on every mutation —store_attestation,store_org_member, andappend_eventperform best-effort write-through toArc<Mutex<AttestationIndex>>(feature-gated:indexed-storage). Index is best-effort; Git remains the source of truth. -
auths-id:list_org_members_fastadded toRegistryBackendtrait — default delegates tolist_org_members;PackedRegistryBackendoverride uses the SQLite index for O(1) lookups, falling back to Git when the index is empty or a capability filter requires full attestation data. -
auths-id: Replaced redb cache with Redis-backed tiered storage — removed the embeddedredbread-through cache (RegistryCache) fromPackedRegistryBackend. Identity resolution now uses a two-tier architecture: Tier 0 (Redis) for sub-millisecond cached lookups and Tier 1 (Git) as the persistent cryptographic ledger. Newauths-cachecrate implementsTierZeroCache(Redis viabb8pool) andTierOneArchive(Git viaspawn_blocking), orchestrated by aTieredResolverusing Cache-Aside reads and Write-Through writes with a backgroundArchivalWorker. Failed Git writes route to a Redis Stream dead letter queue to protect KERI hash chain integrity. Redis is optional — whenAUTHS_REDIS_URLis not set, the system falls back to direct Git reads. -
auths-sdk/auths-cli: Extracted business logic from CLI to SDK — signing pipeline (sign_artifact,validate_freeze_state), device pairing orchestration (validate_short_code,verify_device_did,create_pairing_attestation), git audit engine (AuditWorkflow+GitLogProviderport), artifact digest abstraction (ArtifactSourceport +LocalFileArtifactadapter), system diagnostics (DiagnosticProviderport), SSH crypto ops, and capability parsing all moved behind trait-based ports inauths-sdk. CLI is now a thin presentation layer delegating to SDK workflows. -
auths-core:EnvironmentConfig/KeychainConfig— new structs that collect all environment-variable reads (AUTHS_KEYCHAIN_BACKEND,AUTHS_HOME,AUTHS_KEYCHAIN_FILE,AUTHS_PASSPHRASE) at the process boundary.get_platform_keychain_with_config()andauths_home_with_config()replace zero-argument functions that read env vars internally.EnvironmentConfig::from_env()is the single permitted I/O site; all downstream logic receives the config by value. Eliminates hidden I/O coupling and makes the keychain backend fully injectable for tests. -
auths-core:ClockProvidertrait andSystemClock/MockClockimplementations — abstractsUtc::now()calls acrossauths-sdk(setup, device, pairing, signing, rotation),auths-id, andauths-verifier.MockClockinauths-test-utilsenables deterministic time in tests withoutunsafeenv-var mutation. -
Clock injection completed (Epic 2) — zero
Utc::now()calls remain inauths-core/src/orauths-id/src/outside#[cfg(test)]. All time-sensitive functions (create_signed_attestation,verify_with_resolver,extend_expiration,try_incremental_validation,provision_agent_identity,resolve_trust,PairingToken::generate*,WitnessStorage::store_receipt,GitKel::get_state,RegistryMetadata::new) acceptnow: DateTime<Utc>as an explicit parameter.auths-sdkpassesclock.now(); CLI passesUtc::now()at the presentation boundary. -
auths-core:EventSinktelemetry port — newEventSinktrait decouples structured event emission from stdout.StdoutSink(async MPSC worker, non-blockingemit(), blockingflush()) andMemorySink(in-process test capture) are the two provided implementations.init_telemetry()/init_telemetry_with_sink()set the global sink once at startup.DROPPED_AUDIT_EVENTScounter surfaces backpressure in the SIEM pipeline. -
auths-sdk:GitConfigProviderport trait —set(key, value)abstraction removesstd::process::Command::new("git")andwhich::whichfromauths-sdk.SystemGitConfigProviderinauths-cliimplements the trait via the systemgitbinary.DeveloperSetupConfiggains an optionalsign_binary_pathfield; the CLI resolves the path viawhich::which("auths-sign")and passes it at the presentation boundary. -
auths-sdk:SdkStorageErrortyped enum — replacesanyhow::ErrorinSetupError::StorageErrorandDeviceError::StorageError.RegistrationError::NetworkErrornow wrapsauths_core::ports::network::NetworkError(typed).RegistrationError::LocalDataErrorcarries aString.map_storage_err()andmap_device_storage_err()helper functions removed; callers use inline.map_err(|e| ...StorageError(SdkStorageError::OperationFailed(e.to_string()))).anyhowremoved fromauths-sdk/Cargo.toml.
Note: notes on release
0.0.1-rc.11and prior come from an earlier repository that (a) lived on the my personal account and (b) included crates that have since been stripped out. I've decided to leave them intact for documenting the development.
auths-auth-server: Migrated session store from SQLite to PostgreSQL —SqliteSessionStoreand itsrusqlitedependency have been removed (hard cut, no backward compatibility). Replaced byPostgresSessionStore(crates/auths-auth-server/src/adapters/postgres_session_store.rs) backed by sqlx 0.8 with compile-time query verification. Schema managed via sqlx migrations (migrations/001_init.sql). TheSessionStoretrait is now fully async viaasync-trait, making it dyn-compatible asBox<dyn SessionStore>. SetDATABASE_URLto a PostgreSQL connection string to enable; falls back toInMemorySessionStorewhen unset. sqlx offline query cache (.sqlx/) committed for builds without a live database (SQLX_OFFLINE=true).
auths-auth-server: Atomic CAS nonce invalidation inverify_auth—SessionStore::update_statusnow takesfrom+toparameters and returnsOk(bool).SqliteSessionStoreusesUPDATE … WHERE status = ?(evaluated atomically by SQLite);InMemorySessionStoreusesstd::mem::discriminantcomparison inside its write lock. Concurrent requests racing to verify the same session now get exactly one200 OK; the rest receive409 CONFLICT(SessionAlreadyVerified). Also addsPRAGMA synchronous=NORMALalongside WAL mode.
-
auths setup --profile developer: Step 6/6 — signing pipeline verification — after git config, runs a test commit in a throwaway temp repo to confirmauths-signis wired end-to-end. ReportsSkippedgracefully ifauths-signis not yet on PATH. -
UnifiedPassphraseProvider(auths-core): New passphrase provider that prompts exactly once regardless of how many distinct prompt messages are presented. Used inauths device linkso the entire link operation requires only one passphrase entry instead of two. -
auths doctor: exact runnable fix commands — all suggestion strings now start withRun:and are copy-pasteable.check_git_signing_configexpanded from checking onlygpg.formatto all 5 required signing configs (gpg.format,commit.gpgsign,tag.gpgsign,user.signingkey,gpg.ssh.program). -
auths-cliREADME: CI setup section — copy-pasteable GitHub Actions workflows for signed commits (auths setup --profile ci) and commit signature verification (auths verify-commit HEAD). -
LocalGitResolverfor air-gapped identity resolution (auths-auth-server): New adapter reads KERI key state directly from a local git registry (refs/auths/registry) viaPackedRegistryBackend, requiring zero network access. Eliminates the single point of failure fromRegistryIdentityResolverrequiring a live HTTP endpoint. -
ResolverModeconfig enum (auths-auth-server):AuthServerConfig.registry_url: Stringreplaced withresolver_mode: ResolverMode(RegistryHttp { url }|LocalGit { repo_path }). Builder methods:with_registry_url()andwith_local_git_resolver(). -
AUTH_SERVER_LOCAL_GIT_REPOenv var (auths-auth-server): When set, the server usesLocalGitResolverbacked by the given path instead of the HTTP registry. OverridesAUTH_SERVER_REGISTRY_URLif both are set. -
Air-gapped integration tests (
auths-auth-server):tests/air_gapped.rscovers full auth flow, unknown-DID rejection, and wrong-key rejection using a temp-dir git repo — no registry server needed. -
Bundle TTL:
IdentityBundlenow requiresbundle_timestampandmax_valid_for_secsfields. Bundles fail verification once stale, preventing revoked keys from passing CI indefinitely. -
auths id export-bundlegains a required--max-age-secsflag to set bundle TTL at export time. -
New
AttestationError::BundleExpiredvariant (AUTHS_BUNDLE_EXPIRED) with a re-export suggestion. -
GitHub Action enforces bundle age before invoking CLI verification.
- PKCS#8 magic offset removed from
extract_seed_from_pkcs8— replaced the brittlekey_bytes[16..48]fallback with a directPrivateKeyInfo::from_dercall and an exhaustive slice-pattern match on inner key bytes. Handles both the RFC 8410 DER OCTET STRING wrapping (04 20 <seed>) that ring produces and bare 32-byte seeds. Fails loudly with a descriptive error on unexpected formats. auths verify-commitalways failing with empty error —ssh-keygen -Y verify -I "*"does not treat*as a wildcard; it searches for a literal*entry in the allowed_signers file. Fixed by runningfind-principalsfirst to resolve the actual signer identity, then passing it toverify. Also fixed error capture:ssh-keygenwrites"Could not verify signature."to stdout, not stderr.
TODO: Cut a new release (
v0.0.1-rc.12) so CI downloads the fixed binary and commit verification passes in GitHub Actions.
- Support for homebrew install via
brew install auths-dev/auths-cli/auths
Note: these releases were a series of trial and error to get homebrew install working, which required several quick releases with nominal changes to configurations.
Note: these releases were a series of trial and error to get homebrew install working, which required several quick releases with nominal changes to configurations.
- Improved CLI error messages with actionable suggestions.
- New
auths doctorcommand to diagnose setup issues. - ci: Release workflow builds a native
authsbinary on the host and signs release artifacts using a device-only key from the encrypted CI keychain (AUTHS_CI_KEYCHAIN), with no identity/root key present in CI..auths.jsonattestation files are included in the release upload. - xtask: New
xtaskworkspace crate (publish = false) replaces the 187-line shellci-setuprecipe in the justfile. Uses the idiomatic Rust xtask pattern for project-internal CI tooling. Invokable viacargo xt ci-setuporjust ci-setup. - xtask: Native base64 encoding (
base64crate) eliminates the macOSbase6476-char line-wrapping bug that causedbase64: invalid inputon Linux CI runners. - xtask:
TempDir-based cleanup replaces manualrm -f— seed and keychain temp files are cleaned up automatically even on error. - xtask: Passphrase prompting via
rpassword— passphrase never appears in process arguments (unlike shellread -spiped through variable expansion). - xtask:
GH_TOKEN/GITHUB_TOKENenv vars are cleared viaenv_remove()on everyghinvocation, fixing the silent auth failure when a stale token overrides the keyring account. - xtask: Native tar/gzip archiving with
tar+flate2+walkdircrates — excludes*.sockfiles, norsyncdependency. - docs: adds docs on GitHub action and tarball signing workflows.
- docs: adds commit signing troubleshooting guide covering agent, keychain, and git config issues.
- auths-cli: New
auths key copy-backendsubcommand — copies a key from the current keychain backend to a file-based keychain without exposing raw key material. Accepts--dst-backend,--dst-file, and--dst-passphrase(orAUTHS_PASSPHRASEenv var). Replaces the fragile PEM-export → seed-parse → re-import pipeline previously used byjust ci-setup.
- auths-core: Implement
add_identity,remove_identity, andremove_all_identitieson the SSH agent session. Previously the agent rejected all key-loading requests withUnsupportedCommand, makingauths agent unlockfail and breaking Git commit signing via the agent. - auths-cli:
auths-signTier 2 keychain failure no longer causes an early return. When keychain or passphrase prompts fail (common in subprocess contexts), the error message now includes actionable instructions to start the agent and unlock the key. - ci: Fix WASM build check — qualify feature with package name (
--features auths_verifier/wasm) as required by Rust 1.93 / resolver 3 when running from a workspace root. - ci: Fix Windows build — gate
agent::clientmodule and all consumers behind#[cfg(unix)]sincestd::os::unix::net::UnixStreamdoes not exist on Windows. - ci: Fix
cargo testinvocation — split--docinto a separate step because cargo cannot mix--docwith--lib/--binstarget selectors. - auths-core:
AUTHS_KEYCHAIN_FILEenv var is now implemented — the file keychain backend uses the specified path instead of the default~/.auths/keys.enc. - auths-core:
AUTHS_PASSPHRASEenv var is now wired to the file keychain password, enabling fully headless CI artifact signing without interactive prompts. - auths-core:
EncryptedFileStorage::get_password()now falls back to theAUTHS_PASSPHRASEenvironment variable when no password has been set viaset_password(). This fixes a "Missing Passphrase" error that occurred when a newEncryptedFileStorageinstance was created after the initial one had the password wired in. - release.yml: Homebrew step secrets error secrets is only valid inside
${{ }}interpolation, not as a bare named value inif:expressions. Solution: expose a booleanHAS_HOMEBREW_TOKENenv var at the job level (where${{ }}is valid), then gate the step onenv.HAS_HOMEBREW_TOKEN == 'true'.
- auths-verifier:
identity_signatureonAttestationis now optional — serialized withskip_serializing_if = "Vec::is_empty"and deserialized withdefault. Dual-signed attestations are unchanged; device-only attestations omit the field (backward-compatible). - auths-cli:
--identity-key-aliasonauths artifact signis now optional. Omitting it produces a device-only attestation; the identity key never needs to enter CI. - auths-id:
create_signed_attestation,resign_attestation, andextend_expirationacceptidentity_alias: Option<&str>. PassingNoneskips identity signing. - auths-core:
EncryptedFileStorage::set_password()now takesZeroizing<String>instead ofString, enforcing secure handling of the passphrase from the point of construction. All callers updated. - justfile:
ci-setuprecipe now delegates tocargo xt ci-setup(was 187 lines of shell). - docs: Release process guide leads with justfile (
just release,just ci-setup) and moves manual steps to a secondary section.
- auths-cli:
auths emergency reportnow loads real identity and device data from storage instead of returning hardcoded mock DIDs. - auths-cli:
auths agent lock/unlockwired end-to-end — lock removes keys from agent memory, unlock reloads from keychain. - auths-cli:
--schemaflag onauths device linknow validates the payload against the JSON schema instead of being silently ignored. - auths-cli:
auths migrate statusdistinguishes GPG vs SSH signatures using%GSsigner format instead of assuming GPG. - auths-id:
extend_expiration()andresign_attestation()rewritten to useSecureSignerinstead of raw seeds. - auths-id: Revocation attestations now carry the real device public key (looked up from existing attestations) instead of a zeroed placeholder.
- auths-nostr:
run_with_permission_callback()now checks the callback before signing requests instead of ignoring it. - auths-core: Invalid custom policy actions return an error instead of silently falling back to
sign_commit. - auths-core: Socket timeout errors in the agent client are now propagated instead of silently discarded.
- auths-core: Replaced commented-out HTTP server code with a clean placeholder module.
- auths-id: Auto-install pre-receive hook during
auths init— rejects non-fast-forward pushes and ref deletions forrefs/keri/,refs/auths/, andrefs/did/keri/, preventing Git-level KEL rewrites that bypass the Rust registry. - auths-id: Add replay attack prevention to
store_attestation()— timestamp monotonicity andrid-based duplicate detection. - auths-verifier: Introduce
VerifiedAttestationnewtype; attestations must pass verification before storage. - auths-verifier: Add
MAX_ATTESTATION_JSON_SIZE(64 KiB) andMAX_JSON_BATCH_SIZE(1 MiB) limits — all JSON deserialization points across Rust, FFI, WASM, Python, Swift, and Go reject oversized inputs before parsing.
- auths-cli:
auths artifact signandauths artifact verifycommands for signing and verifying arbitrary files (tarballs, binaries). Uses dual-signed attestations withsign_releasecapability, SHA-256 content addressing, and optional witness quorum verification. HexagonalArtifactSourcetrait enables future Docker/NPM/Cargo adapters. - auths-id: End-to-end witness integration —
WitnessConfigandWitnessPolicy(Enforce/Warn/Skip) structs for identity-level witness configuration;create_keri_identity(),rotate_keys(), andabandon_identity()now populate KERI eventbt/bfields from config; witness receipts are automatically collected and stored after inception and rotation events when thewitness-clientfeature is enabled. - auths-id:
witness_integrationmodule (feature-gated behindwitness-client) —collect_and_store_receipts()wiresHttpWitnessClient,ReceiptCollector, andGitReceiptStorageinto the identity lifecycle with policy-based degradation. - auths-cli:
auths initgains--witness,--witness-threshold, and--witness-policyflags for configuring witnesses at identity creation time. - auths-cli:
auths witness add,auths witness remove, andauths witness listsubcommands for managing witness URLs in identity metadata post-init. - auths-cli:
auths id rotatenow loads witness config from identity metadata and threads it through to KERI rotation, automatically collecting receipts for rotation events. - auths-auth-server: SQLite-backed
SqliteSessionStoreas default session store — sessions persist across restarts with WAL mode for read concurrency, background cleanup task evicts expired sessions every 60s.SessionStoretrait expanded withdelete(),list_active(), andcleanup_expired()methods. - auths-registry-server: Extract
PairingStoretrait and add SQLite-backedSqlitePairingStoreas default pairing session store — sessions persist across restarts, background cleanup task evicts expired sessions every 60s. WebSocket notifiers remain ephemeral (in-memory). - auths-oidc-bridge: New crate that exchanges KERI attestation chains for short-lived RS256 JWTs consumable by cloud providers (AWS STS, GCP, Azure AD).
- auths-core (witness): Optional TLS via
tlsfeature flag (axum-server+rustls). - auths-id:
freezemodule — time-bounded identity freeze withauths emergency freeze/unfreeze. - auths-cli:
auths-signrefuses to sign while identity is frozen. - auths-verifier: FFI exports expanded to 4 functions: added
ffi_verify_chain_json()andffi_verify_device_authorization_json(). - auths-registry-server: OpenAPI 3.0 spec served at
/api-docs/openapi.json. - Dockerfiles for
auths-registry-serverandauths-auth-server, plusdocker-compose.yml. - GitHub Actions release workflow for cross-platform binaries (linux, macOS, Windows).
- CI: code coverage via
cargo-llvm-cov+ Codecov, mobile FFI tests, Go bindings tests.
- auths-cli:
auths verify-commit --identity-bundlenow verifies the full attestation chain (revocation, expiry, signature integrity) instead of only extracting the public key for SSH verification.--witness-receipts,--witness-threshold, and--witness-keysflags are now functional, enabling quorum-based witness verification for commit signatures. Refactored internals to eliminate duplicated range/single dispatch and unified JSON/text output with newssh_valid,chain_valid,chain_report,witness_quorum, andwarningsfields. Extracted sharedparse_witness_keys()helper intoverify_helpersmodule. - auths-verifier: Replace
revoked: boolwithrevoked_at: Option<DateTime<Utc>>onAttestation— enables time-aware revocation checks ("was this attestation valid at time T?") for audit and compliance.None= active,Some(t)= revoked at timet. Addsis_revoked()helper. Propagated across all crates, SQLite index, Go bindings, CLI, and registry server. - auths-verifier:
verify_with_keys_at()now performs time-aware revocation — attestations revoked after the reference time are still considered valid at that point. - auths-verifier:
is_device_listed()now requires&[VerifiedAttestation]instead of&[Attestation]— enforces signature verification at the type level. - auths-verifier: Remove deprecated
is_device_authorized()from Rust, Go, Python, and Swift bindings. - auths-registry-server: Wire org management endpoints (
add_member,revoke_member,update_capabilities) to real storage with Ed25519 signature verification and admin authorization. - auths-verifier: Add witness receipt verification with k-of-n quorum support, FFI/WASM bindings, and CLI
--witness-receiptsflags.
- GitHub Action:
getAuthsDownloadUrl()now returns correct release asset URLs.
-
auths-policy: Replace non-cryptographic
DefaultHasher(SipHash) withblake3for policy source hashing. The previous implementation usedstd::collections::hash_map::DefaultHasherwith a comment acknowledging it was a placeholder. Policy hashes are now computed withblake3::hash(), a cryptographic hash function. -
auths-core (witness): Fix receipt SAID computation to use proper Blake3 hash instead of a truncated string slice (
format!("E{}", &event_said[1..].chars().take(20)...)). Receipts now compute SAID viacompute_said()over the canonical signing payload and sign that payload rather than aformat!("{}:{}:{}", ...)string. -
auths-core (witness): Add event verification to
submit_eventhandler. The witness server previously issued receipts for any submitted event without validation. Now verifies:- SAID integrity (zeroes
dfield, recomputes Blake3 hash, compares) - Structural requirements (required fields per event type)
- Signature format (
xfield must be valid hex encoding 64 bytes) - Inception self-signature (Ed25519 verification of
k[0]over the event)
- SAID integrity (zeroes
-
auths-registry-server: Add real Ed25519 signature verification for authenticated API requests. The
VerifiedSignatureextractor (renamed toSignatureHeaders) previously extracted headers but had a TODO where verification should occur. Addedverify_request_signature(headers, body)which decodes hex public key and signature, validates timestamp within a 300-second window, constructs the signing payload, and verifies viaring::signature::UnparsedPublicKey. -
auths-cli: Remove fake success messages from emergency commands.
revoke-devicenow callscreate_signed_revocation()and exports viaAttestationSink.rotate-nownow callsrotate_keri_identity().freezenow returns an honest error stating the feature is not yet implemented, instead of printing a fake "Identity frozen" success message.
- auths-registry-server:
ringmoved from dev-dependencies to dependencies. - auths-registry-server:
VerifiedSignaturerenamed toSignatureHeaders; a type alias preserves backward compatibility. - auths-core (witness):
submit_eventhandler now acceptsJson<serde_json::Value>instead ofJson<SubmitEventRequest>to enable full-event validation. - auths-cli:
emergency revoke-devicenow requires--identity-key-alias(or interactive prompt).emergency rotate-nownow requires--current-aliasand--next-alias(or interactive prompts).
- auths-policy:
blake3dependency (1.5). - auths-registry-server:
verify_request_signature()public function for verifying Ed25519 request signatures with timestamp replay protection. - auths-core (witness):
verify_event_said(),validate_event_structure(),validate_signature_format(), andverify_inception_self_signature()functions.
These pre-release versions were yanked from crates.io.