ol.clave.automation.impl.decisions
Pure decision functions for the automation layer.
These functions contain all the logic for determining what maintenance actions are needed for certificates.
renewal-threshold
Fraction of lifetime remaining that triggers renewal. Default 0.33 means renew when 1/3 of lifetime remains.
emergency-override-ari-threshold
Fraction of lifetime remaining that overrides ARI guidance. Default 0.05 (1/20) = 5% of lifetime.
emergency-critical-threshold
Fraction of lifetime remaining that triggers critical emergency. Default 0.02 (1/50) = 2% of lifetime.
ocsp-refresh-threshold
Fraction of OCSP validity window that triggers refresh. Default 0.5 = refresh at 50% of validity window.
short-lived-threshold-ms
Threshold for short-lived certificates (7 days in ms). Certificates shorter than this use different renewal logic.
max-retry-duration-ms
Maximum duration to retry a failing operation (30 days). After this duration, the operation fails permanently.
short-lived-cert?
(short-lived-cert? bundle)
Check if a certificate is short-lived (< 7 days lifetime).
Short-lived certificates (like those from ACME staging or specialized CAs) require different renewal timing logic.
ari-suggests-renewal?
(ari-suggests-renewal? bundle now maintenance-interval-ms)
Check if ARI data suggests renewal is due.
Per RFC 9710, returns true if current time is past the cutoff, where cutoff = selected-time minus maintenance-interval. This ensures we don’t miss the renewal window if maintenance runs just after the selected time.
Returns false if no ARI data or no selected-time is present.
| key | description |
|---------------------------|----------------------------------------------|
| bundle | Certificate bundle with optional :ari-data |
| now | Current instant |
| maintenance-interval-ms | Maintenance loop interval in milliseconds |
calculate-ari-renewal-time
(calculate-ari-renewal-time ari-data)
(calculate-ari-renewal-time ari-data rng)
Calculate a random time within the ARI suggested renewal window.
| key | description |
|------------|---------------------------------------------------------------|
| ari-data | ARI data with :suggested-window [start-instant end-instant] |
| rng | java.util.Random instance for random selection (optional) |
needs-renewal?
(needs-renewal? bundle now maintenance-interval-ms)
Check if certificate needs renewal based on expiration, ARI, and emergency.
Returns true if:
- Less than 5% (emergency-override-ari-threshold) of lifetime remains
(supersedes ARI guidance for safety), OR
- ARI selected-time cutoff has passed (per RFC 9710), OR
- Less than renewal-threshold (default 1/3) of lifetime remains
The emergency override ensures we never rely solely on ARI when the certificate is dangerously close to expiration.
emergency-renewal?
(emergency-renewal? bundle now maintenance-interval-ms)
Check if certificate is dangerously close to expiration.
Tiered thresholds:
- :critical - 1/50 (2%) lifetime remaining OR fewer than 5 maintenance intervals
- :override-ari - 1/20 (5%) lifetime remaining, overrides ARI guidance
- nil - no emergency
needs-ocsp-refresh?
(needs-ocsp-refresh? bundle config now)
Check if OCSP staple needs refresh.
Returns true if: - OCSP is enabled in config AND - Certificate is not short-lived (>= 7 days) AND - Staple is nil OR past 50% of validity window
Returns false if: - OCSP is disabled, OR - Certificate is short-lived (< 7 days lifetime)
Short-lived certificates don’t benefit from OCSP stapling because the certificate will expire before the OCSP response provides value.
| key | description |
|----------|----------------------------------------------------------|
| bundle | Certificate bundle with optional :ocsp-staple |
| config | Configuration with :ocsp map containing :enabled key |
| now | Current instant |
check-cert-maintenance
(check-cert-maintenance bundle config now maintenance-interval-ms)
Returns commands needed for this certificate.
Pure function that examines certificate state and returns a vector of command descriptors. Does not perform any I/O.
| key | description |
|---------------------------|-------------------------------------------|
| bundle | Certificate bundle from cache |
| config | Resolved configuration for this domain |
| now | Current instant |
| maintenance-interval-ms | Maintenance loop interval in milliseconds |
command-key
(command-key cmd)
Generate a key for command deduplication.
Returns a vector of [command-type domain] that uniquely identifies a command. Commands with the same key are considered duplicates and can be deduplicated by the job queue.
| key | description |
|-------|-------------------------------------------------------|
| cmd | Command descriptor with :command and :domain keys |
fast-command?
(fast-command? cmd)
Check if a command is fast.
| key | description |
|-------|----------------------------------------|
| cmd | Command descriptor with :command key |
classify-error
(classify-error ex)
Classify an exception into an error category.
Categories:
- :network-error - connection failures, DNS issues, timeouts
- :rate-limited - HTTP 429 responses
- :acme-error - ACME protocol errors (4xx responses)
- :server-error - server-side failures (5xx responses)
- :config-error - configuration problems
- :storage-error - I/O and storage failures
- :unknown - unrecognized exceptions
| key | description |
|------|-----------------------|
| ex | Exception to classify |
retryable-error?
(retryable-error? error-type)
Check if an error type should be retried.
Retryable errors:
- :network-error - transient network issues
- :rate-limited - should back off and retry
- :server-error - server may recover
- :storage-error - storage may become available
Non-retryable errors:
- :acme-error - client errors unlikely to succeed
- :config-error - configuration must be fixed
- :unknown - cannot determine if safe to retry
event-for-result
(event-for-result cmd result)
Create an event from a command result.
Event types by command and status:
- :obtain-certificate success → :certificate-obtained
- :renew-certificate success → :certificate-renewed
- :obtain-certificate error → :certificate-failed
- :renew-certificate error → :certificate-failed
- :fetch-ocsp success → :ocsp-stapled
- :fetch-ocsp error → :ocsp-failed
| key | description |
|----------|----------------------------------------------------|
| cmd | Command descriptor with :command and :domain |
| result | Result map with :status (:success or :error) |
create-certificate-loaded-event
(create-certificate-loaded-event bundle)
Create an event for a certificate loaded from storage.
retry-intervals
Exponential backoff intervals for failed operations (in milliseconds).
The pattern is front-loaded: aggressive early retries (1-2 min) catch transient failures quickly, then backs off through medium intervals (5-20 min) for rate-limiting or brief outages, then longer intervals (30 min - 1 hr) for issues requiring propagation or human intervention. Caps at 6 hours to avoid wasting resources during persistent outages.
Repeated consecutive values control dwell time at each tier before escalating (e.g., three 10-minute intervals means 3 attempts at that tier before moving to 20 minutes).
calculate-maintenance-jitter
(calculate-maintenance-jitter maintenance-jitter)
(calculate-maintenance-jitter maintenance-jitter rng)
Calculate random jitter for maintenance loop scheduling.
Returns a random value in [0, maintenance-jitter) to spread out maintenance operations and avoid thundering herd problems.