This is an automated email from the ASF dual-hosted git repository.

oscerd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 4ef53c0e71a3 CAMEL-23849: Camel-PQC - add automated key rotation 
scheduling (#24455)
4ef53c0e71a3 is described below

commit 4ef53c0e71a3eb163133ab2ec15c140eac61b9b7
Author: Andrea Cosentino <[email protected]>
AuthorDate: Wed Jul 8 23:03:05 2026 +0200

    CAMEL-23849: Camel-PQC - add automated key rotation scheduling (#24455)
    
    * CAMEL-23849: Camel-PQC add automated key rotation scheduling
    
    Add KeyRotationScheduler, an opt-in background service that periodically
    evaluates the keys of a KeyLifecycleManager and rotates the ones that need
    rotation according to a configurable policy (check interval, max age, max
    usage, key filter). Rotated keys are replaced by a freshly generated key
    and the previous key is deprecated. The scheduler is a Camel Service (can
    be added to the CamelContext), notifies an optional KeyRotationListener on
    each rotation and error, and exposes counters for monitoring.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
    
    * CAMEL-23849: Address review - CamelContext ExecutorServiceManager and 
component options
    
    Review feedback on PR #24455:
    - KeyRotationScheduler implements CamelContextAware and, when a 
CamelContext is
      present, obtains its scheduled executor from the ExecutorServiceManager 
(with a
      standalone Executors fallback for non-Camel use); shutdown also goes 
through the
      manager.
    - Add camel.component.pqc.* options (keyRotationSchedulerEnabled,
      keyRotationCheckInterval, keyRotationMaxAge, keyRotationMaxUsage) so the 
scheduler
      can be configured and started without Java, reusing the existing 
keyLifecycleManager
      component option. Regenerated catalog and component-dsl.
    - Docs: property-driven configuration example.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
    
    ---------
    
    Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
---
 .../org/apache/camel/catalog/components/pqc.json   |  26 +-
 .../component/pqc/PQCComponentConfigurer.java      |  24 ++
 .../org/apache/camel/component/pqc/pqc.json        |  26 +-
 .../camel-pqc/src/main/docs/pqc-key-lifecycle.adoc |  67 ++++
 .../apache/camel/component/pqc/PQCComponent.java   |  99 ++++++
 .../pqc/lifecycle/KeyRotationScheduler.java        | 360 +++++++++++++++++++++
 .../pqc/lifecycle/KeyRotationSchedulerTest.java    | 284 ++++++++++++++++
 .../component/dsl/PqcComponentBuilderFactory.java  |  73 +++++
 8 files changed, 937 insertions(+), 22 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json
index 067244919a3f..a57b6015bc51 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json
@@ -39,17 +39,21 @@
     "keyLifecycleManager": { "index": 12, "kind": "property", "displayName": 
"Key Lifecycle Manager", "group": "advanced", "label": "advanced", "required": 
false, "type": "object", "javaType": 
"org.apache.camel.component.pqc.lifecycle.KeyLifecycleManager", "deprecated": 
false, "deprecationNote": "", "autowired": true, "secret": false, 
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "The KeyLifecycleManager 
to  [...]
     "keyPair": { "index": 13, "kind": "property", "displayName": "Key Pair", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "java.security.KeyPair", "deprecated": false, "deprecationNote": 
"", "autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The KeyPair to be used" },
     "keyPairAlias": { "index": 14, "kind": "property", "displayName": "Key 
Pair Alias", "group": "advanced", "label": "advanced", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "A KeyPair alias to use 
in combination with KeyStore parameter" },
-    "keyStore": { "index": 15, "kind": "property", "displayName": "Key Store", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "java.security.KeyStore", "deprecated": false, "deprecationNote": 
"", "autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "A KeyStore where we could get Cryptographic 
material" },
-    "keyStorePassword": { "index": 16, "kind": "property", "displayName": "Key 
Store Password", "group": "advanced", "label": "advanced", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": true, "security": 
"secret", "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The KeyStore password to use in combination 
with KeySto [...]
-    "signatureAlgorithm": { "index": 17, "kind": "property", "displayName": 
"Signature Algorithm", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA", 
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC", 
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "c [...]
-    "signer": { "index": 18, "kind": "property", "displayName": "Signer", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote": 
"", "autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The Signer to be used" },
-    "statefulKeyWarningThreshold": { "index": 19, "kind": "property", 
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label": 
"advanced", "required": false, "type": "number", "javaType": "double", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "defaultValue": 0.1, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The warning threshold for stateful key exh 
[...]
-    "storeExtractedSecretKeyAsHeader": { "index": 20, "kind": "property", 
"displayName": "Store Extracted Secret Key As Header", "group": "advanced", 
"label": "advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "defaultValue": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "In the context of extractSec [...]
-    "strictKeyLifecycle": { "index": 21, "kind": "property", "displayName": 
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "Whether to enforce key 
status checks before cryptographic  [...]
-    "symmetricKeyAlgorithm": { "index": 22, "kind": "property", "displayName": 
"Symmetric Key Algorithm", "group": "advanced", "label": "advanced", 
"required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ 
"AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6", "CHACHA7539", 
"DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128", "HC256", 
"SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "co [...]
-    "symmetricKeyLength": { "index": 23, "kind": "property", "displayName": 
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "The required length of 
the symmetric key used" },
-    "healthCheckConsumerEnabled": { "index": 24, "kind": "property", 
"displayName": "Health Check Consumer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all consumer based health checks 
from this component" },
-    "healthCheckProducerEnabled": { "index": 25, "kind": "property", 
"displayName": "Health Check Producer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all producer based health checks 
from this component. Notice: Camel has by default disabled all producer based 
health-checks. You can turn on produce [...]
+    "keyRotationCheckInterval": { "index": 15, "kind": "property", 
"displayName": "Key Rotation Check Interval", "group": "advanced", "label": 
"advanced", "required": false, "type": "duration", "javaType": "long", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 
"3600000", "description": "Interval between key rotation checks when the 
scheduler is enabled." },
+    "keyRotationMaxAge": { "index": 16, "kind": "property", "displayName": 
"Key Rotation Max Age", "group": "advanced", "label": "advanced", "required": 
false, "type": "duration", "javaType": "long", "deprecated": false, 
"autowired": false, "secret": false, "description": "When the scheduler is 
enabled, rotate keys older than this age. If not set, age is not used as a 
rotation signal." },
+    "keyRotationMaxUsage": { "index": 17, "kind": "property", "displayName": 
"Key Rotation Max Usage", "group": "advanced", "label": "advanced", "required": 
false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0, "description": "When the scheduler 
is enabled, rotate keys whose recorded usage count reaches this value. 0 
disables usage-based rotation." },
+    "keyRotationSchedulerEnabled": { "index": 18, "kind": "property", 
"displayName": "Key Rotation Scheduler Enabled", "group": "advanced", "label": 
"advanced", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 
false, "description": "Whether to start an automated background key rotation 
scheduler for this component. Requires keyLifecycleManager to be set. The 
scheduler periodically rotates keys that exce [...]
+    "keyStore": { "index": 19, "kind": "property", "displayName": "Key Store", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "java.security.KeyStore", "deprecated": false, "deprecationNote": 
"", "autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "A KeyStore where we could get Cryptographic 
material" },
+    "keyStorePassword": { "index": 20, "kind": "property", "displayName": "Key 
Store Password", "group": "advanced", "label": "advanced", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": true, "security": 
"secret", "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The KeyStore password to use in combination 
with KeySto [...]
+    "signatureAlgorithm": { "index": 21, "kind": "property", "displayName": 
"Signature Algorithm", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA", 
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC", 
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "c [...]
+    "signer": { "index": 22, "kind": "property", "displayName": "Signer", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote": 
"", "autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The Signer to be used" },
+    "statefulKeyWarningThreshold": { "index": 23, "kind": "property", 
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label": 
"advanced", "required": false, "type": "number", "javaType": "double", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "defaultValue": 0.1, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The warning threshold for stateful key exh 
[...]
+    "storeExtractedSecretKeyAsHeader": { "index": 24, "kind": "property", 
"displayName": "Store Extracted Secret Key As Header", "group": "advanced", 
"label": "advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "defaultValue": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "In the context of extractSec [...]
+    "strictKeyLifecycle": { "index": 25, "kind": "property", "displayName": 
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "Whether to enforce key 
status checks before cryptographic  [...]
+    "symmetricKeyAlgorithm": { "index": 26, "kind": "property", "displayName": 
"Symmetric Key Algorithm", "group": "advanced", "label": "advanced", 
"required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ 
"AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6", "CHACHA7539", 
"DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128", "HC256", 
"SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "co [...]
+    "symmetricKeyLength": { "index": 27, "kind": "property", "displayName": 
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "The required length of 
the symmetric key used" },
+    "healthCheckConsumerEnabled": { "index": 28, "kind": "property", 
"displayName": "Health Check Consumer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all consumer based health checks 
from this component" },
+    "healthCheckProducerEnabled": { "index": 29, "kind": "property", 
"displayName": "Health Check Producer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all producer based health checks 
from this component. Notice: Camel has by default disabled all producer based 
health-checks. You can turn on produce [...]
   },
   "headers": {
     "CamelPQCOperation": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The operation we want to perform", "constantName": 
"org.apache.camel.component.pqc.PQCConstants#OPERATION" },
diff --git 
a/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCComponentConfigurer.java
 
b/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCComponentConfigurer.java
index 39e46f037f72..4799514a49fa 100644
--- 
a/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCComponentConfigurer.java
+++ 
b/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCComponentConfigurer.java
@@ -59,6 +59,14 @@ public class PQCComponentConfigurer extends 
PropertyConfigurerSupport implements
         case "keyPair": 
getOrCreateConfiguration(target).setKeyPair(property(camelContext, 
java.security.KeyPair.class, value)); return true;
         case "keypairalias":
         case "keyPairAlias": 
getOrCreateConfiguration(target).setKeyPairAlias(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "keyrotationcheckinterval":
+        case "keyRotationCheckInterval": 
target.setKeyRotationCheckInterval(property(camelContext, 
java.time.Duration.class, value).toMillis()); return true;
+        case "keyrotationmaxage":
+        case "keyRotationMaxAge": 
target.setKeyRotationMaxAge(property(camelContext, java.time.Duration.class, 
value).toMillis()); return true;
+        case "keyrotationmaxusage":
+        case "keyRotationMaxUsage": 
target.setKeyRotationMaxUsage(property(camelContext, long.class, value)); 
return true;
+        case "keyrotationschedulerenabled":
+        case "keyRotationSchedulerEnabled": 
target.setKeyRotationSchedulerEnabled(property(camelContext, boolean.class, 
value)); return true;
         case "keystore":
         case "keyStore": 
getOrCreateConfiguration(target).setKeyStore(property(camelContext, 
java.security.KeyStore.class, value)); return true;
         case "keystorepassword":
@@ -120,6 +128,14 @@ public class PQCComponentConfigurer extends 
PropertyConfigurerSupport implements
         case "keyPair": return java.security.KeyPair.class;
         case "keypairalias":
         case "keyPairAlias": return java.lang.String.class;
+        case "keyrotationcheckinterval":
+        case "keyRotationCheckInterval": return long.class;
+        case "keyrotationmaxage":
+        case "keyRotationMaxAge": return long.class;
+        case "keyrotationmaxusage":
+        case "keyRotationMaxUsage": return long.class;
+        case "keyrotationschedulerenabled":
+        case "keyRotationSchedulerEnabled": return boolean.class;
         case "keystore":
         case "keyStore": return java.security.KeyStore.class;
         case "keystorepassword":
@@ -177,6 +193,14 @@ public class PQCComponentConfigurer extends 
PropertyConfigurerSupport implements
         case "keyPair": return getOrCreateConfiguration(target).getKeyPair();
         case "keypairalias":
         case "keyPairAlias": return 
getOrCreateConfiguration(target).getKeyPairAlias();
+        case "keyrotationcheckinterval":
+        case "keyRotationCheckInterval": return 
target.getKeyRotationCheckInterval();
+        case "keyrotationmaxage":
+        case "keyRotationMaxAge": return target.getKeyRotationMaxAge();
+        case "keyrotationmaxusage":
+        case "keyRotationMaxUsage": return target.getKeyRotationMaxUsage();
+        case "keyrotationschedulerenabled":
+        case "keyRotationSchedulerEnabled": return 
target.isKeyRotationSchedulerEnabled();
         case "keystore":
         case "keyStore": return getOrCreateConfiguration(target).getKeyStore();
         case "keystorepassword":
diff --git 
a/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json
 
b/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json
index 067244919a3f..a57b6015bc51 100644
--- 
a/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json
+++ 
b/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json
@@ -39,17 +39,21 @@
     "keyLifecycleManager": { "index": 12, "kind": "property", "displayName": 
"Key Lifecycle Manager", "group": "advanced", "label": "advanced", "required": 
false, "type": "object", "javaType": 
"org.apache.camel.component.pqc.lifecycle.KeyLifecycleManager", "deprecated": 
false, "deprecationNote": "", "autowired": true, "secret": false, 
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "The KeyLifecycleManager 
to  [...]
     "keyPair": { "index": 13, "kind": "property", "displayName": "Key Pair", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "java.security.KeyPair", "deprecated": false, "deprecationNote": 
"", "autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The KeyPair to be used" },
     "keyPairAlias": { "index": 14, "kind": "property", "displayName": "Key 
Pair Alias", "group": "advanced", "label": "advanced", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "A KeyPair alias to use 
in combination with KeyStore parameter" },
-    "keyStore": { "index": 15, "kind": "property", "displayName": "Key Store", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "java.security.KeyStore", "deprecated": false, "deprecationNote": 
"", "autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "A KeyStore where we could get Cryptographic 
material" },
-    "keyStorePassword": { "index": 16, "kind": "property", "displayName": "Key 
Store Password", "group": "advanced", "label": "advanced", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": true, "security": 
"secret", "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The KeyStore password to use in combination 
with KeySto [...]
-    "signatureAlgorithm": { "index": 17, "kind": "property", "displayName": 
"Signature Algorithm", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA", 
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC", 
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "c [...]
-    "signer": { "index": 18, "kind": "property", "displayName": "Signer", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote": 
"", "autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The Signer to be used" },
-    "statefulKeyWarningThreshold": { "index": 19, "kind": "property", 
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label": 
"advanced", "required": false, "type": "number", "javaType": "double", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "defaultValue": 0.1, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The warning threshold for stateful key exh 
[...]
-    "storeExtractedSecretKeyAsHeader": { "index": 20, "kind": "property", 
"displayName": "Store Extracted Secret Key As Header", "group": "advanced", 
"label": "advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "defaultValue": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "In the context of extractSec [...]
-    "strictKeyLifecycle": { "index": 21, "kind": "property", "displayName": 
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "Whether to enforce key 
status checks before cryptographic  [...]
-    "symmetricKeyAlgorithm": { "index": 22, "kind": "property", "displayName": 
"Symmetric Key Algorithm", "group": "advanced", "label": "advanced", 
"required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ 
"AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6", "CHACHA7539", 
"DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128", "HC256", 
"SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "co [...]
-    "symmetricKeyLength": { "index": 23, "kind": "property", "displayName": 
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "The required length of 
the symmetric key used" },
-    "healthCheckConsumerEnabled": { "index": 24, "kind": "property", 
"displayName": "Health Check Consumer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all consumer based health checks 
from this component" },
-    "healthCheckProducerEnabled": { "index": 25, "kind": "property", 
"displayName": "Health Check Producer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all producer based health checks 
from this component. Notice: Camel has by default disabled all producer based 
health-checks. You can turn on produce [...]
+    "keyRotationCheckInterval": { "index": 15, "kind": "property", 
"displayName": "Key Rotation Check Interval", "group": "advanced", "label": 
"advanced", "required": false, "type": "duration", "javaType": "long", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 
"3600000", "description": "Interval between key rotation checks when the 
scheduler is enabled." },
+    "keyRotationMaxAge": { "index": 16, "kind": "property", "displayName": 
"Key Rotation Max Age", "group": "advanced", "label": "advanced", "required": 
false, "type": "duration", "javaType": "long", "deprecated": false, 
"autowired": false, "secret": false, "description": "When the scheduler is 
enabled, rotate keys older than this age. If not set, age is not used as a 
rotation signal." },
+    "keyRotationMaxUsage": { "index": 17, "kind": "property", "displayName": 
"Key Rotation Max Usage", "group": "advanced", "label": "advanced", "required": 
false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0, "description": "When the scheduler 
is enabled, rotate keys whose recorded usage count reaches this value. 0 
disables usage-based rotation." },
+    "keyRotationSchedulerEnabled": { "index": 18, "kind": "property", 
"displayName": "Key Rotation Scheduler Enabled", "group": "advanced", "label": 
"advanced", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 
false, "description": "Whether to start an automated background key rotation 
scheduler for this component. Requires keyLifecycleManager to be set. The 
scheduler periodically rotates keys that exce [...]
+    "keyStore": { "index": 19, "kind": "property", "displayName": "Key Store", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "java.security.KeyStore", "deprecated": false, "deprecationNote": 
"", "autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "A KeyStore where we could get Cryptographic 
material" },
+    "keyStorePassword": { "index": 20, "kind": "property", "displayName": "Key 
Store Password", "group": "advanced", "label": "advanced", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": true, "security": 
"secret", "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The KeyStore password to use in combination 
with KeySto [...]
+    "signatureAlgorithm": { "index": 21, "kind": "property", "displayName": 
"Signature Algorithm", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA", 
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC", 
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "c [...]
+    "signer": { "index": 22, "kind": "property", "displayName": "Signer", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote": 
"", "autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The Signer to be used" },
+    "statefulKeyWarningThreshold": { "index": 23, "kind": "property", 
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label": 
"advanced", "required": false, "type": "number", "javaType": "double", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "defaultValue": 0.1, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "The warning threshold for stateful key exh 
[...]
+    "storeExtractedSecretKeyAsHeader": { "index": 24, "kind": "property", 
"displayName": "Store Extracted Secret Key As Header", "group": "advanced", 
"label": "advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "defaultValue": false, "configurationClass": 
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField": 
"configuration", "description": "In the context of extractSec [...]
+    "strictKeyLifecycle": { "index": 25, "kind": "property", "displayName": 
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "Whether to enforce key 
status checks before cryptographic  [...]
+    "symmetricKeyAlgorithm": { "index": 26, "kind": "property", "displayName": 
"Symmetric Key Algorithm", "group": "advanced", "label": "advanced", 
"required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ 
"AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6", "CHACHA7539", 
"DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128", "HC256", 
"SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "co [...]
+    "symmetricKeyLength": { "index": 27, "kind": "property", "displayName": 
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", 
"configurationField": "configuration", "description": "The required length of 
the symmetric key used" },
+    "healthCheckConsumerEnabled": { "index": 28, "kind": "property", 
"displayName": "Health Check Consumer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all consumer based health checks 
from this component" },
+    "healthCheckProducerEnabled": { "index": 29, "kind": "property", 
"displayName": "Health Check Producer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all producer based health checks 
from this component. Notice: Camel has by default disabled all producer based 
health-checks. You can turn on produce [...]
   },
   "headers": {
     "CamelPQCOperation": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The operation we want to perform", "constantName": 
"org.apache.camel.component.pqc.PQCConstants#OPERATION" },
diff --git a/components/camel-pqc/src/main/docs/pqc-key-lifecycle.adoc 
b/components/camel-pqc/src/main/docs/pqc-key-lifecycle.adoc
index 9ef0d21b04d6..adbd2af4c146 100644
--- a/components/camel-pqc/src/main/docs/pqc-key-lifecycle.adoc
+++ b/components/camel-pqc/src/main/docs/pqc-key-lifecycle.adoc
@@ -816,6 +816,73 @@ if (needsRotation) {
 }
 ----
 
+=== Automated Rotation Scheduling
+
+Rather than calling `needsRotation()`/`rotateKey()` by hand, the 
`KeyRotationScheduler` can evaluate all managed keys
+periodically in the background and rotate the ones that breach a configurable 
policy. It is opt-in: nothing runs until
+the scheduler is started.
+
+On every tick the scheduler lists the keys of its `KeyLifecycleManager`, keeps 
the ones matching the key filter (by
+default only `ACTIVE` keys) and, for each, delegates the decision to 
`needsRotation(keyId, maxKeyAge, maxKeyUsage)`. A
+key that needs rotation is replaced by a freshly generated key while the 
previous key is deprecated. At least one
+rotation signal must be configured - a maximum age, a maximum usage, or a 
per-key `nextRotationAt`/`PENDING_ROTATION`
+status recorded in the key metadata - otherwise no key will ever be selected.
+
+._Java-only: scheduling automated key rotation_
+[source,java]
+----
+KeyLifecycleManager keyManager = new 
FileBasedKeyLifecycleManager("/secure/keys");
+
+KeyRotationScheduler scheduler = new KeyRotationScheduler(keyManager)
+    .setCheckInterval(Duration.ofHours(6))   // how often to evaluate the keys 
(default: 1 hour)
+    .setMaxKeyAge(Duration.ofDays(90))       // rotate keys older than 90 days
+    .setMaxKeyUsage(1_000_000)               // and/or rotate keys used more 
than 1,000,000 times
+    .setListener(new KeyRotationScheduler.KeyRotationListener() {
+        @Override
+        public void onRotated(String oldKeyId, String newKeyId, KeyMetadata 
previous, KeyPair newKeyPair) {
+            logger.info("Rotated {} -> {}", oldKeyId, newKeyId);
+        }
+    });
+
+scheduler.start();       // begin the background schedule
+// ... application runs ...
+scheduler.stop();        // stop the background schedule
+----
+
+Because `KeyRotationScheduler` is a Camel `Service`, it can instead be added 
to the `CamelContext` so that it is started
+and stopped together with the context:
+
+._Java-only: managing the scheduler with the CamelContext_
+[source,java]
+----
+camelContext.addService(scheduler);   // started and stopped with the context
+----
+
+Alternatively, the scheduler can be started and configured entirely through 
component options - no Java code - by setting
+`camel.component.pqc.*` properties (for example in `application.properties`). 
Bind a `KeyLifecycleManager` in the
+registry and enable the scheduler:
+
+._application.properties: property-driven key rotation_
+[source,properties]
+----
+# a KeyLifecycleManager bean must be available in the registry, e.g. 
#myKeyManager
+camel.component.pqc.key-lifecycle-manager = #myKeyManager
+camel.component.pqc.key-rotation-scheduler-enabled = true
+camel.component.pqc.key-rotation-check-interval = 6h
+camel.component.pqc.key-rotation-max-age = 90d
+camel.component.pqc.key-rotation-max-usage = 1000000
+----
+
+When `keyRotationSchedulerEnabled` is `true`, the `pqc` component builds a 
`KeyRotationScheduler` around the configured
+`keyLifecycleManager` and starts and stops it with the component. The same 
options are available in the YAML DSL and as
+`PQCComponent` setters, which makes the scheduler usable from Spring Boot and 
Quarkus without any Java code.
+
+The default id of a replacement key is the previous key id with a rotation 
marker and timestamp appended; supply a
+`setKeyIdStrategy(Function<KeyMetadata, String>)` to control it, and a 
`setKeyFilter(Predicate<KeyMetadata>)` to change
+which keys are considered. The scheduler also exposes counters 
(`getChecksPerformed()`, `getRotationsPerformed()`,
+`getRotationFailures()`, `getLastCheckAt()`) for monitoring. A single pass can 
be triggered on demand with
+`checkAndRotate()`.
+
 == Key Export and Import
 
 Keys can be exported and imported in multiple formats:
diff --git 
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCComponent.java
 
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCComponent.java
index 6734fc1eb1d3..a8e9942bd882 100644
--- 
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCComponent.java
+++ 
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCComponent.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.component.pqc;
 
+import java.time.Duration;
 import java.util.Map;
 
 import org.apache.camel.CamelContext;
@@ -23,6 +24,8 @@ import org.apache.camel.Endpoint;
 import org.apache.camel.component.pqc.crypto.*;
 import org.apache.camel.component.pqc.crypto.hybrid.*;
 import org.apache.camel.component.pqc.crypto.kem.*;
+import org.apache.camel.component.pqc.lifecycle.KeyLifecycleManager;
+import org.apache.camel.component.pqc.lifecycle.KeyRotationScheduler;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.annotations.Component;
 import org.apache.camel.support.HealthCheckComponent;
@@ -36,6 +39,24 @@ public class PQCComponent extends HealthCheckComponent {
 
     @Metadata
     private PQCConfiguration configuration = new PQCConfiguration();
+    @Metadata(label = "advanced", defaultValue = "false",
+              description = "Whether to start an automated background key 
rotation scheduler for this component."
+                            + " Requires keyLifecycleManager to be set. The 
scheduler periodically rotates keys that"
+                            + " exceed the configured age and/or usage 
policy.")
+    private boolean keyRotationSchedulerEnabled;
+    @Metadata(label = "advanced", defaultValue = "3600000", javaType = 
"java.time.Duration",
+              description = "Interval between key rotation checks when the 
scheduler is enabled.")
+    private long keyRotationCheckInterval = 3600000L;
+    @Metadata(label = "advanced", javaType = "java.time.Duration",
+              description = "When the scheduler is enabled, rotate keys older 
than this age. If not set, age is not used"
+                            + " as a rotation signal.")
+    private long keyRotationMaxAge;
+    @Metadata(label = "advanced", defaultValue = "0",
+              description = "When the scheduler is enabled, rotate keys whose 
recorded usage count reaches this value. 0"
+                            + " disables usage-based rotation.")
+    private long keyRotationMaxUsage;
+
+    private KeyRotationScheduler keyRotationScheduler;
 
     public PQCComponent() {
         this(null);
@@ -260,6 +281,31 @@ public class PQCComponent extends HealthCheckComponent {
         }
     }
 
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+        if (keyRotationSchedulerEnabled) {
+            KeyLifecycleManager manager = configuration != null ? 
configuration.getKeyLifecycleManager() : null;
+            ObjectHelper.notNull(manager,
+                    "keyLifecycleManager (required when 
keyRotationSchedulerEnabled=true)");
+            keyRotationScheduler = new KeyRotationScheduler(manager)
+                    
.setCheckInterval(Duration.ofMillis(keyRotationCheckInterval))
+                    .setMaxKeyAge(keyRotationMaxAge > 0 ? 
Duration.ofMillis(keyRotationMaxAge) : null)
+                    .setMaxKeyUsage(keyRotationMaxUsage);
+            keyRotationScheduler.setCamelContext(getCamelContext());
+            keyRotationScheduler.start();
+        }
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        if (keyRotationScheduler != null) {
+            keyRotationScheduler.stop();
+            keyRotationScheduler = null;
+        }
+        super.doStop();
+    }
+
     public PQCConfiguration getConfiguration() {
         return configuration;
     }
@@ -270,4 +316,57 @@ public class PQCComponent extends HealthCheckComponent {
     public void setConfiguration(PQCConfiguration configuration) {
         this.configuration = configuration;
     }
+
+    public boolean isKeyRotationSchedulerEnabled() {
+        return keyRotationSchedulerEnabled;
+    }
+
+    /**
+     * Whether to start an automated background key rotation scheduler for 
this component. Requires keyLifecycleManager
+     * to be set. The scheduler periodically rotates keys that exceed the 
configured age and/or usage policy.
+     */
+    public void setKeyRotationSchedulerEnabled(boolean 
keyRotationSchedulerEnabled) {
+        this.keyRotationSchedulerEnabled = keyRotationSchedulerEnabled;
+    }
+
+    public long getKeyRotationCheckInterval() {
+        return keyRotationCheckInterval;
+    }
+
+    /**
+     * Interval between key rotation checks when the scheduler is enabled.
+     */
+    public void setKeyRotationCheckInterval(long keyRotationCheckInterval) {
+        this.keyRotationCheckInterval = keyRotationCheckInterval;
+    }
+
+    public long getKeyRotationMaxAge() {
+        return keyRotationMaxAge;
+    }
+
+    /**
+     * When the scheduler is enabled, rotate keys older than this age. If not 
set, age is not used as a rotation signal.
+     */
+    public void setKeyRotationMaxAge(long keyRotationMaxAge) {
+        this.keyRotationMaxAge = keyRotationMaxAge;
+    }
+
+    public long getKeyRotationMaxUsage() {
+        return keyRotationMaxUsage;
+    }
+
+    /**
+     * When the scheduler is enabled, rotate keys whose recorded usage count 
reaches this value. 0 disables usage-based
+     * rotation.
+     */
+    public void setKeyRotationMaxUsage(long keyRotationMaxUsage) {
+        this.keyRotationMaxUsage = keyRotationMaxUsage;
+    }
+
+    /**
+     * The automated key rotation scheduler created when 
keyRotationSchedulerEnabled is true, or null.
+     */
+    public KeyRotationScheduler getKeyRotationScheduler() {
+        return keyRotationScheduler;
+    }
 }
diff --git 
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/lifecycle/KeyRotationScheduler.java
 
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/lifecycle/KeyRotationScheduler.java
new file mode 100644
index 000000000000..d936576a43b3
--- /dev/null
+++ 
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/lifecycle/KeyRotationScheduler.java
@@ -0,0 +1,360 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pqc.lifecycle;
+
+import java.security.KeyPair;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An opt-in background scheduler that periodically evaluates the keys managed 
by a {@link KeyLifecycleManager} and
+ * rotates the ones that need rotation according to a configurable policy 
(maximum age and/or maximum usage). A rotated
+ * key is replaced by a freshly generated key while the previous key is 
deprecated - this is the behaviour of
+ * {@link KeyLifecycleManager#rotateKey(String, String, String)}.
+ * <p/>
+ * The scheduler is inactive until {@link #start()} is called. It implements 
the Camel {@code Service} contract, so it
+ * can be added to a {@code CamelContext} to participate in the context 
lifecycle:
+ *
+ * <pre>{@code
+ * KeyRotationScheduler scheduler = new KeyRotationScheduler(keyManager)
+ *         .setCheckInterval(Duration.ofHours(6))
+ *         .setMaxKeyAge(Duration.ofDays(90))
+ *         .setMaxKeyUsage(1_000_000);
+ * camelContext.addService(scheduler); // started and stopped with the context
+ * }</pre>
+ *
+ * On every tick the scheduler lists the managed keys, keeps only those 
matching the configured {@link #setKeyFilter key
+ * filter} (by default only {@link KeyMetadata.KeyStatus#ACTIVE ACTIVE} keys) 
and, for each of them, delegates the
+ * decision to {@link KeyLifecycleManager#needsRotation(String, Duration, 
long)}. When a key needs rotation, the id of
+ * its replacement is produced by the configured {@link #setKeyIdStrategy key 
id strategy} (by default the previous key
+ * id with a rotation marker and timestamp appended).
+ * <p/>
+ * At least one rotation signal should be configured (a {@link #setMaxKeyAge 
maximum age}, a {@link #setMaxKeyUsage
+ * maximum usage}, or a per-key {@code nextRotationAt}/{@code 
PENDING_ROTATION} status recorded in the key metadata);
+ * otherwise no key will ever be selected for rotation.
+ * <p/>
+ * A single check can also be triggered on demand with {@link 
#checkAndRotate()}, which is what the scheduled task
+ * calls. The method is thread-safe: concurrent invocations (for example a 
manual call overlapping a scheduled tick) are
+ * serialized.
+ */
+public class KeyRotationScheduler extends ServiceSupport implements 
CamelContextAware {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(KeyRotationScheduler.class);
+
+    private final KeyLifecycleManager keyManager;
+
+    private Duration checkInterval = Duration.ofHours(1);
+    private Duration maxKeyAge;
+    private long maxKeyUsage;
+    private Predicate<KeyMetadata> keyFilter = metadata -> 
metadata.getStatus() == KeyMetadata.KeyStatus.ACTIVE;
+    private Function<KeyMetadata, String> keyIdStrategy = 
KeyRotationScheduler::defaultRotatedKeyId;
+    private KeyRotationListener listener;
+
+    private final AtomicLong checksPerformed = new AtomicLong();
+    private final AtomicLong rotationsPerformed = new AtomicLong();
+    private final AtomicLong rotationFailures = new AtomicLong();
+    private volatile Instant lastCheckAt;
+
+    private ScheduledExecutorService executorService;
+
+    private CamelContext camelContext;
+
+    public KeyRotationScheduler(KeyLifecycleManager keyManager) {
+        this.keyManager = ObjectHelper.notNull(keyManager, "keyManager");
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    /**
+     * Performs a single rotation pass over the managed keys and returns how 
many keys were rotated. This is invoked by
+     * the scheduled task and can also be called manually. Never throws for an 
individual key failure: such failures are
+     * counted, logged and reported to the {@link KeyRotationListener 
listener}, then the pass continues with the next
+     * key.
+     *
+     * @return the number of keys rotated during this pass
+     */
+    public synchronized int checkAndRotate() {
+        checksPerformed.incrementAndGet();
+        lastCheckAt = Instant.now();
+
+        List<KeyMetadata> keys;
+        try {
+            keys = keyManager.listKeys();
+        } catch (Exception e) {
+            LOG.warn("Failed to list keys during rotation check", e);
+            notifyError(null, e);
+            return 0;
+        }
+
+        int rotated = 0;
+        for (KeyMetadata metadata : keys) {
+            if (metadata == null || !keyFilter.test(metadata)) {
+                continue;
+            }
+            String keyId = metadata.getKeyId();
+            try {
+                if (keyManager.needsRotation(keyId, maxKeyAge, maxKeyUsage)) {
+                    String newKeyId = keyIdStrategy.apply(metadata);
+                    LOG.info("Rotating PQC key '{}' -> '{}' (algorithm={})", 
keyId, newKeyId, metadata.getAlgorithm());
+                    KeyPair newKeyPair = keyManager.rotateKey(keyId, newKeyId, 
metadata.getAlgorithm());
+                    rotationsPerformed.incrementAndGet();
+                    rotated++;
+                    notifyRotated(keyId, newKeyId, metadata, newKeyPair);
+                }
+            } catch (Exception e) {
+                rotationFailures.incrementAndGet();
+                LOG.warn("Failed to rotate PQC key '{}'", keyId, e);
+                notifyError(keyId, e);
+            }
+        }
+        return rotated;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        ObjectHelper.notNull(checkInterval, "checkInterval");
+        if (checkInterval.isNegative() || checkInterval.isZero()) {
+            throw new IllegalArgumentException("checkInterval must be a 
positive duration");
+        }
+        long millis = checkInterval.toMillis();
+        // Prefer Camel's ExecutorServiceManager (centralized lifecycle, 
profiling, naming) when running inside a
+        // CamelContext; fall back to a self-managed daemon executor for 
standalone use.
+        if (camelContext != null) {
+            executorService = camelContext.getExecutorServiceManager()
+                    .newSingleThreadScheduledExecutor(this, 
"PQCKeyRotationScheduler");
+        } else {
+            executorService = Executors.newSingleThreadScheduledExecutor(new 
RotationThreadFactory());
+        }
+        executorService.scheduleWithFixedDelay(this::runScheduledCheck, 
millis, millis, TimeUnit.MILLISECONDS);
+        LOG.info("Started PQC KeyRotationScheduler (interval={}, maxAge={}, 
maxUsage={})",
+                checkInterval, maxKeyAge, maxKeyUsage);
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        if (executorService != null) {
+            if (camelContext != null) {
+                
camelContext.getExecutorServiceManager().shutdownNow(executorService);
+            } else {
+                executorService.shutdownNow();
+            }
+            executorService = null;
+        }
+        LOG.info("Stopped PQC KeyRotationScheduler (checks={}, rotations={}, 
failures={})",
+                checksPerformed.get(), rotationsPerformed.get(), 
rotationFailures.get());
+    }
+
+    private void runScheduledCheck() {
+        try {
+            checkAndRotate();
+        } catch (Throwable t) {
+            // Swallow everything so a single failing pass does not cancel the 
recurring schedule
+            LOG.warn("Unexpected error during scheduled PQC key rotation 
check", t);
+        }
+    }
+
+    private void notifyRotated(String oldKeyId, String newKeyId, KeyMetadata 
previousMetadata, KeyPair newKeyPair) {
+        if (listener != null) {
+            try {
+                listener.onRotated(oldKeyId, newKeyId, previousMetadata, 
newKeyPair);
+            } catch (Exception e) {
+                LOG.warn("KeyRotationListener.onRotated threw an exception", 
e);
+            }
+        }
+    }
+
+    private void notifyError(String keyId, Exception error) {
+        if (listener != null) {
+            try {
+                listener.onError(keyId, error);
+            } catch (Exception e) {
+                LOG.warn("KeyRotationListener.onError threw an exception", e);
+            }
+        }
+    }
+
+    private static String defaultRotatedKeyId(KeyMetadata metadata) {
+        return metadata.getKeyId() + "-rotated-" + 
Instant.now().toEpochMilli();
+    }
+
+    public KeyLifecycleManager getKeyManager() {
+        return keyManager;
+    }
+
+    public Duration getCheckInterval() {
+        return checkInterval;
+    }
+
+    /**
+     * How often the managed keys are evaluated for rotation. Must be a 
positive duration. Defaults to one hour.
+     */
+    public KeyRotationScheduler setCheckInterval(Duration checkInterval) {
+        this.checkInterval = ObjectHelper.notNull(checkInterval, 
"checkInterval");
+        return this;
+    }
+
+    public Duration getMaxKeyAge() {
+        return maxKeyAge;
+    }
+
+    /**
+     * Rotate a key once it is older than this age. When {@code null} (the 
default) age is not used as a rotation
+     * signal.
+     */
+    public KeyRotationScheduler setMaxKeyAge(Duration maxKeyAge) {
+        this.maxKeyAge = maxKeyAge;
+        return this;
+    }
+
+    public long getMaxKeyUsage() {
+        return maxKeyUsage;
+    }
+
+    /**
+     * Rotate a key once its recorded usage count reaches this value. When 
{@code 0} or negative (the default) usage is
+     * not used as a rotation signal.
+     */
+    public KeyRotationScheduler setMaxKeyUsage(long maxKeyUsage) {
+        this.maxKeyUsage = maxKeyUsage;
+        return this;
+    }
+
+    public Predicate<KeyMetadata> getKeyFilter() {
+        return keyFilter;
+    }
+
+    /**
+     * Selects which keys are considered for rotation. Defaults to only {@link 
KeyMetadata.KeyStatus#ACTIVE ACTIVE}
+     * keys.
+     */
+    public KeyRotationScheduler setKeyFilter(Predicate<KeyMetadata> keyFilter) 
{
+        this.keyFilter = ObjectHelper.notNull(keyFilter, "keyFilter");
+        return this;
+    }
+
+    public Function<KeyMetadata, String> getKeyIdStrategy() {
+        return keyIdStrategy;
+    }
+
+    /**
+     * Produces the id of the replacement key from the metadata of the key 
being rotated. Defaults to the previous key
+     * id with a rotation marker and timestamp appended.
+     */
+    public KeyRotationScheduler setKeyIdStrategy(Function<KeyMetadata, String> 
keyIdStrategy) {
+        this.keyIdStrategy = ObjectHelper.notNull(keyIdStrategy, 
"keyIdStrategy");
+        return this;
+    }
+
+    public KeyRotationListener getListener() {
+        return listener;
+    }
+
+    /**
+     * An optional listener notified on every rotation and on every rotation 
error.
+     */
+    public KeyRotationScheduler setListener(KeyRotationListener listener) {
+        this.listener = listener;
+        return this;
+    }
+
+    /**
+     * The number of rotation passes performed so far (scheduled and manual).
+     */
+    public long getChecksPerformed() {
+        return checksPerformed.get();
+    }
+
+    /**
+     * The number of keys successfully rotated so far.
+     */
+    public long getRotationsPerformed() {
+        return rotationsPerformed.get();
+    }
+
+    /**
+     * The number of key rotation attempts that failed so far.
+     */
+    public long getRotationFailures() {
+        return rotationFailures.get();
+    }
+
+    /**
+     * The instant of the last rotation pass, or {@code null} if no pass has 
run yet.
+     */
+    public Instant getLastCheckAt() {
+        return lastCheckAt;
+    }
+
+    /**
+     * Listener callbacks invoked by a {@link KeyRotationScheduler}. All 
methods have an empty default implementation,
+     * so an implementation only needs to override the callbacks it cares 
about.
+     */
+    public interface KeyRotationListener {
+
+        /**
+         * Invoked after a key has been rotated.
+         *
+         * @param oldKeyId         the id of the key that was rotated (and is 
now deprecated)
+         * @param newKeyId         the id of the freshly generated replacement 
key
+         * @param previousMetadata the metadata of the rotated key at the time 
of rotation
+         * @param newKeyPair       the freshly generated key pair
+         */
+        default void onRotated(String oldKeyId, String newKeyId, KeyMetadata 
previousMetadata, KeyPair newKeyPair) {
+        }
+
+        /**
+         * Invoked when a rotation attempt fails.
+         *
+         * @param keyId the id of the key that could not be rotated, or {@code 
null} when listing the keys failed
+         * @param error the failure
+         */
+        default void onError(String keyId, Exception error) {
+        }
+    }
+
+    private static final class RotationThreadFactory implements ThreadFactory {
+        @Override
+        public Thread newThread(Runnable r) {
+            Thread thread = new Thread(r, "PQCKeyRotationScheduler");
+            thread.setDaemon(true);
+            return thread;
+        }
+    }
+}
diff --git 
a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/lifecycle/KeyRotationSchedulerTest.java
 
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/lifecycle/KeyRotationSchedulerTest.java
new file mode 100644
index 000000000000..35fb53d7d4e2
--- /dev/null
+++ 
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/lifecycle/KeyRotationSchedulerTest.java
@@ -0,0 +1,284 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pqc.lifecycle;
+
+import java.nio.file.Path;
+import java.security.KeyPair;
+import java.security.Security;
+import java.time.Duration;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.camel.component.pqc.PQCComponent;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;
+import org.bouncycastle.pqc.jcajce.spec.DilithiumParameterSpec;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class KeyRotationSchedulerTest {
+
+    @TempDir
+    Path tempDir;
+
+    private FileBasedKeyLifecycleManager keyManager;
+    private KeyRotationScheduler scheduler;
+
+    @BeforeAll
+    static void startup() {
+        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
+            Security.addProvider(new BouncyCastleProvider());
+        }
+        if (Security.getProvider(BouncyCastlePQCProvider.PROVIDER_NAME) == 
null) {
+            Security.addProvider(new BouncyCastlePQCProvider());
+        }
+    }
+
+    @AfterEach
+    void cleanup() throws Exception {
+        if (scheduler != null && scheduler.isStarted()) {
+            scheduler.stop();
+        }
+        if (keyManager != null) {
+            for (KeyMetadata metadata : keyManager.listKeys()) {
+                keyManager.deleteKey(metadata.getKeyId());
+            }
+        }
+    }
+
+    private FileBasedKeyLifecycleManager newManager() throws Exception {
+        keyManager = new FileBasedKeyLifecycleManager(tempDir.toString());
+        return keyManager;
+    }
+
+    /** Generates a Dilithium key and drives its recorded usage count to the 
given value. */
+    private void generateKeyWithUsage(String keyId, long usage) throws 
Exception {
+        keyManager.generateKeyPair("DILITHIUM", keyId, 
DilithiumParameterSpec.dilithium2);
+        KeyMetadata metadata = keyManager.getKeyMetadata(keyId);
+        for (long i = 0; i < usage; i++) {
+            metadata.updateLastUsed();
+        }
+        keyManager.updateKeyMetadata(keyId, metadata);
+    }
+
+    @Test
+    void testRotatesKeyThatExceedsUsagePolicy() throws Exception {
+        newManager();
+        generateKeyWithUsage("app-key", 100);
+
+        scheduler = new KeyRotationScheduler(keyManager).setMaxKeyUsage(50);
+        int rotated = scheduler.checkAndRotate();
+
+        assertEquals(1, rotated);
+        assertEquals(1, scheduler.getChecksPerformed());
+        assertEquals(1, scheduler.getRotationsPerformed());
+        assertEquals(0, scheduler.getRotationFailures());
+        assertNotNull(scheduler.getLastCheckAt());
+
+        // The old key is deprecated and a single fresh ACTIVE replacement 
exists
+        assertEquals(KeyMetadata.KeyStatus.DEPRECATED, 
keyManager.getKeyMetadata("app-key").getStatus());
+        List<KeyMetadata> active = keyManager.listKeys().stream()
+                .filter(m -> m.getStatus() == KeyMetadata.KeyStatus.ACTIVE)
+                .toList();
+        assertEquals(1, active.size());
+        assertNotEquals("app-key", active.get(0).getKeyId());
+        assertEquals("DILITHIUM", active.get(0).getAlgorithm());
+    }
+
+    @Test
+    void testDoesNotRotateWhenPolicyNotBreached() throws Exception {
+        newManager();
+        generateKeyWithUsage("app-key", 10);
+
+        scheduler = new KeyRotationScheduler(keyManager).setMaxKeyUsage(1000);
+        int rotated = scheduler.checkAndRotate();
+
+        assertEquals(0, rotated);
+        assertEquals(0, scheduler.getRotationsPerformed());
+        assertEquals(KeyMetadata.KeyStatus.ACTIVE, 
keyManager.getKeyMetadata("app-key").getStatus());
+        assertEquals(1, keyManager.listKeys().size());
+    }
+
+    @Test
+    void testKeyFilterExcludesNonActiveKeys() throws Exception {
+        newManager();
+        // Would breach the usage policy, but the key is not ACTIVE so the 
default filter skips it
+        generateKeyWithUsage("app-key", 100);
+        KeyMetadata metadata = keyManager.getKeyMetadata("app-key");
+        metadata.setStatus(KeyMetadata.KeyStatus.DEPRECATED);
+        keyManager.updateKeyMetadata("app-key", metadata);
+
+        scheduler = new KeyRotationScheduler(keyManager).setMaxKeyUsage(50);
+        int rotated = scheduler.checkAndRotate();
+
+        assertEquals(0, rotated);
+        assertEquals(0, scheduler.getRotationsPerformed());
+        assertEquals(1, keyManager.listKeys().size());
+    }
+
+    @Test
+    void testCustomKeyIdStrategy() throws Exception {
+        newManager();
+        generateKeyWithUsage("app-key", 100);
+
+        scheduler = new KeyRotationScheduler(keyManager)
+                .setMaxKeyUsage(50)
+                .setKeyIdStrategy(m -> m.getKeyId() + "-v2");
+        scheduler.checkAndRotate();
+
+        KeyMetadata rotated = keyManager.getKeyMetadata("app-key-v2");
+        assertNotNull(rotated);
+        assertEquals(KeyMetadata.KeyStatus.ACTIVE, rotated.getStatus());
+    }
+
+    @Test
+    void testListenerInvokedOnRotation() throws Exception {
+        newManager();
+        generateKeyWithUsage("app-key", 100);
+
+        AtomicReference<String> oldId = new AtomicReference<>();
+        AtomicReference<String> newId = new AtomicReference<>();
+        AtomicReference<KeyPair> newPair = new AtomicReference<>();
+        scheduler = new KeyRotationScheduler(keyManager)
+                .setMaxKeyUsage(50)
+                .setListener(new KeyRotationScheduler.KeyRotationListener() {
+                    @Override
+                    public void onRotated(
+                            String oldKeyId, String newKeyId, KeyMetadata 
previousMetadata, KeyPair newKeyPair) {
+                        oldId.set(oldKeyId);
+                        newId.set(newKeyId);
+                        newPair.set(newKeyPair);
+                    }
+                });
+        scheduler.checkAndRotate();
+
+        assertEquals("app-key", oldId.get());
+        assertNotNull(newId.get());
+        assertNotEquals("app-key", newId.get());
+        assertNotNull(newPair.get());
+        assertNotNull(newPair.get().getPrivate());
+    }
+
+    @Test
+    void testScheduledRotation() throws Exception {
+        newManager();
+        generateKeyWithUsage("app-key", 100);
+
+        CountDownLatch rotated = new CountDownLatch(1);
+        scheduler = new KeyRotationScheduler(keyManager)
+                .setCheckInterval(Duration.ofMillis(50))
+                .setMaxKeyUsage(50)
+                .setListener(new KeyRotationScheduler.KeyRotationListener() {
+                    @Override
+                    public void onRotated(
+                            String oldKeyId, String newKeyId, KeyMetadata 
previousMetadata, KeyPair newKeyPair) {
+                        rotated.countDown();
+                    }
+                });
+
+        scheduler.start();
+        assertTrue(rotated.await(10, TimeUnit.SECONDS), "Scheduled rotation 
did not run in time");
+        scheduler.stop();
+
+        assertFalse(scheduler.isStarted());
+        assertTrue(scheduler.getRotationsPerformed() >= 1);
+        assertTrue(scheduler.getChecksPerformed() >= 1);
+        assertEquals(KeyMetadata.KeyStatus.DEPRECATED, 
keyManager.getKeyMetadata("app-key").getStatus());
+    }
+
+    @Test
+    void testStartRejectsNonPositiveInterval() throws Exception {
+        newManager();
+        scheduler = new 
KeyRotationScheduler(keyManager).setCheckInterval(Duration.ZERO);
+        assertThrows(RuntimeException.class, () -> scheduler.start());
+    }
+
+    @Test
+    void testScheduledRotationWithCamelContext() throws Exception {
+        newManager();
+        generateKeyWithUsage("app-key", 100);
+
+        CountDownLatch rotated = new CountDownLatch(1);
+        try (DefaultCamelContext context = new DefaultCamelContext()) {
+            context.start();
+            // With a CamelContext set, the scheduler obtains its executor 
from the ExecutorServiceManager
+            scheduler = new KeyRotationScheduler(keyManager)
+                    .setCheckInterval(Duration.ofMillis(50))
+                    .setMaxKeyUsage(50)
+                    .setListener(new 
KeyRotationScheduler.KeyRotationListener() {
+                        @Override
+                        public void onRotated(
+                                String oldKeyId, String newKeyId, KeyMetadata 
previousMetadata, KeyPair newKeyPair) {
+                            rotated.countDown();
+                        }
+                    });
+            scheduler.setCamelContext(context);
+            scheduler.start();
+
+            assertTrue(rotated.await(10, TimeUnit.SECONDS), "Scheduled 
rotation did not run in time");
+            assertSame(context, scheduler.getCamelContext());
+            scheduler.stop();
+        }
+
+        assertTrue(scheduler.getRotationsPerformed() >= 1);
+        assertEquals(KeyMetadata.KeyStatus.DEPRECATED, 
keyManager.getKeyMetadata("app-key").getStatus());
+    }
+
+    @Test
+    void testComponentOptionsStartScheduler() throws Exception {
+        newManager();
+        generateKeyWithUsage("app-key", 100);
+
+        try (DefaultCamelContext context = new DefaultCamelContext()) {
+            context.start();
+            PQCComponent component = new PQCComponent();
+            component.setCamelContext(context);
+            component.getConfiguration().setKeyLifecycleManager(keyManager);
+            component.setKeyRotationSchedulerEnabled(true);
+            component.setKeyRotationCheckInterval(3_600_000L); // 1h - won't 
auto-fire during the test
+            component.setKeyRotationMaxUsage(50);
+            component.start();
+
+            KeyRotationScheduler s = component.getKeyRotationScheduler();
+            assertNotNull(s);
+            assertSame(context, s.getCamelContext());
+            assertTrue(s.isStarted());
+
+            // Deterministic manual trigger: the component wired the manager 
and policy correctly
+            assertEquals(1, s.checkAndRotate());
+            assertEquals(KeyMetadata.KeyStatus.DEPRECATED, 
keyManager.getKeyMetadata("app-key").getStatus());
+
+            component.stop();
+            assertFalse(s.isStarted());
+            assertNull(component.getKeyRotationScheduler());
+        }
+    }
+}
diff --git 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PqcComponentBuilderFactory.java
 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PqcComponentBuilderFactory.java
index 6d9dbb4f6003..be73ea8fdd64 100644
--- 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PqcComponentBuilderFactory.java
+++ 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PqcComponentBuilderFactory.java
@@ -307,6 +307,75 @@ public interface PqcComponentBuilderFactory {
             return this;
         }
     
+        
+        /**
+         * Interval between key rotation checks when the scheduler is enabled.
+         * 
+         * The option is a: &lt;code&gt;long&lt;/code&gt; type.
+         * 
+         * Default: 3600000
+         * Group: advanced
+         * 
+         * @param keyRotationCheckInterval the value to set
+         * @return the dsl builder
+         */
+        default PqcComponentBuilder keyRotationCheckInterval(long 
keyRotationCheckInterval) {
+            doSetProperty("keyRotationCheckInterval", 
keyRotationCheckInterval);
+            return this;
+        }
+    
+        /**
+         * When the scheduler is enabled, rotate keys older than this age. If
+         * not set, age is not used as a rotation signal.
+         * 
+         * The option is a: &lt;code&gt;long&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param keyRotationMaxAge the value to set
+         * @return the dsl builder
+         */
+        default PqcComponentBuilder keyRotationMaxAge(long keyRotationMaxAge) {
+            doSetProperty("keyRotationMaxAge", keyRotationMaxAge);
+            return this;
+        }
+    
+        /**
+         * When the scheduler is enabled, rotate keys whose recorded usage 
count
+         * reaches this value. 0 disables usage-based rotation.
+         * 
+         * The option is a: &lt;code&gt;long&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param keyRotationMaxUsage the value to set
+         * @return the dsl builder
+         */
+        default PqcComponentBuilder keyRotationMaxUsage(long 
keyRotationMaxUsage) {
+            doSetProperty("keyRotationMaxUsage", keyRotationMaxUsage);
+            return this;
+        }
+    
+        
+        /**
+         * Whether to start an automated background key rotation scheduler for
+         * this component. Requires keyLifecycleManager to be set. The 
scheduler
+         * periodically rotates keys that exceed the configured age and/or 
usage
+         * policy.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: advanced
+         * 
+         * @param keyRotationSchedulerEnabled the value to set
+         * @return the dsl builder
+         */
+        default PqcComponentBuilder keyRotationSchedulerEnabled(boolean 
keyRotationSchedulerEnabled) {
+            doSetProperty("keyRotationSchedulerEnabled", 
keyRotationSchedulerEnabled);
+            return this;
+        }
+    
         /**
          * A KeyStore where we could get Cryptographic material.
          * 
@@ -538,6 +607,10 @@ public interface PqcComponentBuilderFactory {
             case "keyLifecycleManager": 
getOrCreateConfiguration((PQCComponent) 
component).setKeyLifecycleManager((org.apache.camel.component.pqc.lifecycle.KeyLifecycleManager)
 value); return true;
             case "keyPair": getOrCreateConfiguration((PQCComponent) 
component).setKeyPair((java.security.KeyPair) value); return true;
             case "keyPairAlias": getOrCreateConfiguration((PQCComponent) 
component).setKeyPairAlias((java.lang.String) value); return true;
+            case "keyRotationCheckInterval": ((PQCComponent) 
component).setKeyRotationCheckInterval((long) value); return true;
+            case "keyRotationMaxAge": ((PQCComponent) 
component).setKeyRotationMaxAge((long) value); return true;
+            case "keyRotationMaxUsage": ((PQCComponent) 
component).setKeyRotationMaxUsage((long) value); return true;
+            case "keyRotationSchedulerEnabled": ((PQCComponent) 
component).setKeyRotationSchedulerEnabled((boolean) value); return true;
             case "keyStore": getOrCreateConfiguration((PQCComponent) 
component).setKeyStore((java.security.KeyStore) value); return true;
             case "keyStorePassword": getOrCreateConfiguration((PQCComponent) 
component).setKeyStorePassword((java.lang.String) value); return true;
             case "signatureAlgorithm": getOrCreateConfiguration((PQCComponent) 
component).setSignatureAlgorithm((java.lang.String) value); return true;

Reply via email to