Skip to content

Release Notes 3.2.0

Release: 3.2.0
Date: 2026-10-15
Type: generally available release
Upgrades from: 3.1.0


Overview

3.2.0 makes key rotation automatic and durable — on a schedule and, for capped keys, on usage — adds a platform log search for operators, completes the audit views of the console, and corrects the issues found on 3.1.0. It is the first release that upgrades an installed one in place.


New

Scheduled key rotation on a durable scheduler

  • Time-based key rotation runs on a dedicated scheduling service. A due rotation survives restarts and outages: it is claimed once, retried with backoff and reconciled, so it runs exactly once and is never lost.
  • Each rotation re-checks the key before it acts, records its cause, and sets the next due date.
  • Rotation intervals accept hours and minutes (ISO 8601 durations such as P1DT12H). The shortest interval a deployment admits is one day by default.
  • In the console a tenant administrator sees each key's next rotation beside its expiry and as a list column, the cause of every key version, and a Rotation schedule tab with the schedule, its executions and Rotate now. A platform administrator can read one tenant's schedules and executions.
  • New operations: listTenantSchedules, listTenantScheduleExecutions, listPlatformTenantSchedules and listPlatformTenantScheduleExecutions, with the read scopes scheduling.tenant.schedules.read and scheduling.platform.schedules.read.

Usage-based rotation

  • A key with a usage limit raises an alert when it reaches its soft usage limit and when it exhausts its usage limit: a signed audit event (admin.key-usage.soft-limit-reached, admin.key-usage.exhausted), forwarded to SIEM destinations with severity 5 and 8, and an e-mail to every member of the tenant who may write the key's rotation schedule. Lowering a soft limit to or below the current usage count is a crossing too.
  • Two per-key options on the rotation schedule, rotateOnSoftUsageLimit and rotateOnUsageExhaustion, rotate the key automatically at the soft limit or when the limit is exhausted; the new key version records the cause USAGE_THRESHOLD or USAGE_EXHAUSTED. Each crossing is detected once per key version and limit value, and the first trigger — time, manual or usage — wins. After a usage rotation, the time schedule counts from the new version.
  • Without the option, an exhausted key keeps refusing encryption and signing, keeps decrypting and verifying, and is rotated by its time schedule or manually.
  • The console's key drawer shows both options in its Automatic rotation section, and the Lineage tab names the two new causes. The schedule view reports usageRotationAvailable, and inheritedInterval: the interval a key would follow without one of its own, so the drawer lets a key return to it.
  • In that section the Rotate this key automatically switch governs the triggers: while it is off they are kept and paused, it can always be turned on (with no trigger it asks for one and saves nothing until one is chosen), and turning off the last trigger turns automatic rotation off.
  • A click anywhere on a row of the key inventory opens that key's details.
  • Platform operators search the logs of every platform service and infrastructure component from the console, with deep links from System Health, alert details and the correlation trace. Searches are bounded and audited; the scope is admin.platform.logs.read.
  • Service logs are structured JSON, one object per line, and infrastructure components are stored under their service names.
  • A platform alert, log.ingest.stalled, reports when log ingestion stops.
  • Logs can be exported over OpenTelemetry beside metrics and traces.
  • The log store runs with least-privilege accounts, and its passwords are platform secrets.

Audit views in the console

  • Applications show the cryptographic activity of each application.
  • Exchange contexts and constraint policies show their own activity; a constraint policy lists the grants that use it.
  • An actor's Activity tab shows its audit timeline, with All, Administration and Usage views.
  • The exchange topology panel opens the exchange context, shows its constraint policy and the signed constraint evaluations, names the actor of each audit row, and links each actor to its detail.
  • References show names and open the canonical detail of the entity, instead of bare identifiers.
  • New scope audit.tenant.application.read, held by the Tenant Administrator and Tenant Auditor roles, reads an application's cryptographic activity (GET /api/v3/audit/tenants/{tenantId}/applications/{applicationId}, operation listApplicationCryptoEvents). The Applications Crypto Activity view uses it, and the Intelligence Hub question TRBL-005 now returns an answer.

Complete application, actor, exchange-context and grant screens

  • The application record. listApplications (each row), getApplication, createApplication and updateApplication return one schema, ApplicationResponse: the application as stored, with its business, ownership, contact and risk members — description, environment, businessUnit, costCenter, ownerName, ownerEmail, technicalContactName, technicalContactEmail, dataClassification, riskLevel, regulatoryScope, tags and externalRefs — present on every record, null or empty when not entered. defaultActorId is on the createApplication response only.
  • Tenant-wide application counts. New operation getApplicationStatistics (GET /api/v3/admin/tenants/{tenantId}/applications/statistics, scope admin.tenant.application.list) returns totalApplications, activeApplications and applicationsWithValidCredential. The last counts applications with at least one credential that is not deleted, not revoked and inside its validity window, on an actor that is not deleted; federated issuer bindings are not counted.
  • Capability grants carry updatedAt, the time of the grant's last change.
  • regulatoryScope entries are validated. On createApplication and updateApplication, each entry must be 1 to 100 characters and not blank, with at most 50 entries. A request with an empty, blank, null or longer entry is refused with 400 problem+json naming regulatoryScope[i], and nothing is written.
  • In the console, an application's Info tab shows the full record, including owner and technical contact e-mail addresses, tags and external references, and the three tiles above the list — Total Applications, Active and With Credentials — count the whole tenant. Against an older platform server, a value it does not send reads "not provided by this server".
  • Actors, exchange contexts and capability grants show when they were last Updated. Exchange contexts show their counterparty type in the list and on Info, and the Edit tab sets or removes it.
  • Constraint policies state each condition in the same words in the list and in the detail.
  • Every key of a capability grant opens its own detail; a re-encryption or re-signing grant opens its source key and its target key.

Changed

  • Compliance remediation shows what ran. After a step is confirmed, the dialog shows whether it completed, stopped or is still running, the outcome and new expiry of each key, and the recomputed compliance status. The execution names who requested it. Rotation and a successor key are presented as alternatives, and creating a successor for a key that can be rotated is refused with compliance-remediation-rotation-admissible.
  • Projection republish reports its progress. republishPlatformProjection returns the pass it started, and the new getPlatformProjectionRepublishPass and listPlatformProjectionRepublishPasses report each pass as RUNNING, SUCCEEDED or FAILED with per-unit outcomes.
  • SDK clients tolerate newer servers. The Java SDK and the Admin SDK ignore response members they do not declare, and their public enumerations include UNKNOWN, so a value a newer server adds is read as UNKNOWN instead of failing the response.
  • SDKs redact secrets in toString, validation messages, exceptions and debug logs, including the PQC session and usage-export headers. The toString output of the SDK models has a new, redacted format; code must not parse it.
  • Java SDK TokenResponse: passwordChangeEligible can be null — a token-exchange response does not carry it — and two members are added for that grant, issuedTokenType and scope (RFC 8693). Code that reads passwordChangeEligible handles the null case.
  • A token-exchange response omits refresh_token instead of returning it as null.
  • Derived soft usage limit. A key created or imported with a usage limit and no soft limit gets 80 % of the limit, rounded down, and never a soft limit equal to the limit itself.
  • Usage accounting can refuse a protect operation. Once the upgrade is finalized, an encryption or signing operation on a capped key whose usage cannot be recorded is refused with 503 usage-accounting-unavailable and Retry-After, and nothing is counted.
  • Control-plane audit reads return a declared page. listActorCryptoEvents, listApplicationCryptoEvents, listExchangeContextCryptoEvents, listCounterpartyCryptoEvents and listConstraintViolations return a CryptoAuditLogPage with the members content, totalElements, totalPages, number, size, first, last, numberOfElements and empty. The response no longer carries the pageable and sort members.
  • The crypto CLI fat JAR needs its lib/ directory. ankasecure-cli-crypto-3.2.0-fat.jar loads Bouncy Castle from lib/bcprov-jdk18on.jar, lib/bcutil-jdk18on.jar and lib/bcpkix-jdk18on.jar beside it. Every installer lays them out that way. A script or container image that copies the fat JAR alone must copy lib/ with it.
  • Classic McEliece is LEGACY. BSI now advises that Classic McEliece should no longer be used for new developments or in the planning of new cryptographic applications; results so far allow no practical attack on its parameter sets. CMCE-460896 and CMCE-6688128 are LEGACY, with no sunset date, and are attributed to ISO alone: ISO/IEC 18033-2:2006/Amd 2:2026 standardises them. Catalogue reads filtered on status=RECOMMENDED or standards=BSI no longer return them.
  • Existing Classic McEliece keys keep working. Encryption, decryption, re-encryption from such a key and rotation away from it are unaffected. Under BSI_COMPLIANT, creating, importing or rotating to a Classic McEliece key is refused with 400 algorithm-not-admitted; GLOBAL_ISO_COMPLIANT still admits it.
  • BSI compliance pack 2026-10-15. BSI_TR_02102_1 cites BSI's TR-02102 page beside TR-02102-1 and reports Classic McEliece keys under the new SHOULD_NOT control BSI.NOT-RECOMMENDED.CLASSIC-MCELIECE, which replaces its admission. BSI.HYBRID.KEM names ML-KEM-768, ML-KEM-1024, FRODO-976 and FRODO-1344, and the pack lists no Classic McEliece set as not offered. A remediation plan recorded on an earlier version is read on the current pack.
  • The BSI_COMPLIANT policy template no longer declares Classic McEliece. Its families are ML-KEM, ML-DSA, SLH-DSA, FRODO, RSA, EC and oct (template version 1.1). On an upgraded installation the template row changes at upgrade finalize; a fresh installation has it from the start. The refusal applies from the upgrade on, because no Classic McEliece set carries BSI. A policy already created from the template keeps its own copy, and its BSI standard refuses Classic McEliece on its own.
  • FrodoKEM carries the ISO attribution. FRODO-976 and FRODO-1344 are attributed to BSI, ANSSI, ENISA and ISO, so FINANCE_COMPLIANT (NIST or ISO, levels 3 and 5) now admits them, as does any policy that mandates ISO without restricting families.
  • The compliance CBOM carries FrodoKEM and Classic McEliece OIDs from the ISO/IEC 18033-2 arc: 1.0.18033.2.2.7.5, 1.0.18033.2.2.7.6, 1.0.18033.2.2.6.1 and 1.0.18033.2.2.6.5.
  • The PQC handshake admits exactly the KEMs it lists. GET /api/v3/pqc-handshake/supported-algorithms and POST /api/v3/pqc-handshake/init share one set: by default ML-KEM-512, ML-KEM-768, ML-KEM-1024, HQC-128, HQC-192, HQC-256, FRODO-976 and FRODO-1344, plus the experimental KEMs when pqc.handshake.allow-experimental-kem is true. Classic McEliece is refused with 400 invalid-input. clientPublicKeyBase64 accepts at most 29,000 characters, which admits the largest key of an admitted KEM (FrodoKEM-1344); a longer value is 400 validation.
  • PQC transport offers HQC and FrodoKEM. In the Java SDK and the crypto CLI, pqc.kem.algorithm now accepts ML-KEM-512, ML-KEM-768 (default), ML-KEM-1024, HQC-128, HQC-192, HQC-256, FRODO-976 and FRODO-1344. Before, only ML-KEM worked from the client. Classic McEliece is not offered, because the BSI advises against it for new developments. view-session shows the KEM in use.

  • Key creation and import refusals. Creating a key whose expiry is not after its creation is refused with HTTP 400. Importing a key, or analysing a keystore entry, whose algorithm or curve cannot be determined is refused with HTTP 400. An interoperability operation refuses a caller key of another parameter set than the one it names. Re-importing a key that a tenant's minimum security level or hybrid requirement excludes is refused; keys already stored are not re-evaluated.


Fixed

  • The crypto CLI's PQC transport works on an Oracle JDK. Running the fat JAR (java -jar ankasecure-cli-crypto-3.2.0-fat.jar) on an Oracle JDK used to make every KEM fail with "JCE cannot authenticate the provider BC", because the JAR carried Bouncy Castle without its signature. Bouncy Castle now ships unmodified, with its signature, in a lib/ directory beside the fat JAR, and the JAR loads it from there. The installed AnkaSecureCLI launcher was not affected.
  • The key history of a tenant with few audit records no longer times out (HTTP 504) when that tenant shares an audit storage partition with a tenant that has many records.
  • When an operation is denied on a key that cannot be resolved, the audit record no longer carries that reference as the key identifier; it records it as the requested key identifier.
  • A key lifecycle operation refused by policy is recorded in the audit trail as DENIED, not FAILURE.
  • SM2 keys are rebuilt correctly. Rebuilding an SM2 public or private key, for example to verify with a caller-supplied SM2 key, failed because the key factory was requested by the name SM2; it is now requested as EC. A test rebuilds the keys of every asymmetric algorithm in the catalogue.
  • An imported elliptic-curve key is identified by its full curve parameters. An import whose curve could not be identified was recorded as P-256 (a secp256k1 key, for example). It is now identified exactly or refused with HTTP 400, and a stored key is used only as the algorithm recorded for it.

Security

  • Audit reads return the signed change set of an administrative event, never the whole stored event.
  • Fields that name a principal are withheld from audited change sets by a vocabulary defined for each entity type, the creator of a linked account is withheld from tenant readers, and a resource read discloses only principals of the same tenant.
  • A change made during a support session is attributed to the acting platform operator, not to the tenant user: the administration service records the acting principal (act.sub) on the administrative changes made under impersonation.
  • A tenant membership records the plane, tenant or platform, of the account that created it.
  • Setting values are published as sensitive, so generated clients redact them.
  • Service logs never carry a query string: the usage log records the referring page as scheme, host and path, the audit service logs its request filter at INFO, and the host edge proxy logs request and referrer paths only.
  • Every key import applies the tenant's minimum security level and hybrid requirement, as key creation does, and a key whose permitted operations are empty is refused for every operation.

Breaking changes

  • Admin SDK: republishPlatformProjection, republishPlatformProjectionWithHttpInfo and republishPlatformProjectionAsync return ProjectionRepublishAcceptedResponse (members status, projection and passId) instead of Object. Code calling them must be recompiled against the 3.2.0 Admin SDK.
  • Admin SDK, generated client: CapabilityGrantsApi.listCapabilityGrants and its WithHttpInfo, Async and Call variants take a new positional UUID constraintPolicyId argument between exchangeContextId and page. Callers compiled against 3.1.0 add the argument; null applies no filter. The curated Admin SDK facade is unchanged.
  • Admin SDK, generated client, applications: TenantApplicationsApi.listApplications returns PageApplicationResponse, and getApplication, createApplication and updateApplication return ApplicationResponse, instead of PagePrincipalDetailsResponse and PrincipalDetailsResponse; their WithHttpInfo, Async and Call variants change with them. PagePrincipalDetailsResponse is removed, and PrincipalDetailsResponse no longer has defaultActorId. Code that uses these generated types is recompiled against the 3.2.0 Admin SDK. The curated facade is unchanged: ApplicationOperations.listApplications and createApplication keep their signatures and return the same values.
  • Java SDK, PQC transport: code compiled against 3.1.0 that uses these types must be recompiled and adapted:
    • PqcSessionManager takes (AnkaSecureOpenApiClient, PqcTransportConfig). The KEM comes from PqcTransportConfig.getKemAlgorithm(), and the three-argument constructor is removed.
    • AsymmetricAlgorithmRegistry.AsymmetricAlgorithmSpec has the components name, keyGenAlgorithm, provider and keyGenParameters. originalName is removed, and findSpec accepts only the eight transport KEMs listed by PqcTransportConfig.supportedKemAlgorithms().
    • The constant AsymmetricAlgorithmRegistry.BC_PROVIDER is removed.
  • Java SDK and crypto CLI, pqc.kem.algorithm: with pqc.transport.enabled=true, a KEM outside the supported set is refused when the client is built (InvalidInputException naming the supported set, from new AnkaSecureSdk(...)). Before, it failed at the first request. A configuration naming a KEM other than ML-KEM must name one of the eight.

Known issues

  • During a support session, four compliance and policy records still name the tenant user as the actor instead of the acting platform operator: the tenant policy override flag, a compliance workflow update, the requester of a remediation execution and the creator of an attestation. The operator is recorded in the signed audit trail of each change. The correction is planned for 3.3.0.

Upgrade notes

  • Supported path: 3.1.0 → 3.2.0, in place: envctl.sh <env> upgrade plan, then apply, then finalize. apply takes a backup, applies the schema migrations, deploys the release images by digest and rolls back automatically on failure. The release can be rolled back until finalize runs.
  • Deployment order: upgrade apply migrates the schema before it deploys the services. An operator who deploys services individually deploys the schema migrator first, then the administration service, then the console.
  • Upgrade the clients with the server. Admin SDK and Admin CLI 3.1.x refuse response members they do not declare, and 3.2.0 adds members to remediation plans and executions, to key responses, to application records (the business, ownership, contact and risk members) and to capability grants (updatedAt). Move both to 3.2.0 when the platform is upgraded. From 3.2.0 on, the SDKs ignore undeclared members.
  • Features that start at finalize: sub-day rotation intervals (refused with rotation-interval-format-not-finalized until then) and usage-based rotation are enabled once the upgrade is finalized. finalize also applies the schema changes that 3.1.0 could not run with, which is why a rollback is possible only before it.
  • New secrets for the scheduling service and the log store are created by upgrade apply.
  • Install this release's host edge manager on every host before creating or upgrading an environment: sudo install -m 0755 /opt/ankatech/admin/edge-nginx-manager.sh /usr/local/bin/edge-nginx-manager.sh, then sudo edge-nginx-manager.sh init and reload the edge NGINX, so the edge logs paths only. create-env.sh refuses to run while the host copy differs.
  • Backup before apply: the mandatory backup needs an offline escrow recipient declared at /etc/ankatech/.ankasecure-backup-escrow-key. Without one apply changes nothing; --skip-backup proceeds without the backup.
  • Log store: durationMs is mapped as a number from this release on. upgrade apply rolls the write index over once, so earlier indices keep it as text until retention removes them; a direct OpenSearch query that sorts or aggregates durationMs across them returns partial results.
  • New optional setting ROTATION_SCHEDULE_MINIMUM_INTERVAL: leave it empty in production (one day).
  • No new images and no third-party version changes. Apache Kafka stays at 4.2.2: the 4.3 line carries an upstream defect that can stall transactions after a broker restart.