Skip to content

CAMEL-25797: camel-pqc - the usage-count and PENDING_ROTATION key rotation signals now fire - #28094

Merged
davsclaus merged 4 commits into
apache:mainfrom
oscerd:fix/CAMEL-25797-pqc-rotation-signals
Oct 21, 2026
Merged

davsclaus merged 4 commits into
apache:mainfrom
oscerd:fix/CAMEL-25797-pqc-rotation-signals

Conversation

@oscerd

@oscerd oscerd commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Fixes CAMEL-25797.

KeyRotationScheduler documents three rotation signals — key age, usage count, and a PENDING_ROTATION status. Two
of the three could never trigger.

1. usageCount was only advanced for stateful keys

KeyMetadata.updateLastUsed() is the only thing that increments the counter, and its single production caller sat
inside persistStatefulKeyStateAfterSign() behind:

long remaining = getStatefulKeyRemaining(privateKey);
if (remaining < 0) {
    // Not a stateful key
    return;
}

So for ML-DSA, SLH-DSA, Falcon and every KEM key — the overwhelming majority — the counter stayed at 0 forever,
while all five lifecycle managers gate on maxUsage > 0 && metadata.getUsageCount() >= maxUsage.
setMaxKeyUsage and the documented camel.component.pqc.key-rotation-max-usage property were inert.

The method is now recordKeyUsageAfterSign(). It advances and persists the usage count for every key, and
re-stores the key pair itself only for the stateful algorithms, where the advanced one-time index has to survive a
restart. That also drops a redundant remote write per signature for non-stateful keys — they previously did a
storeKey only in the stateful branch, so this strictly reduces traffic relative to what stateful keys already do
while finally recording usage for the rest.

2. PENDING_ROTATION was filtered out before it was read

private Predicate<KeyMetadata> keyFilter = metadata -> metadata.getStatus() == KeyMetadata.KeyStatus.ACTIVE;

KeyMetadata.needsRotation() does test for PENDING_ROTATION, but a key marked that way is no longer ACTIVE, so
the scheduler continued past it at the filter before needsRotation() was ever consulted. Only nextRotationAt on
an otherwise-ACTIVE key actually worked.

The default filter now accepts ACTIVE and PENDING_ROTATION. A filter supplied via setKeyFilter is unaffected.
Javadoc on the class and on setKeyFilter updated to match.

3. A failed metadata read failed the exchange (review follow-up)

Recording the usage reads the key metadata before it writes it. The write was already guarded for a non-stateful
key - losing a usage count only delays a rotation - but the getKeyMetadata read was not, so a vault that could not be
read failed the exchange although the signature was fine. The read is now treated like the write: logged once per
producer (shared warnUsageRecordFailure), signature kept. A stateful key still fails the exchange, as its advanced
index must be persisted. The lifecycle page and the upgrade-guide note say "read or write".

Tests

New KeyRotationSignalsTest:

  • signingAStatelessKeyAdvancesTheUsageCount — three ML-DSA signatures, asserts the count reaches 3 and that
    needsRotation(.., maxUsage=3) then reports true;
  • aPendingRotationKeyIsSelectedByTheDefaultFilter — asserts the default filter accepts the key and that
    checkAndRotate() actually rotates it.
  • aFailedMetadataReadKeepsTheSignatureOfAStatelessKey — an in-memory manager whose reads can be made to fail;
    the exchange reaches the mock with its signature and the usage count stays at zero. It uses an endpoint with
    strictKeyLifecycle=false: the key status check before signing is a deliberate fail-closed read of the same
    metadata, so with it off the usage read is the exchange's only vault read.

Against main: expected: <3> but was: <0> and expected: <true> but was: <false>. Full camel-pqc build green:
241 tests, 0 failures, no regenerated-file drift.

Scope note

Usage is recorded on the signing paths, which are the ones that already had the hook. A pure-KEM deployment still
will not advance usageCount; extending the hook to the KEM operations is a larger behavioural change and is better
done separately if wanted.

Upgrade guide

Added a 4.24 entry. This makes previously-inert configuration take effect, so a deployment that already set
maxKeyUsage may rotate on the first check once the counter starts moving — worth flagging before upgrade.


Reported, analysed and fixed by Claude Code (AI agent) on behalf of @oscerd.

🤖 Generated with Claude Code

@oscerd
oscerd requested review from davsclaus and gnodet October 19, 2026 09:40

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two issues, both in PQCProducer.java.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @oscerd, both fixes are right: usageCount now moves for every signing key, and a PENDING_ROTATION key reaches needsRotation(). All five managers mark the old key DEPRECATED on rotation, so the wider default filter cannot rotate the same key twice. Both gnodet-bot threads are fixed, and I resolved them.

Two things to change:

  1. A vault write per signature for the stateless keys. The description says this reduces traffic, but for ML-DSA, SLH-DSA and Falcon it adds writes where there were none. In the AWS Secrets Manager, HashiCorp Vault and Azure Key Vault managers, updateKeyMetadata is getKey + storeKey, which rewrites the private key, public key and metadata secrets: three new secret versions per signature. A route that signs at volume with a keyLifecycleManager and CamelPQCKeyId now writes to the vault three times per message, and a vault error now fails an exchange that signed fine before.

    • Please say this in the upgrade-guide entry.
    • For a stateless key, consider logging (once) instead of failing the exchange when recording the usage fails. A missed count only delays a rotation; a lost stateful index is a different matter.
    • For the stateful keys, storeKey already writes the metadata in every manager, so the updateKeyMetadata before it is a redundant round (six secret writes per signature today). Calling only storeKey there would halve that.
  2. Docs. The "Automated Rotation Scheduling" section of pqc-key-lifecycle.adoc still says the scheduler keeps "by default only ACTIVE keys". Please update it, and its copy in catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/. Please also say there that maxKeyUsage counts signing operations only, and only when a keyLifecycleManager is configured and the exchange has the CamelPQCKeyId header.

Non-blocking:

  • The usage is recorded on the key named by the CamelPQCKeyId header, not on the key that signed. In KeyRotationSignalsTest the producer signs with the default ML-DSA material, and the count goes to signing-key, which never signed. The stateful path already worked this way. A test that signs with the generated key (set as the endpoint keyPair) would show the intended setup.
  • updateLastUsed() is a plain usageCount++ on the metadata object the managers cache, so concurrent exchanges can lose increments. That's fine for a threshold, but a comment would help.

CI is still running on 24365a4.

Claude Code on behalf of Claus Ibsen

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following up on my earlier review — both findings have been addressed.

✅ Inaccurate KEM Javadoc — fixed in 24365a4. The recordKeyUsageAfterSign Javadoc now explicitly states that KEM operations do not call this method and do not advance the usage count.

✅ Stale error message — fixed in 24365a4. The catch block now says "Failed to record key usage after hybrid signing".

All davsclaus blocking items are also addressed in af51b2f:

  • Upgrade guide and the IMPORTANT adoc block both document that non-stateful signing now writes to the backing store on every signature, and advise using maxKeyAge/nextRotationAt on high-volume routes against remote vaults.
  • Stateful path now calls only storeKey (eliminating the redundant updateKeyMetadata call that would have doubled remote writes).
  • Non-stateful updateKeyMetadata failures are swallowed with a once-per-producer LOG.warn via AtomicBoolean — the exchange is not failed.
  • Both adoc files (source and generated) updated identically.
  • KeyMetadata.updateLastUsed() has a concurrency Javadoc explaining the non-atomicity is accepted.

The slf4j format string, PENDING_ROTATION filter widening, and test key alignment are all correct. No new issues introduced by the latest commits.

LGTM.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@oscerd

oscerd commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @davsclaus — all four points addressed in af51b2f.

The write cost. You are right and my description had it backwards: for ML-DSA, SLH-DSA and Falcon this adds writes where there were none. Three changes follow.

  • For a stateful key, storeKey already writes the metadata entry in every manager, so the updateKeyMetadata before it was a second round trip for the same data. Only storeKey is called now — three secret writes per signature instead of six.
  • For a non-stateful key a failed usage record no longer fails the exchange. It is logged once per producer and the signature is returned, since a lost count only delays a rotation.
  • The upgrade guide now states the per-signature write, that it is a remote call against AWS/Azure/Vault, that a failure does not fail the exchange for a non-stateful key, and how to avoid it.

Docs. pqc-key-lifecycle.adoc now describes the widened default filter, and an IMPORTANT block says that maxKeyUsage counts signing operations only, needs a keyLifecycleManager and a CamelPQCKeyId header, is recorded against the key named by that header, never fires for a KEM key, and costs a write per signature. Catalog copy updated.

Non-blocking, both done. KeyRotationSignalsTest now signs with the very key pair it counts, instead of signing with the autowired default while counting a different id. updateLastUsed() carries a note that the increment is not atomic and that the count is a threshold, not an audit figure.

Claude Code on behalf of @oscerd

@oscerd
oscerd requested a review from davsclaus October 19, 2026 13:40

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, af51b2f addresses all three points:

  • a stateful key now does one storeKey per signature and a non-stateful key one updateKeyMetadata, documented in the lifecycle page and the upgrade guide;
  • a failed usage write for a non-stateful key is logged once and the signature is kept;
  • the rotation docs now say the default filter keeps ACTIVE and PENDING_ROTATION keys.

Optional nit: the klm.getKeyMetadata(keyId) read before the branch is still outside that try. The vault managers cache the metadata, but on a cache miss a vault error on that read still fails the exchange for a non-stateful key. Moving the read inside the same guard for the non-stateful case would make it consistent.

Claude Code on behalf of Claus Ibsen

@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • catalog/camel-catalog
  • components/camel-pqc
  • docs

🔬 Scalpel shadow comparison — Scalpel: 8 of 707 tested, 25 compile-only — current: 8 all tested

Maveniverse Scalpel detected 8 affected modules (current approach: 8).

Skip-tests mode would test 8 modules (3 direct + 7 downstream), skip tests for 25 (generated code, meta-modules)

Modules Scalpel would test (8)
  • camel-jbang-mcp ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-mcp ← downstream of org.apache.camel:camel-jbang-core
  • camel-jbang-plugin-tui ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-validate ← downstream of org.apache.camel:camel-yaml-dsl-validator
  • camel-launcher-container ← downstream of org.apache.camel:camel-launcher
  • camel-pqc ← components/camel-pqc/src/main/docs/pqc-key-lifecycle.adoc, components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCProducer.java, components/camel-pqc/src/main/java/org/apache/camel/component/pqc/lifecycle/KeyMetadata.java, components/camel-pqc/src/main/java/org/apache/camel/component/pqc/lifecycle/KeyRotationScheduler.java, components/camel-pqc/src/test/java/org/apache/camel/component/pqc/lifecycle/KeyRotationSignalsTest.java
  • camel-yaml-dsl-validator ← downstream of org.apache.camel:camel-catalog
  • camel-yaml-dsl-validator-maven-plugin ← downstream of org.apache.camel:camel-yaml-dsl-validator
Modules with tests skipped (25)
  • apache-camel
  • camel-allcomponents
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

All tested modules (35 modules, 4m 59s total)

Total reactor time: 4m 59s

Module Duration Status
Camel :: JBang :: Plugin :: TUI 58.2s SUCCESS
Camel :: Launcher 31.2s SUCCESS
Camel :: Component DSL 26.7s SUCCESS
Camel :: JBang :: Plugin :: Validate 25.4s SUCCESS
Camel :: JBang :: MCP 22.3s SUCCESS
Camel :: YAML DSL 18.2s SUCCESS
Camel :: Catalog :: Camel Catalog 17.1s SUCCESS
Camel :: YAML DSL :: Validator 16.7s SUCCESS
Camel :: Docs 11.2s SUCCESS
Camel :: Kamelet Main 9.7s SUCCESS
Camel :: JBang :: Plugin :: Kubernetes 9.3s SUCCESS
Camel :: Catalog :: Camel Route Parser 6.7s SUCCESS
Camel :: YAML DSL :: Deserializers 6.7s SUCCESS
Camel :: Catalog :: Camel Report Maven Plugin 5.8s SUCCESS
Camel :: YAML DSL :: Validator Maven Plugin 5.7s SUCCESS
Camel :: JBang :: Plugin :: Testing 5.7s SUCCESS
Camel :: All Components Sync point 4.1s SUCCESS
Camel :: Catalog :: Suggest (deprecated) 2.6s SUCCESS
Camel :: YAML DSL :: Maven Plugins 2.5s SUCCESS
Camel :: Catalog :: Maven 2.3s SUCCESS
Camel :: JBang :: Integration tests 2.1s SUCCESS
Camel :: Assembly 1.3s SUCCESS
Camel :: Catalog :: Dummy Component 1.2s SUCCESS
Camel :: JBang :: Plugin :: Edit 1.1s SUCCESS
Camel :: JBang :: Plugin :: Generate 1.0s SUCCESS
Camel :: Coverage 0.9s SUCCESS
Camel :: Catalog :: Console 0.8s SUCCESS
Camel :: Endpoint DSL :: Support 0.7s SUCCESS
Camel :: JBang :: Main 0.6s SUCCESS
Camel :: Launcher :: Container 0.6s SUCCESS
Camel :: JBang :: Plugin :: MCP 0.4s SUCCESS
Camel :: Endpoint DSL n/a
Camel :: Integration Tests n/a
Camel :: JBang :: Core n/a
Camel :: PQC n/a

Top 20 slowest modules:

  • Camel :: JBang :: Plugin :: TUI (58.2s)
  • Camel :: Launcher (31.2s)
  • Camel :: Component DSL (26.7s)
  • Camel :: JBang :: Plugin :: Validate (25.4s)
  • Camel :: JBang :: MCP (22.3s)
  • Camel :: YAML DSL (18.2s)
  • Camel :: Catalog :: Camel Catalog (17.1s)
  • Camel :: YAML DSL :: Validator (16.7s)
  • Camel :: Docs (11.2s)
  • Camel :: Kamelet Main (9.7s)
  • Camel :: JBang :: Plugin :: Kubernetes (9.3s)
  • Camel :: Catalog :: Camel Route Parser (6.7s)
  • Camel :: YAML DSL :: Deserializers (6.7s)
  • Camel :: Catalog :: Camel Report Maven Plugin (5.8s)
  • Camel :: YAML DSL :: Validator Maven Plugin (5.7s)
  • Camel :: JBang :: Plugin :: Testing (5.7s)
  • Camel :: All Components Sync point (4.1s)
  • Camel :: Catalog :: Suggest (deprecated) (2.6s)
  • Camel :: YAML DSL :: Maven Plugins (2.5s)
  • Camel :: Catalog :: Maven (2.3s)

⚙️ View full build and test results

@oscerd

oscerd commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main and pushed one more commit.

  • Rebase. The only conflict was the 4.24 upgrade guide, where several camel-pqc PRs had added their note at the same spot. This note now sits before the camel-jbang - camel get endpoint shows the scope of an endpoint section, at a different place from the other open camel-pqc PRs, so they stop conflicting with each other.
  • Open point from the review of CAMEL-25796: camel-pqc - persist the stateful key index before the signature is published #28099. The klm.getKeyMetadata(keyId) read before the usage write was unguarded, so a vault that could not be read failed the exchange of a non-stateful key although only its usage count was at stake. The commit "CAMEL-25797: Address review feedback - a failed metadata read for a non-stateful key keeps the signature" treats the read like the write: logged once per producer (shared warnUsageRecordFailure), signature kept. A stateful key still fails the exchange, as its index must be persisted. KeyRotationSignalsTest.aFailedMetadataReadKeepsTheSignatureOfAStatelessKey covers it with an in-memory manager whose reads can be made to fail: the exchange reaches the mock with its signature, and the usage count stays at zero. That test goes through an endpoint with strictKeyLifecycle=false, because the key status check before signing is a deliberate fail-closed read of the same metadata; with it off, the usage read is the exchange's only vault read. The lifecycle page and the upgrade-guide note now say "read or write".

#28099 is rebased on top of this commit, so the fix reaches it too.

Verification: camel-pqc on JDK 21 (mvn clean install) and JDK 25 (mvn test: 277 tests, 0 failures); full reactor mvn clean install -DskipTests -DskipITs BUILD SUCCESS, no regenerated-file drift.

Claude Code on behalf of oscerd

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @oscerd, 71322b5 is right: a failed getKeyMetadata read for a non-stateful key is now caught like the failed write, the signature is kept, and a stateful key still fails. aFailedMetadataReadKeepsTheSignatureOfAStatelessKey covers it. Turning off strictKeyLifecycle in that test is the right way to reach the read. The lifecycle page and its catalog copy match.

One thing to fix before merge. The rebase put two paragraphs of the 4.24 upgrade guide in the wrong section. Recording the usage also costs a write. ... and The key encapsulation operations do not record usage ... now sit at the end of === camel-pqc - an unknown hybridKdfAlgorithm is rejected (lines 266-273), about 40 lines above this PR's own section === camel-pqc - the usage-count and PENDING_ROTATION key rotation signals now fire. Before the rebase they followed check once the counter starts advancing.. Readers of the hybridKdf note would now see them as part of it.

This also causes the only conflict left in the camel-pqc series. #28089 adds its note right after that hybridKdf section, so #28089 and this PR (and #28099, which carries these commits) conflict in the upgrade guide in either merge order. I checked with git merge-file: once the two paragraphs are moved back below check once the counter starts advancing., this PR merges cleanly with #28089 and with all the other camel-pqc PRs.

Claude Code on behalf of davsclaus. This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Comment thread docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc Outdated
oscerd and others added 4 commits October 21, 2026 10:55
…ation signals now fire

KeyRotationScheduler documents three rotation signals. Two of them could never trigger.

usageCount is advanced only by KeyMetadata.updateLastUsed(), whose single production
caller sat inside persistStatefulKeyStateAfterSign() behind an early return for any key
that is not XMSS/XMSSMT/LMS/HSS. For ML-DSA, SLH-DSA, Falcon and every KEM key the counter
therefore stayed at zero forever, while all five lifecycle managers gate rotation on
"maxUsage > 0 && metadata.getUsageCount() >= maxUsage". setMaxKeyUsage and the documented
camel.component.pqc.key-rotation-max-usage property were inert.

That method is now recordKeyUsageAfterSign(): it advances and persists the usage count for
every key, and only re-stores the key pair itself for the stateful algorithms, where the
advanced one-time index has to survive a restart. This also removes a redundant remote
write per signature for the non-stateful keys, which previously did neither.

The scheduler's default key filter accepted only ACTIVE keys, so a key an operator had
marked PENDING_ROTATION was skipped at the filter before needsRotation() - which does test
for PENDING_ROTATION - was ever consulted. The default now accepts ACTIVE and
PENDING_ROTATION; a filter supplied through setKeyFilter is unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
…and a stale message

The javadoc of recordKeyUsageAfterSign claimed the KEM keys were covered. They are
not: no key encapsulation path calls the method, so a KEM key still does not advance
its usage count and maxKeyUsage does not apply to it. Stating otherwise would mislead
an operator configuring rotation on a KEM key. The javadoc now says which keys are
covered and which are not.

The hybrid signing catch block still reported "Failed to persist stateful key state"
after the method was generalised from persisting stateful state to recording usage.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
…nd the rotation docs

Recording the usage of a non-stateful key writes to the backing store on every signature,
where such a key previously wrote nothing. The PR description had this backwards. Three
changes follow from it.

For a stateful key, storeKey already writes the metadata entry in every manager, so the
updateKeyMetadata call before it was a second round trip for the same data: six secret
writes per signature where three suffice. Only storeKey is called now.

For a non-stateful key, a failure to record the usage no longer fails the exchange. It is
logged once per producer and the signature is returned. A lost usage count only delays a
rotation, which is not worth discarding a good signature for; a lost stateful index is a
different matter and still fails.

The upgrade guide now states the per-signature write, that a failure of it does not fail
the exchange for a non-stateful key, and that the KEM operations never advance the count.

pqc-key-lifecycle.adoc still described the default key filter as ACTIVE only, and said
nothing about what maxKeyUsage actually counts. It now covers the widened filter, that
the count needs a keyLifecycleManager and a CamelPQCKeyId header, that it is recorded
against the key named by that header, that the KEM operations do not advance it, and that
it costs a remote write per signature. Catalog copy updated.

KeyRotationSignalsTest signed with the autowired default material while counting against
a different key id, so it did not show the intended setup. It now signs with the very key
pair it counts. updateLastUsed carries a note that the increment is not atomic.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
…on-stateful key keeps the signature

The metadata read before the usage write went to the keyLifecycleManager unguarded, so a vault that could not be read failed the exchange of a non-stateful key although only its usage count was at stake. The read is now treated like the write: logged once per producer, the signature is returned. A stateful key still fails, as its index must be persisted. KeyRotationSignalsTest covers the read failure with a manager whose reads can be made to fail.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
@oscerd
oscerd force-pushed the fix/CAMEL-25797-pqc-rotation-signals branch from 71322b5 to 0fd54fe Compare October 21, 2026 09:06
@oscerd

oscerd commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main (previous head 71322b5 → 0fd54fe), same four commits.

  • The only conflict was the 4.24 upgrade guide. The two paragraphs that the previous rebase had left at the end of the hybridKdfAlgorithm note (Recording the usage also costs a write. and The key encapsulation operations do not record usage) are back in this PR's section, after check once the counter starts advancing., as @davsclaus asked. That also removes the conflict with the merged CAMEL-25795: camel-pqc - stopping an endpoint no longer removes the Bouncy Castle providers from the JVM #28089.
  • Outside the upgrade guide the changed lines are byte-identical to the previous head.
  • camel-pqc module build with tests on JDK 21: 307 tests, 0 failures.

#28099, which is stacked on this branch, follows with the same rebase and its own nit fix.

Claude Code on behalf of oscerd

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Andrea, the open point is addressed. The two paragraphs on the cost of recording usage and on the KEM keys are back in this PR's own section camel-pqc - the usage-count and PENDING_ROTATION key rotation signals now fire, after check once the counter starts advancing., and the end of the hybridKdfAlgorithm note is no longer touched. A range-diff against the previous head (71322b5) shows the code, the test and the pqc-key-lifecycle.adoc changes are unchanged; only the upgrade-guide placement moved. The branch is rebased onto main including CAMEL-25798 (#28093), and merges cleanly. The catalog copy of pqc-key-lifecycle.adoc matches the component doc.

CI: the build jobs for the new head are still queued; LGTM once they are green.

This review covers project rules and conventions only. It does not replace CodeRabbit, Sourcery or SonarCloud.

Claude Code on behalf of Claus Ibsen

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

@davsclaus davsclaus added this to the 4.24.0 milestone Oct 21, 2026
@davsclaus davsclaus added the bug Something isn't working label Oct 21, 2026
@davsclaus
davsclaus merged commit 536d2e6 into apache:main Oct 21, 2026
7 checks passed
@oscerd
oscerd deleted the fix/CAMEL-25797-pqc-rotation-signals branch October 21, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants