Repository: cedar-policy/cedar
Pull request #1541 (2025-03-19 20:28:34)

Stabilize `datetime` extension
## Description of changes

## Issue #, if available

## Checklist for requesting a review

The change in this PR is (choose one, and delete the other options):

- [x] A backwards-compatible change requiring a minor version bump to `cedar-policy` (e.g., addition of a new API).

I confirm that this PR (choose one, and delete the other options):

- [x] Updates the "Unreleased" section of the CHANGELOG with a description of my change (required for major/minor version bumps).

I confirm that [`cedar-spec`](https://github.com/cedar-policy/cedar-spec) (choose one, and delete the other options):

- [x] Requires updates, and I have made / will make these updates myself. (Please include in your description a timeline or link to the relevant PR in `cedar-spec`, and how you have tested that your updates are correct.)

I confirm that [`docs.cedarpolicy.com`](https://docs.cedarpolicy.com/) (choose one, and delete the other options):

- [x] Requires updates, and I have made / will make these updates myself. (Please include in your description a timeline or link to the relevant PR in [`cedar-docs`](https://github.com/cedar-policy/cedar-docs). PRs should be targeted at a `staging-X.Y` branch, not `main`.)

github-actions[bot]: 
# Coverage Report
Head Commit: ```4e70ddc171e0249bce6f7ab2e706465a83386d8a```

Base Commit: ```e93072f4975b021109e2a56e954427b23d30e1f8```

[Download the full coverage report.](https://github.com/cedar-policy/cedar/actions/runs/13956085762/artifacts/2783895418)

## Coverage of Added or Modified Lines of Rust Code
**Required coverage:** 80.00%

**Actual coverage:** 100.00%

**Status:** PASSED :white_check_mark:

<details>
<summary><b>Details</b></summary>

| File | Status | Covered | Coverage | Missed Lines |
|:-----|:------:|:-------:|---------:|:-------------|

</details>

## Coverage of All Lines of Rust Code
**Required coverage:** 80.00%

**Actual coverage:** 81.53%

**Status:** PASSED :white_check_mark:

<details>
<summary><b>Details</b></summary>

| Package | Status | Covered | Coverage | Base Coverage |
|:--------|:------:|:-------:|---------:|--------------:|
cedar-policy | :red_circle: | 3059/4397 | 69.57% | --
cedar-policy-cli | :red_circle: | 538/927 | 58.04% | --
cedar-policy-core | :green_circle: | 11657/13899 | 83.87% | --
cedar-policy-formatter | :green_circle: | 914/1043 | 87.63% | --
cedar-policy-validator | :green_circle: | 8310/9729 | 85.41% | --
cedar-wasm | :red_circle: | 0/29 | 0.00% | --
</details>


Patch:
diff --git a/cedar-policy-cli/Cargo.toml b/cedar-policy-cli/Cargo.toml
index 0e9b6ded..7fc29304 100644
--- a/cedar-policy-cli/Cargo.toml
+++ b/cedar-policy-cli/Cargo.toml
@@ -22,11 +22,10 @@ semver = "1.0.26"
 
 [features]
 default = []
-experimental = ["level-validate", "permissive-validate", "partial-validate", "partial-eval", "datetime"]
+experimental = ["level-validate", "permissive-validate", "partial-validate", "partial-eval"]
 permissive-validate = ["cedar-policy/permissive-validate"]
 partial-validate = ["cedar-policy/partial-validate"]
 partial-eval = ["cedar-policy/partial-eval"]
-datetime = ["cedar-policy/datetime"]
 level-validate = ["cedar-policy/level-validate"]
 
 [dev-dependencies]
diff --git a/cedar-policy-core/Cargo.toml b/cedar-policy-core/Cargo.toml
index e721ed52..ea578bf7 100644
--- a/cedar-policy-core/Cargo.toml
+++ b/cedar-policy-core/Cargo.toml
@@ -43,7 +43,7 @@ chrono = { version = "0.4.40", optional = true, default-features = false}
 
 [features]
 # by default, enable all Cedar extensions
-default = ["ipaddr", "decimal"]
+default = ["ipaddr", "decimal", "datetime"]
 ipaddr = []
 decimal = ["dep:regex"]
 datetime = ["dep:chrono", "dep:regex"]
diff --git a/cedar-policy-core/src/evaluator.rs b/cedar-policy-core/src/evaluator.rs
index 6f3faaa5..8f3633f8 100644
--- a/cedar-policy-core/src/evaluator.rs
+++ b/cedar-policy-core/src/evaluator.rs
@@ -3184,7 +3184,6 @@ pub(crate) mod test {
         );
     }
 
-    #[cfg(feature = "datetime")]
     #[test]
     fn interpret_datetime_extension_compares() {
         let request = basic_request();
diff --git a/cedar-policy-core/src/parser/cst_to_ast.rs b/cedar-policy-core/src/parser/cst_to_ast.rs
index 81ac709e..c801799e 100644
--- a/cedar-policy-core/src/parser/cst_to_ast.rs
+++ b/cedar-policy-core/src/parser/cst_to_ast.rs
@@ -841,6 +841,7 @@ enum PrincipalOrResource {
     Resource(ResourceConstraint),
 }
 
+#[derive(Debug, Clone, Copy)]
 enum TolerantAstSetting {
     NotTolerant,
     #[cfg(feature = "tolerant-ast")]
@@ -5864,12 +5865,9 @@ mod tests {
         policyset
             .get(&ast::PolicyID::from_string("policy2"))
             .expect("should be a policy");
-        assert_eq!(
-            policyset
-                .get(&ast::PolicyID::from_string("policy3"))
-                .is_none(),
-            true
-        );
+        assert!(policyset
+            .get(&ast::PolicyID::from_string("policy3"))
+            .is_none());
     }
 
     #[cfg(feature = "tolerant-ast")]
diff --git a/cedar-policy-validator/Cargo.toml b/cedar-policy-validator/Cargo.toml
index c9f62bb2..23006fdc 100644
--- a/cedar-policy-validator/Cargo.toml
+++ b/cedar-policy-validator/Cargo.toml
@@ -35,7 +35,7 @@ wasm-bindgen = { version = "0.2.97", optional = true }
 
 [features]
 # by default, enable all Cedar extensions
-default = ["ipaddr", "decimal"]
+default = ["ipaddr", "decimal", "datetime"]
 # when enabling a feature, make sure that the Core feature is also enabled
 ipaddr = ["cedar-policy-core/ipaddr"]
 decimal = ["cedar-policy-core/decimal"]
diff --git a/cedar-policy-validator/src/schema.rs b/cedar-policy-validator/src/schema.rs
index ab4c8168..2b0f5377 100644
--- a/cedar-policy-validator/src/schema.rs
+++ b/cedar-policy-validator/src/schema.rs
@@ -3109,7 +3109,6 @@ pub(crate) mod test {
                     .build());
         });
 
-        #[cfg(feature = "datetime")]
         {
             let src: serde_json::Value = json!({
                 "": {
diff --git a/cedar-policy/Cargo.toml b/cedar-policy/Cargo.toml
index 716d36ba..bc871f41 100644
--- a/cedar-policy/Cargo.toml
+++ b/cedar-policy/Cargo.toml
@@ -39,7 +39,7 @@ prost-build = { version = "0.13", optional = true }
 
 [features]
 # by default, enable all Cedar extensions, but not other crate features
-default = ["ipaddr", "decimal"]
+default = ["ipaddr", "decimal", "datetime"]
 
 # Cedar extensions
 ipaddr = ["cedar-policy-core/ipaddr", "cedar-policy-validator/ipaddr"]
@@ -52,7 +52,7 @@ corpus-timing = []
 
 # Experimental features.
 # Enable all experimental features with `cargo build --features "experimental"`
-experimental = ["partial-eval", "permissive-validate", "partial-validate", "level-validate", "entity-manifest", "protobufs", "datetime", "tolerant-ast", "extended-schema"]
+experimental = ["partial-eval", "permissive-validate", "partial-validate", "level-validate", "entity-manifest", "protobufs", "tolerant-ast", "extended-schema"]
 entity-manifest = ["cedar-policy-validator/entity-manifest"]
 partial-eval = ["cedar-policy-core/partial-eval", "cedar-policy-validator/partial-eval"]
 permissive-validate = []


Test patch:
diff --git a/cedar-policy-validator/src/typecheck/test/expr.rs b/cedar-policy-validator/src/typecheck/test/expr.rs
index 516c1cb1..976c1f5f 100644
--- a/cedar-policy-validator/src/typecheck/test/expr.rs
+++ b/cedar-policy-validator/src/typecheck/test/expr.rs
@@ -1353,7 +1353,6 @@ fn is_typechecks() {
     );
 }
 
-#[cfg(feature = "datetime")]
 mod datetime {
     use cedar_policy_core::{
         ast::{Expr, Name, Value},
diff --git a/cedar-policy/src/test/test.rs b/cedar-policy/src/test/test.rs
index 9bf3d470..c6e5f974 100644
--- a/cedar-policy/src/test/test.rs
+++ b/cedar-policy/src/test/test.rs
@@ -6563,7 +6563,7 @@ mod policy_manipulation_functions_tests {
         assert_entity_sub(
             r#"permit(principal, action, resource) when { User::"Alice".lessThan(User::"Alice") };"#,
             r#"permit(principal, action, resource) when { User::"Bob".lessThan(User::"Bob") };"#,
-            mapping.clone(),
+            mapping,
         );
     }
 
@@ -6580,19 +6580,19 @@ mod policy_manipulation_functions_tests {
             ),
         )];
         assert_entity_sub(
-            r#"permit(principal, action, resource) when { 1 };"#,
-            r#"permit(principal, action, resource) when { 1 };"#,
+            r"permit(principal, action, resource) when { 1 };",
+            r"permit(principal, action, resource) when { 1 };",
             mapping.clone(),
         );
         assert_entity_sub(
-            r#"permit(principal, action, resource) when { false };"#,
-            r#"permit(principal, action, resource) when { false };"#,
+            r"permit(principal, action, resource) when { false };",
+            r"permit(principal, action, resource) when { false };",
             mapping.clone(),
         );
         assert_entity_sub(
             r#"permit(principal, action, resource) when { "foo" };"#,
             r#"permit(principal, action, resource) when { "foo" };"#,
-            mapping.clone(),
+            mapping,
         );
     }