Skip to content

Add datetime and duration attribute support#2

Merged
kjdev merged 4 commits into
mainfrom
feat/cedar-datetime-duration
Jun 1, 2026
Merged

Add datetime and duration attribute support#2
kjdev merged 4 commits into
mainfrom
feat/cedar-datetime-duration

Conversation

@kjdev

@kjdev kjdev commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for datetime and duration attribute types in policy expressions and context attributes.
    • Enabled datetime/duration comparisons and arithmetic operations in policies.
    • New methods for datetime and duration values (e.g., toDate(), toMilliseconds()).
  • Documentation

    • Updated README to reflect full support for datetime and duration as supported attribute value types.
  • Tests

    • Added test coverage for datetime/duration attribute handling in authorization decisions.

kjdev added 4 commits June 1, 2026 13:01
Re-snapshot src/cedar/ from upstream tag v0.3.0
(4f120bd1d1c05868b09e307f5636c5d52a604a2b), applying the established
mechanical rewrites (nxe_cedar_ -> php_cedar_, ngx_ types/functions ->
php_cedar_compat equivalents). No new ngx dependencies are introduced,
so php_cedar_compat.* and config.m4 are unchanged.

Brings in the datetime / duration extension types, bare-context record
materialization, attribute/has/in resolution on request entity
literals, total == / != type-mismatch evaluation, lexer error-path
initialization, a make_ip NULL guard, and const-qualified input APIs.
Wire the "datetime" and "duration" union kinds into the three
AttributeValue injection paths (top-level eval context attribute,
record member, set element), mirroring the existing "decimal" handling.
Values are materialized at insertion time; a malformed value makes the
injection API return an error, so the entry is skipped and surfaced in
the response errors[] just like any other unsupported AttributeValue.
Move datetime / duration out of the Unsupported features list, add them
to the AttributeValue union examples, and update the malformed-value
note to reference a genuinely unsupported case.
Add a test exercising datetime / duration through the top-level,
record-member, and set-element paths plus duration method dispatch.
Update the malformed-attribute test to use an unknown union key and an
invalid datetime string now that valid datetime values are accepted.
@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR extends the PHP Cedar extension with full support for datetime and duration attribute values. The changes implement literal parsing with strict validation, method dispatch for date/time/duration conversions and arithmetic, extended operator semantics for equality and ordering, const-correctness across attribute injection APIs, and PHP integration layer updates to recognize and apply these new attribute kinds.

Changes

DateTime and Duration Feature Implementation

Layer / File(s) Summary
Type system contracts
src/cedar/php_cedar_types.h
Token, AST node, and runtime value type enums extended with PHP_CEDAR_TOKEN_DATETIME, PHP_CEDAR_TOKEN_DURATION, PHP_CEDAR_NODE_DATETIME_LITERAL, PHP_CEDAR_NODE_DURATION_LITERAL, and PHP_CEDAR_RVAL_DATETIME/DURATION constants; php_cedar_value_t union gains datetime_val and duration_val int64_t members.
Lexer and parser
src/cedar/php_cedar_lexer.c, src/cedar/php_cedar_parser.c, src/cedar/php_cedar_expr.h
Lexer keywords table recognizes datetime and duration tokens; parser php_cedar_parse_primary() handles datetime(string) and duration(string) expressions with parenthesis validation and star-escape rejection; public expression helper signatures updated to accept const string pointers for IP, decimal, and datetime parsing.
Expression evaluator
src/cedar/php_cedar_expr.c
Datetime parser validates RFC3339 and YYYY-MM-DD formats with leap-year-aware days and timezone offset handling, converting to UTC milliseconds; duration parser accepts unit groups (d, h, m/ms, s) with strict ordering and uniqueness, returning signed milliseconds. Method dispatch adds toDate, toTime conversions for datetime and toMilliseconds, toSeconds, toMinutes, toHours, toDays for duration; datetime arithmetic methods offset and durationSince perform overflow-checked arithmetic. Equality operator removes type-mismatch errors, allowing boolean results via type-agnostic comparison. Ordering operators (<, <=, >, >=) extended from long-only to also support datetime-to-datetime and duration-to-duration comparisons. Entity slot resolution helpers enable attribute access on entity literals matched to request principal/action/resource slots.
Attribute injection APIs
src/cedar/php_cedar_eval.c, src/cedar/php_cedar_eval.h, src/cedar/php_cedar_util.h
All evaluation context, record, and set attribute adders updated to accept const php_cedar_str_t * for name/value/type/id parameters; new eager-parsing helpers php_cedar_eval_ctx_add_*_attr_datetime and *_attr_duration for principal/action/resource/context; new record field adders php_cedar_record_add_datetime and php_cedar_record_add_duration; new set element adders php_cedar_set_add_datetime and php_cedar_set_add_duration. Entity membership helper php_cedar_entity_in_target and scope matching updated for const-correctness.
PHP integration
cedar.c
Functions cedar_apply_top_attr, cedar_apply_record_attr, and cedar_apply_set_element extended to recognize datetime and duration AttributeValue kinds, convert inner values to Cedar strings, and dispatch to corresponding attribute injection functions.
Tests and documentation
README.md, src/cedar/UPSTREAM.md, tests/019-isauthorized-attr-malformed.phpt, tests/036-isauthorized-attr-datetime-duration.phpt
README updated to list datetime and duration as supported AttributeValue union members and removes them from unsupported features section; UPSTREAM.md refreshed with v0.3.0 commit SHA and removes datetime/duration gap. New test 036-isauthorized-attr-datetime-duration.phpt exercises datetime comparisons, duration comparisons, and method dispatch over injected context attributes; test 019 updated to use clearly invalid datetime strings for malformed attribute testing.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • kjdev/php-ext-cedar#1: Establishes the initial PHP Cedar attribute injection layer that this PR extends with full datetime/duration support by removing the prior "unsupported" checks and adding eager-parsing helpers.

Poem

🐰 A rabbit binds the time and tides,
With datetime and duration glides,
Method calls for hours and days,
Constants pure in all the ways,
Now Cedar's claws can grasp the clock!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'Add datetime and duration attribute support' clearly and specifically summarizes the main change: extending the Cedar evaluator to support datetime and duration as AttributeValue union members across all attribute injection points.

✏️ 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 feat/cedar-datetime-duration

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
tests/019-isauthorized-attr-malformed.phpt (1)

17-21: ⚡ Quick win

Keep one malformed datetime case on the context.contextMap path.

This change drops direct coverage of invalid datetime parsing for context attributes, so the new context-side datetime route is no longer exercised in the malformed test. I'd keep one bad datetime entry here in addition to the unsupported/empty cases.

📌 Suggested test tweak
     "context"   => ["contextMap" => [
         "okScalar"    => ["string"      => "hello"],
         "badUnknown"  => ["mysteryType" => "whatever"],
+        "badDatetime" => ["datetime"    => "not-a-valid-datetime"],
         "badEmpty"    => [],
     ]],
🤖 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 `@tests/019-isauthorized-attr-malformed.phpt` around lines 17 - 21, Keep one
malformed datetime case inside the context.contextMap array so the context-side
datetime parsing route is exercised; specifically, add a key (e.g.,
"badDatetime") under the "context" => ["contextMap" => ...] structure with a
datetime-typed attribute containing an invalid value (for example a non-ISO
string) in addition to the existing "badUnknown" and "badEmpty" entries so the
malformed datetime path is still covered by the test.
tests/036-isauthorized-attr-datetime-duration.phpt (1)

11-54: ⚡ Quick win

Add one positive entities.entityList case for the new kinds.

This test proves the context path, but it never asserts that valid datetime / duration values survive the entities.entityList route. Since that is a separate public input shape, a small positive case here would tighten end-to-end coverage for the PHP integration layer.

🧪 Minimal follow-up case
 /* duration methods dispatch on the injected value. */
 $m = new Cedar\PolicyStore("dur");
 $m->loadString("p1", 'permit(principal, action, resource) when { context.window.toHours() == 1 };');
 $cm = new Cedar\AuthorizationClient($m);
 echo "method:", $cm->isAuthorized([
@@
 ])["decision"], PHP_EOL;
+
+$e = new Cedar\PolicyStore("ent");
+$e->loadString("p1",
+    'permit(principal, action, resource) when { principal.createdAt < datetime("2026-06-01T00:00:00Z") && principal.ttl == duration("1h") };');
+$ce = new Cedar\AuthorizationClient($e);
+echo "entity:", $ce->isAuthorized([
+    "policyStoreId" => "ent",
+    "principal" => ["entityType" => "User", "entityId" => "a"],
+    "action"    => ["actionType" => "Action", "actionId" => "x"],
+    "resource"  => ["entityType" => "Doc", "entityId" => "d"],
+    "entities"  => ["entityList" => [[
+        "identifier" => ["entityType" => "User", "entityId" => "a"],
+        "attributes" => [
+            "createdAt" => ["datetime" => "2026-01-01T00:00:00Z"],
+            "ttl"       => ["duration" => "1h"],
+        ],
+    ]]],
+])["decision"], PHP_EOL;
 ?>
 --EXPECT--
 allow: ALLOW
 deny:  DENY
 method:ALLOW
+entity:ALLOW
🤖 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 `@tests/036-isauthorized-attr-datetime-duration.phpt` around lines 11 - 54, Add
a small positive test that sends datetime/duration values via the
entities.entityList input shape and asserts authorization succeeds; update the
test near the existing $req closure and the $c->isAuthorized calls by creating a
new request (similar to $req or the final anonymous request) that uses
"entities" => ["entityList" => [ ... ]] with the same "contextMap" entries
("now" datetime, "window" duration, etc.) and call $c->isAuthorized(...) or
$cm->isAuthorized(...) to echo or assert an "allow" decision so the path through
entities.entityList is exercised for datetime/duration values. Ensure you
reference the existing policyStore IDs ("dt" or "dur") and reuse the permit
policy used by loadString("p1") so the test is positive.
🤖 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.

Nitpick comments:
In `@tests/019-isauthorized-attr-malformed.phpt`:
- Around line 17-21: Keep one malformed datetime case inside the
context.contextMap array so the context-side datetime parsing route is
exercised; specifically, add a key (e.g., "badDatetime") under the "context" =>
["contextMap" => ...] structure with a datetime-typed attribute containing an
invalid value (for example a non-ISO string) in addition to the existing
"badUnknown" and "badEmpty" entries so the malformed datetime path is still
covered by the test.

In `@tests/036-isauthorized-attr-datetime-duration.phpt`:
- Around line 11-54: Add a small positive test that sends datetime/duration
values via the entities.entityList input shape and asserts authorization
succeeds; update the test near the existing $req closure and the
$c->isAuthorized calls by creating a new request (similar to $req or the final
anonymous request) that uses "entities" => ["entityList" => [ ... ]] with the
same "contextMap" entries ("now" datetime, "window" duration, etc.) and call
$c->isAuthorized(...) or $cm->isAuthorized(...) to echo or assert an "allow"
decision so the path through entities.entityList is exercised for
datetime/duration values. Ensure you reference the existing policyStore IDs
("dt" or "dur") and reuse the permit policy used by loadString("p1") so the test
is positive.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 33d72240-617a-4655-8a3e-f0ff01d058dc

📥 Commits

Reviewing files that changed from the base of the PR and between e757712 and ce6b211.

📒 Files selected for processing (13)
  • README.md
  • cedar.c
  • src/cedar/UPSTREAM.md
  • src/cedar/php_cedar_eval.c
  • src/cedar/php_cedar_eval.h
  • src/cedar/php_cedar_expr.c
  • src/cedar/php_cedar_expr.h
  • src/cedar/php_cedar_lexer.c
  • src/cedar/php_cedar_parser.c
  • src/cedar/php_cedar_types.h
  • src/cedar/php_cedar_util.h
  • tests/019-isauthorized-attr-malformed.phpt
  • tests/036-isauthorized-attr-datetime-duration.phpt

@kjdev kjdev changed the title Feat cedar datetime duration Add datetime and duration attribute support Jun 1, 2026
@kjdev kjdev merged commit 65d68c9 into main Jun 1, 2026
7 checks passed
@kjdev kjdev deleted the feat/cedar-datetime-duration branch June 1, 2026 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant