1.2.x
1.2.0
Compare: https://github.com/walt-id/waltid-identity-enterprise/compare/v1.1.1...v1.2.0Release date: 2026-10-14 (UTC)
Highlights
- Added OpenID4VCI key attestation on Issuer2. A credential configuration can accept a key attestation inside a JWT proof, or a standalone attestation proof, and can require one. Trust is a public JWK, an X.509 CA, or a KMS verification key.
- Added Wallet2 batch issuance. One receive call can select offered credential configurations and request several copies, each bound to its own holder key. A single binding remains the default.
- Added per-issuer mandatory PAR. Set
requirePushedAuthorizationRequeststo require the pushed authorization endpoint. The default staysfalse. - Let one
signedMetadataconfiguration sign Credential Issuer metadata and OAuth authorization server metadata, with a JWK or anx5ccertificate chain. Omitting it still signs withtokenKeyId. - Added maintenance mode for an organization or tenant. It is off unless the
maintenancefeature is enabled. - Tightened credential status: Token Status List
ttlis configurable, Verifier2 caches a list for that lifetime, and a status update after rollover uses the list that holds the index.
Features
Issuer2 key attestation
- JWT proofs can carry
key_attestationin the protected header. The holder signature is checked, the attestation is checked against issuer trust, and the proof key must be one of the attested keys. - Standalone
proofs.attestationis a key-attestation JWT. It uses the samekeyAttestationConfigand does not replace OAuth client attestation. - Set
key_attestations_requiredon the JWT proof type to require an attestation. Leave it unset to keep attestation optional. keyAttestationConfig.verificationMethodacceptsstatic-jwk,x509-chain, orkey-reference.
Wallet2 batch issuance
POST /v2/{target}/wallet-service-api/credentials/receive/resolve-offer/batchreturns the offer and the issuerbatchSize.- Pre-authorized and authorization-code receive, and the isolated REST steps, accept
credentialswith explicit holder bindings. - Copies of one target go out as one Credential Request with several
proofs.jwt. Different configurations or datasets stay separate requests. - Omitting
credentialsstill receives every granted target once. Deferred results and partial progress are unchanged.
Mandatory Pushed Authorization Requests
- Service create and configuration update accept
requirePushedAuthorizationRequests. Discovery advertises it asrequire_pushed_authorization_requests. - When it is
true, the wallet posts the authorization parameters to the pushed authorization endpoint, then opens the authorization endpoint withclient_idandrequest_uri. A direct authorization request isinvalid_request. - The default is
false, so existing issuers still allow both direct authorization and PAR. - External login uses the authorization request that PAR accepted.
Signed issuer and authorization-server metadata
signedMetadataselects the signing key for Credential Issuer metadata: inline JWK, inline PEM key plus certificate chain, or a KMS key reference. A KMS reference can attachx5ccertificates from the X.509 store.- The same object signs OAuth authorization server metadata.
- When
signedMetadatais omitted, Issuer2 keeps signing withtokenKeyIdand publishes the publicjwk. - Clients still choose JSON or JWT with
Accept.
Maintenance mode
- Enable the
maintenancefeature, then restart. With the feature off, the routes are not registered. POST /v1/{target}/organization-management-api/maintenance/enablefreezes writes for an organization, or for one tenant when the target is that tenant. The default window is 1 day and the maximum is 30 days. SendenabledFororenabledUntil, not both.- Writes from accounts that lack
organization-management-maintenance-overrideare refused. Theallpermission includes that override, so a default organization admin keeps writing until the override is denied on their role. - Ending maintenance is allowed during the window. Other pods pick up the change within 5 seconds.
Credential status lifetime and rollover
- IETF Token Status List configuration accepts
ttlin seconds. The published token uses that value, and S3, Azure Blob, and Google Cloud Storage objects sendCache-Control: public, max-age=<ttl>. Omittedttlstays 43200 (12 hours). - Verifier2 reuses a downloaded status list until
Cache-Control: max-ageelapses. - Creating a status entry returns
statusListRef, the list that holds the new index. After automatic rollover that can be a versioned list. Later index updates must use that list. Session updates can still name the original configuration. - Enterprise issuance strips
statusListRefout of credential data before signing.
Licensing
- A license can keep a chosen credential lifetime. Online licenses are 4 to 14 days. Offline licenses are 1 to 365 days. The same interval is used for the first credential and each renewal. Leaving it blank keeps the server default of 4 days.
- The license admin UI can unbind an installation. Unbinding lets another deployment activate the license. An offline bundle stays valid until it expires, and cumulative usage totals reset. License type can be edited only while no installation is bound.
Default requests
- A stored default is applied when the target is an entry under the service, such as a certificate id on X.509 create or upsert. Previously only a target that was the service itself picked up the default.
- A Wallet2 receive default may store the holder key and DID without an offer. The offer is still required on the receive call.
Administration
- Listing tenant accounts checks that the tenant path is inside the authenticated organization.
- The admin organization list honors the advertised pagination parameters and rejects invalid ones.
- Organization and tenant configuration updates validate organization ids and DID registry references and return the documented errors.
Fixes and improvements
- Wallet2 pre-authorized receive on DocumentDB no longer fails with a storage error after the issuer has already returned the credential.
- Concurrent receives into one Wallet2 wallet retry a contended credential write instead of failing the issuance that already succeeded.
- A presentation is signed with the holder key the credential was issued to. A different key is rejected before it is sent.
- Revoking or reading a status index after auto-rollover updates the list that holds that index, not the base list that allocated earlier entries.
- Verifier2 accepts an external IETF status list whose
x5cleaf matches the credential. Lists hosted by this deployment stay additionally allowed. - Issuer2 credential responses, including failures before the response writer, send
Cache-Control: no-store. - Deleting an organization also removes its host aliases, role entries on accounts, events, and Issuer2 OAuth state. The accounts remain. The eIDAS audit chain is kept.
- Assigning a role to a user or API key requires every permission that role grants. Removing a deny rule requires the permission it withheld. Removing a grant does not.
- Wallet2 receive defaults
clientIdto the same wallet client id the wallet library uses, so an authorization-code exchange no longer fails with a client mismatch. - Issuer2 OpenAPI examples match the request bodies the API accepts.
- The Enterprise UI updates Vue to 3.5.42 and
source-map-jsto 1.2.2 for the advisory in the Vue server renderer. - Database profile fields that the API never read are marked unused, and a migration scheduling bug found while documenting PostgreSQL is fixed. Profile behavior is otherwise unchanged.
Breaking changes
None
Last updated on October 14, 2026
