Skip to content

feat(jans-cedarling): add CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX bootstrap property#14106

Merged
olehbozhok merged 11 commits into
mainfrom
jans-cedarling-14105
May 20, 2026
Merged

feat(jans-cedarling): add CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX bootstrap property#14106
olehbozhok merged 11 commits into
mainfrom
jans-cedarling-14105

Conversation

@olehbozhok
Copy link
Copy Markdown
Contributor

@olehbozhok olehbozhok commented May 18, 2026

Prepare


Description

Target issue

closes #14105

Implementation Details

Problem. Cedarling refreshes the Status List JWT only when the JWT carries a ttl claim. Two gaps:

  1. If the issuer omits ttl, the list is fetched once at startup and never refreshed, so revoked tokens remain valid in the cache for the lifetime of the process.
  2. If the issuer sets an excessively large ttl (e.g. 86400), Cedarling silently honors it and revocation propagation can lag a full day with no operator override.

There was no bootstrap property to guarantee or cap the refresh cadence.

Approach. Added a single bootstrap property CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX that acts as an upper bound on the refresh interval. The Status List JWT's ttl is still honored when present (per the IETF oauth-status-list spec) — the issuer can always request a more frequent refresh — but the bootstrap value caps how infrequent the refresh can be. When the JWT omits ttl, the max value is used directly, closing the "no ttl → no refresh" gap.

Semantics.

  • JWT has ttl → effective interval is min(jwt_ttl, INTERVAL_MAX). Issuer can refresh faster, never slower.
  • JWT has no ttl → use CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX directly.
  • Property is 0 or unset → resolves to the built-in default (300 seconds). There is intentionally no "disable" mode, so the cache cannot silently go stale forever.
  • Non-zero values below 5 are clamped to 5 to protect the IDP from misconfiguration.

Key changes.

  • cedarling/src/bootstrap_config/jwt_config.rs — new status_list_refresh_interval_max: u64 field on JwtConfig, with JwtConfig::DEFAULT_STATUS_LIST_REFRESH_INTERVAL_MAX_SECS = 300 as an associated constant and MIN_STATUS_LIST_REFRESH_SECS = 5 as the floor. Shared normalizer normalize_status_list_refresh_interval_max is invoked by both the bootstrap deserializer and JwtConfig::normalize so programmatic callers cannot bypass clamping.
  • cedarling/src/bootstrap_config/raw_config/{config,default_values,json_util}.rs — env-var binding for CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX. The deserializer maps None/0 to the default and clamps non-zero values below the minimum.
  • cedarling/src/bootstrap_config/decode.rs — propagates the value from raw config into JwtConfig.
  • cedarling/src/jwt/status_list/cache.rsStatusListCache::init_for_iss now takes the max interval via InitForIssArgs. The background refresh task is always spawned: ttl = jwt.ttl.map_or(MAX, |t| t.min(MAX)). The same min(jwt_ttl, MAX) rule is applied inside the refresh loop, replacing the hardcoded 600s fallback, so init and in-loop paths behave consistently.
  • cedarling/src/jwt/trusted_issuers_loader.rs — passes loader.jwt_config.status_list_refresh_interval_max into init_for_iss.

Docs. Updated docs/cedarling/reference/cedarling-properties.md (property reference) and docs/cedarling/reference/cedarling-jwt-validation.md (new "Status List Refresh Cadence" section explaining the min(jwt_ttl, INTERVAL_MAX) precedence).

Backward compatibility. The new field has a sane default (300s), so:

  • Deployments whose issuer previously omitted ttl (and therefore never refreshed) automatically start refreshing every 5 minutes after upgrade.
  • Deployments whose issuer supplies ttl ≤ 300s are unaffected.
  • Deployments whose issuer supplies ttl > 300s will now refresh every 300s instead of the issuer-requested interval. Operators who relied on a longer issuer-driven interval can raise CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX to restore the previous cadence.

Test and Document the changes

  • Static code analysis has been run locally and issues have been fixed
  • Relevant unit and integration tests have been added/updated
  • Relevant documentation has been updated if any (i.e. user guides, installation and configuration guides, technical design docs etc)

Please check the below before submitting your PR. The PR will not be merged if there are no commits that start with docs: to indicate documentation changes or if the below checklist is not selected.

  • I confirm that there is no impact on the docs due to the code changes in this PR.

Summary by CodeRabbit

  • New Features

    • Configurable maximum refresh interval for Status List JWT validation (default 300s); non-zero values below 5s are clamped to 5s.
  • Behavior

    • Background Status List refresh now always runs. Effective interval = min(jwt ttl, configured max); if ttl is missing the configured max is used.
  • Documentation

    • Added docs for refresh cadence, ttl precedence, defaulting and clamping rules.
  • Tests

    • Tests added for missing-ttl fallback, clamping and refresh behavior.

Review Change Stack

@olehbozhok olehbozhok self-assigned this May 18, 2026
@mo-auto
Copy link
Copy Markdown
Member

mo-auto commented May 18, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX and related runtime wiring: config schema, serde deserializer and defaults, status-list cache uses min(jwt.ttl, max) or max when ttl is absent, tests for parsing/clamping/refresh behavior, and documentation updates.

Changes

Status List Refresh Interval Max

Layer / File(s) Summary
Configuration schema, constants, and normalizer
jans-cedarling/cedarling/src/bootstrap_config/jwt_config.rs
Adds status_list_refresh_interval_max: u64, DEFAULT_STATUS_LIST_REFRESH_INTERVAL_MAX_SECS = 300, MIN_STATUS_LIST_REFRESH_SECS = 5, and normalize_status_list_refresh_interval_max(...) to map 0->default and clamp small non-zero values.
Bootstrap raw config deserialization and wiring
jans-cedarling/cedarling/src/bootstrap_config/raw_config/default_values.rs, jans-cedarling/cedarling/src/bootstrap_config/raw_config/json_util.rs, jans-cedarling/cedarling/src/bootstrap_config/raw_config/config.rs, jans-cedarling/cedarling/src/bootstrap_config/decode.rs
Adds serde default helper and deserializer deserialize_status_list_refresh_interval_max, wires status_list_refresh_interval_max on BootstrapConfigRaw to CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX, plugs value into BootstrapConfig::from_raw_config, and adds unit tests validating defaulting, parsing, zero-as-default, and clamping.
Status List cache refresh loop applying cap
jans-cedarling/cedarling/src/jwt/status_list/cache.rs
Refactors init_for_iss to accept InitForIssArgs including refresh_interval_max; refresh task is always spawned; effective interval computed as min(jwt.ttl, refresh_interval_max) when ttl present or refresh_interval_max when missing; loop recomputes on each refresh; tests updated and new test added for missing ttl.
Integration, test utilities, JwtService wiring, and docs
jans-cedarling/cedarling/src/jwt/test_utils.rs, jans-cedarling/cedarling/src/jwt/trusted_issuers_loader.rs, jans-cedarling/cedarling/src/jwt/mod.rs, docs/cedarling/reference/*
MockServer adds generator omitting ttl for tests; trusted issuer loader constructs InitForIssArgs passing jwt_config.status_list_refresh_interval_max; JwtService::new clones and normalizes JwtConfig before initialization; docs add CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX and describe min(ttl, max) semantics, default=300, 0/unset->default, and clamp to >=5s.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

  • #14097: Shares changes to JwtConfig/bootstrap defaults and normalization; may overlap at JwtConfig and serde default handling.

Possibly related PRs

Suggested reviewers

  • tareknaser
  • haileyesus2433
  • dagregi
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the primary change: adding the CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX bootstrap property.
Description check ✅ Passed The PR description thoroughly covers target issue (#14105), implementation details with clear problem/approach/semantics, key code changes across multiple files, backward compatibility analysis, and confirms tests and documentation updates are complete.
Linked Issues check ✅ Passed All coding requirements from issue #14105 are implemented: new bootstrap property added with u64 seconds type, default 300s with min 5s clamp, env-var binding, normalization logic in JwtConfig, status-list cache updated to use min(jwt_ttl, MAX), docs updated, and comprehensive tests added covering ttl present/absent scenarios.
Out of Scope Changes check ✅ Passed All changes directly support the stated objective of adding CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX with appropriate semantics and bounds. No unrelated or unnecessary modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jans-cedarling-14105

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@mo-auto mo-auto added area-documentation Documentation needs to change as part of issue or PR comp-docs Touching folder /docs comp-jans-cedarling Touching folder /jans-cedarling kind-feature Issue or PR is a new feature request labels May 18, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/cedarling/reference/cedarling-jwt-validation.md`:
- Around line 201-206: Add a sentence to the "Status List Refresh Cadence"
paragraph explicitly stating the clamping rule: if the bootstrap env/property
CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_FALLBACK is set to a non-zero value
less than 5 seconds it will be clamped up to 5 seconds; mention this applies
only to the fallback value (when the Status List JWT's ttl is absent) and is
ignored when a ttl claim is present. Reference the terms "Status List JWT",
"ttl", and CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_FALLBACK so readers can
connect this note to the properties reference.

In `@jans-cedarling/cedarling/src/bootstrap_config/raw_config/config.rs`:
- Line 820: Add a descriptive failure message to the assert_eq! that compares
config.status_list_refresh_interval_fallback to 120 so test failures explain
intent; locate the assertion referencing
config.status_list_refresh_interval_fallback and update the assert_eq! call to
include a string describing what is being validated (e.g., that the fallback
refresh interval defaults to 120 seconds) so the message appears on test
failure.

In `@jans-cedarling/cedarling/src/jwt/status_list/cache.rs`:
- Around line 68-77: The scheduler currently uses
InitForIssArgs.refresh_interval_fallback directly, which allows zero or
too-small values to create a tight refresh loop; normalize
refresh_interval_fallback to a safe minimum before any scheduling by computing a
sanitized interval (e.g., let effective_refresh = if refresh_interval_fallback <
MIN_REFRESH_INTERVAL { MIN_REFRESH_INTERVAL } else { refresh_interval_fallback
}) and use effective_refresh everywhere the refresh loop/scheduler is started
(locations where refresh_interval_fallback is currently read in the refresh
loop/scheduler). Ensure the normalization is done once after destructuring
InitForIssArgs so all subsequent uses (the refresh loop and any retry/schedule
calls) reference the normalized value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e71ff336-3d63-428b-94b8-935addb3af49

📥 Commits

Reviewing files that changed from the base of the PR and between c146ee6 and 10a17c2.

📒 Files selected for processing (10)
  • docs/cedarling/reference/cedarling-jwt-validation.md
  • docs/cedarling/reference/cedarling-properties.md
  • jans-cedarling/cedarling/src/bootstrap_config/decode.rs
  • jans-cedarling/cedarling/src/bootstrap_config/jwt_config.rs
  • jans-cedarling/cedarling/src/bootstrap_config/raw_config/config.rs
  • jans-cedarling/cedarling/src/bootstrap_config/raw_config/default_values.rs
  • jans-cedarling/cedarling/src/bootstrap_config/raw_config/json_util.rs
  • jans-cedarling/cedarling/src/jwt/status_list/cache.rs
  • jans-cedarling/cedarling/src/jwt/test_utils.rs
  • jans-cedarling/cedarling/src/jwt/trusted_issuers_loader.rs

Comment thread docs/cedarling/reference/cedarling-jwt-validation.md
Comment thread jans-cedarling/cedarling/src/bootstrap_config/raw_config/config.rs Outdated
Comment thread jans-cedarling/cedarling/src/jwt/status_list/cache.rs
…ck interval

Previously, the Status List JWT was refreshed only when its payload carried a
`ttl` claim. If the issuer omitted `ttl`, the list was fetched once at startup
and never refreshed, so revoked tokens stayed valid in the cache for the
lifetime of the process. The in-loop fallback was also a hardcoded `600s`.

Replace that magic number with a new bootstrap property
`CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_FALLBACK` (default 300 s).

- 0 resolves to the default; non-zero values below 5 s are clamped
- Background task always spawns, regardless of whether `ttl` is present
- Refactor `StatusListCache::init_for_iss` to take an args struct

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
Add `CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_FALLBACK` to the bootstrap
properties reference and a new "Status List Refresh Cadence" section in the
JWT validation reference explaining the JWT-`ttl` vs. bootstrap-fallback
precedence.

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
Spell out that non-zero CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_FALLBACK
values below 5 seconds are clamped up to 5 seconds, and that the clamp only
applies to the fallback path (Status List JWT without a `ttl` claim).

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
… test

The `from_env` assertion was bare while the sibling assertions in the same
module carry descriptive messages. Add one here so a regression surfaces the
intent of the check rather than just `120 != actual`.

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
… call site

The bootstrap deserializer already normalizes
CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_FALLBACK, but `JwtConfig` is a
public struct that callers can construct programmatically and bypass that
normalization, which could feed a `0` or sub-floor value into the refresh
loop and create a tight scheduling cycle.

Clamp the value to MIN_STATUS_LIST_REFRESH_SECS where the loader hands it
to `StatusListCache::init_for_iss`, so the production path is always safe
while internal callers (tests) can still pass small values directly to the
cache for fast verification.

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
@olehbozhok olehbozhok force-pushed the jans-cedarling-14105 branch from 10a17c2 to efa43de Compare May 18, 2026 22:52
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@jans-cedarling/cedarling/src/jwt/trusted_issuers_loader.rs`:
- Around line 242-245: The current normalization for refresh_interval_fallback
turns an explicit 0 into MIN_STATUS_LIST_REFRESH_SECS by using .max(...); change
this so you check loader.jwt_config.status_list_refresh_interval_fallback first
and if it is exactly 0 you set refresh_interval_fallback to the documented
default (300s), otherwise apply .max(MIN_STATUS_LIST_REFRESH_SECS) to clamp
nonzero values — update the assignment of refresh_interval_fallback to perform
this explicit 0 branch before calling .max.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 43360695-1fb5-403c-80b9-9e1b41b3fc98

📥 Commits

Reviewing files that changed from the base of the PR and between 10a17c2 and efa43de.

📒 Files selected for processing (10)
  • docs/cedarling/reference/cedarling-jwt-validation.md
  • docs/cedarling/reference/cedarling-properties.md
  • jans-cedarling/cedarling/src/bootstrap_config/decode.rs
  • jans-cedarling/cedarling/src/bootstrap_config/jwt_config.rs
  • jans-cedarling/cedarling/src/bootstrap_config/raw_config/config.rs
  • jans-cedarling/cedarling/src/bootstrap_config/raw_config/default_values.rs
  • jans-cedarling/cedarling/src/bootstrap_config/raw_config/json_util.rs
  • jans-cedarling/cedarling/src/jwt/status_list/cache.rs
  • jans-cedarling/cedarling/src/jwt/test_utils.rs
  • jans-cedarling/cedarling/src/jwt/trusted_issuers_loader.rs

Comment thread jans-cedarling/cedarling/src/jwt/trusted_issuers_loader.rs Outdated
The "0 -> default, sub-floor -> floor" rule for
CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_FALLBACK lived in two places:
the bootstrap deserializer and the trusted-issuer-loader call site. They
agreed today, but were easy to drift apart on the next change.

Move the rule into a single `normalize_status_list_refresh_interval_fallback`
helper and expose a `JwtConfig::normalize` method that applies all such
invariants in place. `JwtService::new` now calls `normalize` once on the
incoming config so programmatic callers cannot bypass the bootstrap
deserializer's normalization. Downstream call sites (loader, cache) simply
trust the already-normalized value.

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 18, 2026
dagregi
dagregi previously approved these changes May 19, 2026
haileyesus2433
haileyesus2433 previously approved these changes May 19, 2026
Rename CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_FALLBACK to
CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX and flip its semantics
from "fallback when JWT has no ttl" to "upper bound on the refresh
interval". When the Status List JWT carries a ttl, the effective
refresh interval is now min(jwt_ttl, MAX) so issuers can request more
frequent refreshes but never a less frequent one. When ttl is absent,
the MAX value is used directly.

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
Reflect the rename from CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_FALLBACK
to CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX and the new capping
semantics: the effective refresh interval is min(jwt_ttl, MAX).

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
@olehbozhok olehbozhok changed the title feat(jans-cedarling): add CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_FALLBACK bootstrap property feat(jans-cedarling): add CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX bootstrap property May 19, 2026
@olehbozhok olehbozhok requested a review from haileyesus2433 May 19, 2026 20:06
@olehbozhok olehbozhok requested a review from dagregi May 19, 2026 20:06
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
jans-cedarling/cedarling/src/jwt/status_list/cache.rs (1)

49-56: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Normalize refresh_interval_max inside this cache boundary.

Line 125 and Line 228 still schedule with the raw InitForIssArgs.refresh_interval_max. That means any crate-internal caller can pass 0 or <5 and drive a zero/too-tight refresh loop, even though the documented contract says 0 -> 300 and non-zero <5 -> 5. The new test at Line 454 is already relying on an impossible production value, so this sink is still missing its own guardrail.

Also applies to: 71-78, 123-125, 166-176, 224-228, 448-455

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@jans-cedarling/cedarling/src/jwt/status_list/cache.rs` around lines 49 - 56,
The cache is using the raw InitForIssArgs.refresh_interval_max when scheduling
refresh loops, allowing callers to pass 0 or <5 and force invalid intervals;
normalize this inside the cache boundary by computing let refresh_interval_max =
if args.refresh_interval_max == 0 { 300 } else {
args.refresh_interval_max.max(5) } (or equivalent) at the start of
JwtStatusListCache initialization and use that normalized value for any
scheduling/spawn calls (references: InitForIssArgs::refresh_interval_max,
JwtStatusListCache::init_for_issuer and any functions that currently read
args.refresh_interval_max to schedule loops); update the affected call sites to
use this local normalized variable and adjust the test that passes an impossible
production value to use the normalized semantics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@jans-cedarling/cedarling/src/jwt/status_list/cache.rs`:
- Around line 396-483: Add a new async test (e.g.,
refresh_capped_when_jwt_ttl_exceeds_max) modeled on
refresh_max_used_when_jwt_has_no_ttl that registers an issuer via
JwtValidatorCache::init_for_iss and StatusListCache::init_for_iss but has the
mock server return a status list JWT containing a ttl greater than the provided
refresh_interval_max (use MockServer::generate_status_list_endpoint_with_ttl or
equivalent to set ttl large, e.g., 10s, and pass refresh_interval_max = 1 to
init_for_iss). After updating the server-side list to a different bit pattern,
sleep for a duration slightly greater than refresh_interval_max but less than
the JWT ttl (e.g., 3s) and then assert the StatusListCache.status_lists entry
for mock_server.status_list_endpoint() was refreshed to the new list, proving
the loop used min(ttl, refresh_interval_max) and honored the cap. Ensure you
reference the same types used in the existing test (TrustedIssuer, IssuerConfig,
JwtConfig, StatusList) and reuse the HttpClient/key_service setup to keep the
test consistent.

---

Duplicate comments:
In `@jans-cedarling/cedarling/src/jwt/status_list/cache.rs`:
- Around line 49-56: The cache is using the raw
InitForIssArgs.refresh_interval_max when scheduling refresh loops, allowing
callers to pass 0 or <5 and force invalid intervals; normalize this inside the
cache boundary by computing let refresh_interval_max = if
args.refresh_interval_max == 0 { 300 } else { args.refresh_interval_max.max(5) }
(or equivalent) at the start of JwtStatusListCache initialization and use that
normalized value for any scheduling/spawn calls (references:
InitForIssArgs::refresh_interval_max, JwtStatusListCache::init_for_issuer and
any functions that currently read args.refresh_interval_max to schedule loops);
update the affected call sites to use this local normalized variable and adjust
the test that passes an impossible production value to use the normalized
semantics.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8c0ded87-224a-429d-b441-5e0f13d0913c

📥 Commits

Reviewing files that changed from the base of the PR and between bf07ff9 and 181f300.

📒 Files selected for processing (3)
  • docs/cedarling/reference/cedarling-properties.md
  • jans-cedarling/cedarling/src/jwt/mod.rs
  • jans-cedarling/cedarling/src/jwt/status_list/cache.rs

Comment thread jans-cedarling/cedarling/src/jwt/status_list/cache.rs
Internal StatusListUpdateCtx and InitForIssArgs now carry the refresh
interval and effective sleep as Duration instead of raw u64 seconds.
A helper effective_refresh_interval centralizes the
min(jwt_ttl, refresh_interval_max) cap, with refresh_interval_max used
directly when the JWT omits ttl.

Status list cache tests use sub-second Duration caps so the refresh
loop drives ticks at 200ms instead of 1s, cutting cache suite from
~3.0s to ~0.7s. Adds refresh_capped_when_jwt_ttl_exceeds_max covering
the cap path where JWT ttl exceeds the configured max.

The bootstrap config field remains seconds; the loader converts at the
call site, so user-facing configuration is unchanged.

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
dagregi
dagregi previously approved these changes May 20, 2026
Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
@olehbozhok
Copy link
Copy Markdown
Contributor Author

@coderabbitai approve

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Comments resolved and changes approved.

@olehbozhok olehbozhok merged commit b5142a8 into main May 20, 2026
3 checks passed
@olehbozhok olehbozhok deleted the jans-cedarling-14105 branch May 20, 2026 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-documentation Documentation needs to change as part of issue or PR comp-docs Touching folder /docs comp-jans-cedarling Touching folder /jans-cedarling kind-feature Issue or PR is a new feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(jans-cedarling): add CEDARLING_JWT_STATUS_LIST_REFRESH_INTERVAL_MAX bootstrap property

4 participants