Skip to content

feat(jans-cedarling): make Cedar schema optional#14214

Open
olehbozhok wants to merge 15 commits into
mainfrom
jans-cedarling-14204
Open

feat(jans-cedarling): make Cedar schema optional#14214
olehbozhok wants to merge 15 commits into
mainfrom
jans-cedarling-14204

Conversation

@olehbozhok

@olehbozhok olehbozhok commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Prepare


Description

Target issue

closes #14204

Implementation Details

The feature makes Cedar schema validation optional via the new CEDARLING_STRICT_SCHEMA_VALIDATION bootstrap property (default: enabled).

Key changes:

  1. PolicyStore.schema is now Option<CedarSchema> — all schema-dependent code paths dispatch on Some/None instead of assuming a schema is always present.

  2. Two code paths in authorizationbuild_context_with_schema (injects entity refs from the action's schema-defined context shape) and build_context_no_schema (merges only request context + pushed data; passes None to Context::from_json_value). The Request::builder() call also skips .schema() when no schema is available.

  3. Schema loading is lenientschema.cedarschema is no longer a required file in directory/cjar loaders. If absent and strict_schema_validation is false, the store loads with schema: None. If absent and strict_schema_validation is true, loading fails with a clear error.

  4. convert_to_legacy accepts a strict_schema_validation flag — propagated through all loader entry points (JSON, YAML, Lock, cjar, directory, archive bytes). The legacy store deserializer also allows a missing or null schema field.

  5. Startup warning — when strict_schema_validation is disabled but a schema is present, a warning is logged that the schema will not be enforced.


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

    • Added CEDARLING_STRICT_SCHEMA_VALIDATION (enabled by default) to toggle strict schema enforcement; examples updated to enable it.
  • Documentation

    • Documented the new strict schema validation property.
  • Refactor

    • Policy-store and authorization flows now support optional/absent schemas, conditional schema application, and emit warnings when validation is disabled.
  • Tests

    • New and updated tests and fixtures covering behavior with and without schema enforcement.

Add CEDARLING_STRICT_SCHEMA_VALIDATION (default enabled) bootstrap
property. When disabled, Cedarling starts and authorizes without a
Cedar schema — entities built with None, is_authorized called without
schema.

Key changes:
- LoadedPolicyStore.schema: String → Option<String>
- PolicyStore.schema: CedarSchema → Option<CedarSchema>
- LegacyPolicyStore.schema: LegacyCedarSchema → Option<LegacyCedarSchema>
- build_context split into dispatcher + with/without_schema variants
- All authz paths pass Option<&Schema> for entity building / context
- Legacy & new format loaders all enforce strict flag consistently
- WARN logged when disabled but schema present

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

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
fix clippy issues

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
@olehbozhok olehbozhok self-assigned this Jun 4, 2026
@mo-auto

mo-auto commented Jun 4, 2026

Copy link
Copy Markdown
Member

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

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2d103185-4af5-4e39-b332-8fb2bcc53393

📥 Commits

Reviewing files that changed from the base of the PR and between 21787a8 and 9b6a9c0.

📒 Files selected for processing (2)
  • docs/cedarling/reference/cedarling-properties.md
  • jans-cedarling/cedarling/src/init/service_factory.rs

📝 Walkthrough

Walkthrough

Add CEDARLING_STRICT_SCHEMA_VALIDATION feature toggle (default enabled); make policy-store schema optional and thread strict-schema flag through loaders, conversion, entity/context building, request construction, service wiring, examples, and tests to support both strict and schemaless modes.

Changes

Strict Schema Validation Feature

Layer / File(s) Summary
Bootstrap config & docs
jans-cedarling/cedarling/src/bootstrap_config/raw_config/config.rs, jans-cedarling/cedarling/src/bootstrap_config/authorization_config.rs, jans-cedarling/cedarling/src/bootstrap_config/decode.rs, jans-cedarling/cedarling/config/default_config.yaml, docs/cedarling/reference/cedarling-properties.md
Add CEDARLING_STRICT_SCHEMA_VALIDATION feature toggle, defaulting to enabled; wire into AuthorizationConfig, decode into bootstrap, add default config entry and docs.
PolicyStore schema optionality
jans-cedarling/cedarling/src/common/policy_store.rs, jans-cedarling/cedarling/src/common/policy_store/legacy_store/mod.rs
Change PolicyStore.schema to Option<CedarSchema>; allow legacy deserialization to accept missing/null schema and map to Option during conversion.
Loader behavior and tests
jans-cedarling/cedarling/src/common/policy_store/loader.rs, jans-cedarling/cedarling/src/common/policy_store/loader_tests.rs
Make LoadedPolicyStore.schema an Option<String>, stop requiring schema.cedarschema file, return Ok(None) when absent, add VFS error-injection test, and update tests to unwrap/expect optional schema where needed.
PolicyStoreManager conversion changes
jans-cedarling/cedarling/src/common/policy_store/manager.rs
Add strict_schema_validation parameter to convert_to_legacy, error on missing schema only in strict mode, remove logger-enabled conversion path and final structured log, add conversion tests for strict/non-strict cases.
Init: load_policy_store wiring
jans-cedarling/cedarling/src/init/policy_store.rs, jans-cedarling/cedarling/src/init/service_config.rs
Add strict_schema_validation parameter to load_policy_store and all loader variants, propagate flag into extraction/conversion, and update tests to pass the flag.
ServiceFactory entity builder wiring
jans-cedarling/cedarling/src/init/service_factory.rs
Warn when strict validation is disabled but a schema exists; pass optional schema into EntityBuilder::new only when validation enabled.
Authorization context and request wiring
jans-cedarling/cedarling/src/authz/build_ctx.rs, jans-cedarling/cedarling/src/authz/mod.rs
Refactor build_context into dispatcher with build_context_with_schema/build_context_no_schema; make build_multi_issuer_context accept Option<&Schema>; thread optional schema into Entities::from_entities and conditionally attach schema to cedar_policy::Request. Add tests for no-schema context behavior.
Examples, integration tests, and fixtures
jans-cedarling/cedarling/examples/*, jans-cedarling/cedarling/src/tests/*, jans-cedarling/test_files/*
Enable strict schema in examples/tests, add schemaless fixtures, and add tests covering schemaless authorization and context-data behavior.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • haileyesus2433
  • dagregi
  • tareknaser
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat(jans-cedarling): make Cedar schema optional' clearly summarizes the main objective of the changeset.
Description check ✅ Passed The PR description includes target issue (#14204), implementation details explaining the feature, and confirms testing and documentation updates were completed.
Linked Issues check ✅ Passed All code changes directly implement the requirements from #14204: optional schema via CEDARLING_STRICT_SCHEMA_VALIDATION, PolicyStore.schema as Option, dual authorization paths, lenient schema loading, and warning logs.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing optional Cedar schema validation per #14204; no unrelated functionality modifications were introduced.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jans-cedarling-14204

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


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 Jun 4, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
jans-cedarling/cedarling/src/common/policy_store/manager.rs (1)

632-665: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consider adding test coverage for strict_schema_validation=false path.

The tests verify strict mode behavior, but there's no test for the schemaless path (strict_schema_validation=false with schema: None). This is a new feature behavior that should be tested.

♻️ Suggested test for schemaless mode
#[test]
fn test_convert_to_legacy_schemaless_mode() {
    let loaded = LoadedPolicyStore {
        metadata: create_test_metadata(),
        schema: None, // No schema provided
        policies: vec![PolicyFile {
            name: "test.cedar".to_string(),
            content: "permit(principal, action, resource);".to_string(),
        }],
        templates: vec![],
        entities: vec![],
        trusted_issuers: vec![],
    };

    // With strict=false, missing schema should succeed
    let result = PolicyStoreManager::convert_to_legacy(loaded.clone(), false);
    assert!(result.is_ok(), "Schemaless mode should succeed: {:?}", result.err());
    let store = result.unwrap();
    assert!(store.schema.is_none(), "Schema should be None in schemaless mode");
}

#[test]
fn test_convert_to_legacy_strict_requires_schema() {
    let loaded = LoadedPolicyStore {
        metadata: create_test_metadata(),
        schema: None, // No schema provided
        policies: vec![PolicyFile {
            name: "test.cedar".to_string(),
            content: "permit(principal, action, resource);".to_string(),
        }],
        templates: vec![],
        entities: vec![],
        trusted_issuers: vec![],
    };

    // With strict=true, missing schema should fail
    let result = PolicyStoreManager::convert_to_legacy(loaded, true);
    let err = result.expect_err("Strict mode should fail without schema");
    assert!(
        matches!(err, ConversionError::SchemaConversion(_)),
        "Expected SchemaConversion error, got: {err:?}"
    );
}

Also applies to: 667-720

🤖 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/common/policy_store/manager.rs` around lines 632
- 665, Add unit tests covering the schemaless path for
PolicyStoreManager::convert_to_legacy: create a LoadedPolicyStore with schema:
None and a minimal PolicyFile, then assert convert_to_legacy(loaded.clone(),
false) returns Ok and resulting store.schema is None (test name e.g.
test_convert_to_legacy_schemaless_mode); also add a test that
convert_to_legacy(loaded, true) returns an Err of the SchemaConversion variant
(test name e.g. test_convert_to_legacy_strict_requires_schema). Reference the
LoadedPolicyStore, PolicyFile, and ConversionError enums and use
PolicyStoreManager::convert_to_legacy in the new tests.
🤖 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/common/policy_store/loader_tests.rs`:
- Line 227: Replace bare assertions with ones that include explanatory failure
messages: for the assertion assert!(loaded_directory.schema.is_some()) in
loader_tests.rs update it to include a descriptive message like "expected
loaded_directory.schema to be Some but was None" and do the same for the other
bare asserts referenced (the ones around lines 1075, 1195, 1237, 1360) so each
assertion reports what was being tested and the unexpected state; locate these
by the symbol loaded_directory and the test functions in loader_tests.rs and
append an informative string as the second argument to assert! (or use
assert_eq!/assert_ne! with messages where appropriate).

In `@jans-cedarling/cedarling/src/common/policy_store/loader.rs`:
- Around line 278-286: The match on self.vfs.read_file(&schema_path) swallows
all errors; change the Err(_) arm to inspect the underlying I/O error and only
treat NotFound as Ok(None), while propagating other errors as
PolicyStoreError::FileReadError (including path and source). Update the match to
use Err(e) and check e.kind() == std::io::ErrorKind::NotFound (or the equivalent
from your VFS error type), returning Ok(None) for NotFound and mapping other
errors to PolicyStoreError::FileReadError with schema_path and the original
error as source so permission/disk errors are surfaced.

In `@jans-cedarling/cedarling/src/init/service_factory.rs`:
- Around line 130-154: The code warns when
bootstrap_config.authorization_config.strict_schema_validation is false but
still passes policy_store.schema into EntityBuilder::new, so update the schema
argument supplied to EntityBuilder::new to be None when strict_schema_validation
is disabled (instead of schema.as_deref()); locate the schema local and the call
to EntityBuilder::new and replace the passed schema with a conditional that uses
Some(schema) or schema.as_deref() only if
self.bootstrap_config.authorization_config.strict_schema_validation is true,
otherwise pass None so entity-building skips schema-based validation.

---

Outside diff comments:
In `@jans-cedarling/cedarling/src/common/policy_store/manager.rs`:
- Around line 632-665: Add unit tests covering the schemaless path for
PolicyStoreManager::convert_to_legacy: create a LoadedPolicyStore with schema:
None and a minimal PolicyFile, then assert convert_to_legacy(loaded.clone(),
false) returns Ok and resulting store.schema is None (test name e.g.
test_convert_to_legacy_schemaless_mode); also add a test that
convert_to_legacy(loaded, true) returns an Err of the SchemaConversion variant
(test name e.g. test_convert_to_legacy_strict_requires_schema). Reference the
LoadedPolicyStore, PolicyFile, and ConversionError enums and use
PolicyStoreManager::convert_to_legacy in the new tests.
🪄 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: 078f8007-75fb-4376-863b-3a110f452275

📥 Commits

Reviewing files that changed from the base of the PR and between 8e1bc3a and 058778b.

📒 Files selected for processing (21)
  • docs/cedarling/reference/cedarling-properties.md
  • jans-cedarling/cedarling/config/default_config.yaml
  • jans-cedarling/cedarling/examples/authorize_unsigned.rs
  • jans-cedarling/cedarling/examples/lock_integration.rs
  • jans-cedarling/cedarling/src/authz/build_ctx.rs
  • jans-cedarling/cedarling/src/authz/mod.rs
  • jans-cedarling/cedarling/src/bootstrap_config/authorization_config.rs
  • jans-cedarling/cedarling/src/bootstrap_config/decode.rs
  • jans-cedarling/cedarling/src/bootstrap_config/raw_config/config.rs
  • jans-cedarling/cedarling/src/common/policy_store.rs
  • jans-cedarling/cedarling/src/common/policy_store/legacy_store/mod.rs
  • jans-cedarling/cedarling/src/common/policy_store/legacy_store/test.rs
  • jans-cedarling/cedarling/src/common/policy_store/loader.rs
  • jans-cedarling/cedarling/src/common/policy_store/loader_tests.rs
  • jans-cedarling/cedarling/src/common/policy_store/log_entry.rs
  • jans-cedarling/cedarling/src/common/policy_store/manager.rs
  • jans-cedarling/cedarling/src/init/policy_store.rs
  • jans-cedarling/cedarling/src/init/service_config.rs
  • jans-cedarling/cedarling/src/init/service_factory.rs
  • jans-cedarling/cedarling/src/tests/policy_store_loader.rs
  • jans-cedarling/cedarling/src/tests/ssa_validation_integration.rs

Comment thread jans-cedarling/cedarling/src/common/policy_store/loader_tests.rs Outdated
Comment thread jans-cedarling/cedarling/src/common/policy_store/loader.rs
Comment thread jans-cedarling/cedarling/src/init/service_factory.rs Outdated

@haileyesus2433 haileyesus2433 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No end-to-end tests for schemaless authorize / authorize_unsigned
it will be nice to add this test scenarios:

  • Load with strict=false, no schema, call authorize_unsigned, verify Permit
  • Load with strict=true, no schema, verify PolicyStoreLoadError
  • Load with strict=false, schema present, verify WARN is logged
  • Load with strict=false, no schema, verify WARN is logged

It is not documented in any binding API it will be nice to update the bindings as well

Comment thread jans-cedarling/cedarling/src/common/policy_store/loader.rs
}

// Warn when strict schema validation is disabled but schema is present
if !self.bootstrap_config.authorization_config.strict_schema_validation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The implementation warns when disabled AND schema-present but is completely silent when disabled AND schema-absent which i think is the more dangerous state, because schema-present-but-not-enforced is obvious from logs while schema-absent is invisible.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We notify the user about a potential misconfiguration (because the schema is present).
But if schema validation is disabled (intentionally; it is not the default behaviour) and the schema is not present, it looks like it what user wants.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One more angle: we already emit warnings when CEDARLING_JWT_SIG_VALIDATION or CEDARLING_JWT_STATUS_VALIDATION are disabled (#14141) even though those are intentional opt-outs. It seems to me that schema-off is the same kind of situation. it’s a deliberate choice but it changes evaluation since we no longer do attribute-shape validation.

So instead of only warning when a schema is present but not enforced, we could just always WARN when strict mode is off and vary the message depending on the case (“schema present but not enforced” vs “no schema loaded. policies run without attribute validation”). I think that would make it consistent with how we handle the JWT validation toggles

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

OK, I will add

action: &cedar_policy::EntityUid,
pushed_data: HashMap<String, Value>,
) -> Result<cedar_policy::Context, BuildContextError> {
let store_schema = config.policy_store.schema.as_ref()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The function accepts schema: &cedar_policy::Schema but fetches the JSON schema representation from config rather than deriving it from the passed parameter. The ok_or_else branch is unreachable in all current call sites because the dispatcher build_context only invokes this function when schema.is_some(), and schema_ref and config.policy_store.schema are always the same object.
Either derive json_schema from the passed schema parameter, or remove the schema parameter and derive it from config exclusively, making the contract explicit.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

resolved

Comment thread jans-cedarling/cedarling/src/authz/mod.rs Outdated
// 5. Parse cedar version
let cedar_version = Self::parse_cedar_version(&loaded.metadata.cedar_version)?;

logger.log_any(PolicyStoreLogEntry::info(format!(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is there a reason why this might be removed because i think this was a useful observability signal (confirming how many policies and issuers were loaded at startup)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I returned the log message

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
load_schema swallowed all read errors as Ok(None), hiding permission
and disk failures. Now only NotFound maps to Ok(None); other I/O errors
propagate as PolicyStoreError::FileReadError with path and source.

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

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

Both `schema` (cedar_policy::Schema) and `json` (CedarSchemaJson) were
derived from `config.policy_store.schema` separately, making the
`schema` parameter redundant and the `ok_or_else` branch unreachable.
Now everything is derived from `config` exclusively, making the contract explicit.

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
- build_ctx: no-schema context building, multi-issuer without schema
- manager: convert_to_legacy with/without schema × strict true/false
- policy_store: extract_first_policy_store strict validation paths
- loader_tests: non-NotFound IO error propagation on schema read
- legacy_store: null/missing schema field deserialization

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
- authorize_unsigned: allow, deny, no-principal, strict-fail, schema-present-flag-false
- authorize_multi_issuer: single-token, strict-fail
- context_data_api: pushed data without schema
- test fixtures: policy-store_no_schema.yaml, policy-store-multi-issuer-no-schema.yaml

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
@olehbozhok olehbozhok requested a review from haileyesus2433 June 9, 2026 19:03

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
jans-cedarling/cedarling/src/authz/build_ctx.rs (1)

23-34: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Gate schema-based context building on strict_schema_validation.

With strict_schema_validation = false and a loaded schema, this still routes into build_context_with_schema. That path calls Context::from_json_value(..., Some((schema, action))), so request context is still schema-validated and unknown actions can still fail. That breaks the PR contract for the “schema present but not enforced” mode.

Proposed fix
 pub(super) fn build_context(
     config: &AuthzConfig,
     request_context: Value,
     build_entities: &BuiltEntities,
     action: &cedar_policy::EntityUid,
     pushed_data: HashMap<String, Value>,
 ) -> Result<cedar_policy::Context, BuildContextError> {
-    if config.policy_store.schema.is_some() {
+    if config.authorization.strict_schema_validation && config.policy_store.schema.is_some() {
         build_context_with_schema(config, request_context, build_entities, action, pushed_data)
     } else {
         build_context_no_schema(request_context, pushed_data)
     }
 }
🤖 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/authz/build_ctx.rs` around lines 23 - 34, The
current build_context always chooses build_context_with_schema when a schema
exists, causing validation even when strict_schema_validation is disabled;
change build_context to check both that a schema is present and that
strict_schema_validation is true (e.g. if config.policy_store.schema.is_some()
&& config.strict_schema_validation) and only then call
build_context_with_schema, otherwise call build_context_no_schema; update the
conditional in build_context so it references the strict_schema_validation flag
on AuthzConfig and preserves existing behavior when true.
🤖 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/tests/authorize_without_schema.rs`:
- Around line 131-144: Replace the assert!(result.is_err(), ...) in the
test_unsigned_strict_true_missing_schema_fails_init test with
result.expect_err("init should fail: strict=true but no schema in policy store")
so the test uses expect_err on the Cedarling::new(&config).await result for
clearer failure messages; update the assertion on the local result variable
returned by Cedarling::new to call expect_err with the same descriptive message.
- Around line 234-247: Replace the generic assert!(result.is_err()) check in the
test_multi_issuer_without_schema_strict_true_fails test with an explicit
expect_err call on the result (e.g., result.expect_err("multi-issuer init should
fail: strict=true but policy store has no schema")) so the test uses expect_err
and provides the descriptive failure message; update the assertion in the
test_multi_issuer_without_schema_strict_true_fails function accordingly.

---

Outside diff comments:
In `@jans-cedarling/cedarling/src/authz/build_ctx.rs`:
- Around line 23-34: The current build_context always chooses
build_context_with_schema when a schema exists, causing validation even when
strict_schema_validation is disabled; change build_context to check both that a
schema is present and that strict_schema_validation is true (e.g. if
config.policy_store.schema.is_some() && config.strict_schema_validation) and
only then call build_context_with_schema, otherwise call
build_context_no_schema; update the conditional in build_context so it
references the strict_schema_validation flag on AuthzConfig and preserves
existing behavior when true.
🪄 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: 8fd93212-42a4-4366-acc2-ac60303daa08

📥 Commits

Reviewing files that changed from the base of the PR and between 058778b and 21787a8.

📒 Files selected for processing (14)
  • jans-cedarling/cedarling/src/authz/build_ctx.rs
  • jans-cedarling/cedarling/src/authz/mod.rs
  • jans-cedarling/cedarling/src/common/policy_store.rs
  • jans-cedarling/cedarling/src/common/policy_store/legacy_store/test.rs
  • jans-cedarling/cedarling/src/common/policy_store/loader.rs
  • jans-cedarling/cedarling/src/common/policy_store/loader_tests.rs
  • jans-cedarling/cedarling/src/common/policy_store/manager.rs
  • jans-cedarling/cedarling/src/init/policy_store.rs
  • jans-cedarling/cedarling/src/init/service_factory.rs
  • jans-cedarling/cedarling/src/tests/authorize_without_schema.rs
  • jans-cedarling/cedarling/src/tests/context_data_api.rs
  • jans-cedarling/cedarling/src/tests/mod.rs
  • jans-cedarling/test_files/policy-store-multi-issuer-no-schema.yaml
  • jans-cedarling/test_files/policy-store_no_schema.yaml
💤 Files with no reviewable changes (1)
  • jans-cedarling/cedarling/src/authz/mod.rs

Comment thread jans-cedarling/cedarling/src/tests/authorize_without_schema.rs
Comment thread jans-cedarling/cedarling/src/tests/authorize_without_schema.rs
tareknaser
tareknaser previously approved these changes Jun 9, 2026

@tareknaser tareknaser left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Minor comments. I think we are good to go


- **`CEDARLING_JWT_SIG_VALIDATION`** : `enabled` | `disabled` -- Whether to check the signature of all JWT tokens. When enabled, this requires the `iss` claim to be present in all tokens and the issuer URL must use the `https` scheme. Loopback hosts (`localhost`, `127.0.0.1`, `::1`) are allowed over plain HTTP so local development is not blocked. Default is `enabled`. **Disabling this is strongly discouraged outside of testing**: a JWT without signature validation is just plain JSON and is trivially spoofable.
- **`CEDARLING_JWT_STATUS_VALIDATION`** : `enabled` | `disabled` -- Whether to check the status of the JWT. On startup, the Cedarling should fetch and retrieve the latest Status List JWT from the `.well-known/openid-configuration` via the `status_list_endpoint` claim and cache it. See the [IETF Draft](https://datatracker.ietf.org/doc/draft-ietf-oauth-status-list/) for more info. Default is `enabled`. If the issuer does not publish a `status_list_endpoint`, status checks are skipped gracefully for that issuer.
- **`CEDARLING_STRICT_SCHEMA_VALIDATION`** : `enabled` | `disabled` -- When `enabled` (default), a Cedar schema is required and policies/entities are validated against it (current behavior). When `disabled`, Cedarling runs without schema-based validation, allowing quick-start and prototyping without maintaining a schema. If disabled and a schema is present, a warning is logged that the schema is loaded but not enforced. Default is `enabled`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This explains how to turn schema off but not what you lose which is the more important part.

AFAIK, the schema is the only thing that enforces shape constraints on entities and context and action arguments. Without it, things like a typo in a policy won’t fail at load time. the policy just silently never matches. You also lose type checking on claims/attributes so mismatches can reach the engine unchecked.

It might be worth adding a line like: “Disabling this removes the load-time guard on attribute names and types. Typos in policies will silently fail to match and claim/attribute types are not validated. Keep enabled outside of prototyping”
That should be consistent with the existing “strongly discouraged outside of testing” wording used for CEDARLING_JWT_SIG_VALIDATION

}

// Warn when strict schema validation is disabled but schema is present
if !self.bootstrap_config.authorization_config.strict_schema_validation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One more angle: we already emit warnings when CEDARLING_JWT_SIG_VALIDATION or CEDARLING_JWT_STATUS_VALIDATION are disabled (#14141) even though those are intentional opt-outs. It seems to me that schema-off is the same kind of situation. it’s a deliberate choice but it changes evaluation since we no longer do attribute-shape validation.

So instead of only warning when a schema is present but not enforced, we could just always WARN when strict mode is off and vary the message depending on the case (“schema present but not enforced” vs “no schema loaded. policies run without attribute validation”). I think that would make it consistent with how we handle the JWT validation toggles

dagregi
dagregi previously approved these changes Jun 10, 2026
Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 10, 2026
…abled

Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
@olehbozhok olehbozhok requested review from dagregi and tareknaser June 10, 2026 14:19
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): make Cedar schema optional

5 participants