Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ and the rest of the request payload is byte-for-byte identical.

See [AVP compatibility](#avp-compatibility) for the per-key compatibility
matrix and [Unsupported features](#unsupported-features) for the known
gaps (`datetime` / `duration`, entity tags, policy templates, schema
validation, dynamic identity sources).
gaps (entity tags, policy templates, schema validation, dynamic identity
sources).

## API overview

Expand Down Expand Up @@ -249,6 +249,8 @@ Both methods accept the same keys as the corresponding AVP API:
['boolean' => true]
['ipaddr' => '10.0.0.1']
['decimal' => '12.3400']
['datetime' => '2026-01-01T00:00:00Z']
['duration' => '1d12h']
['entityIdentifier' => ['entityType' => 'MyApp::User', 'entityId' => 'bob']]
['set' => [AttributeValue, ...]]
['record' => [name => AttributeValue, ...]]
Expand Down Expand Up @@ -340,9 +342,6 @@ The Cedar evaluator follows the feature set bundled from upstream
nxe-cedar. The following features are **not** available in this
release:

- `datetime` / `duration` `AttributeValue` types and their methods
(`<.`, `≤.`, `≥.`, `>.`, `toDate`, ...). Pass them as `long` (Unix
timestamps) and use `<`, `<=`, `>=`, `>` instead.
- Entity tags (`.hasTag()` / `.getTag()`).
- Policy templates (`?principal`, `?resource`) and template-linked
policies.
Expand All @@ -352,9 +351,10 @@ release:
extension delegates that to the caller (see
[Token verification](#token-verification-is-callers-responsibility)).

A malformed or unsupported `AttributeValue` (for example
`['datetime' => '...']`) does not abort the request: the entry is
skipped and an entry is appended to the response's `errors[]`. This
A malformed or unsupported `AttributeValue` (for example an unknown
union key, or `['datetime' => 'not-a-date']`) does not abort the
request: the entry is skipped and an entry is appended to the
response's `errors[]`. This
matches AVP's behavior of returning a successful response with
populated `errors` when a single attribute is broken.

Expand Down
37 changes: 36 additions & 1 deletion cedar.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,26 @@ cedar_apply_top_attr(php_cedar_eval_ctx_t *ctx, cedar_attr_target_t tgt,
}
return PHP_CEDAR_ERROR;
}
if (zend_string_equals_literal(kind, "datetime")) {
if (cedar_zval_to_cedar_str(inner, &v) != PHP_CEDAR_OK) return PHP_CEDAR_ERROR;
switch (tgt) {
case CEDAR_TARGET_PRINCIPAL: return php_cedar_eval_ctx_add_principal_attr_datetime(ctx, name, &v);
case CEDAR_TARGET_ACTION: return php_cedar_eval_ctx_add_action_attr_datetime (ctx, name, &v);
case CEDAR_TARGET_RESOURCE: return php_cedar_eval_ctx_add_resource_attr_datetime (ctx, name, &v);
case CEDAR_TARGET_CONTEXT: return php_cedar_eval_ctx_add_context_attr_datetime (ctx, name, &v);
}
return PHP_CEDAR_ERROR;
}
if (zend_string_equals_literal(kind, "duration")) {
if (cedar_zval_to_cedar_str(inner, &v) != PHP_CEDAR_OK) return PHP_CEDAR_ERROR;
switch (tgt) {
case CEDAR_TARGET_PRINCIPAL: return php_cedar_eval_ctx_add_principal_attr_duration(ctx, name, &v);
case CEDAR_TARGET_ACTION: return php_cedar_eval_ctx_add_action_attr_duration (ctx, name, &v);
case CEDAR_TARGET_RESOURCE: return php_cedar_eval_ctx_add_resource_attr_duration (ctx, name, &v);
case CEDAR_TARGET_CONTEXT: return php_cedar_eval_ctx_add_context_attr_duration (ctx, name, &v);
}
return PHP_CEDAR_ERROR;
}
if (zend_string_equals_literal(kind, "entityIdentifier")) {
php_cedar_str_t et, eid;
if (cedar_pick_entity_ids(inner,
Expand Down Expand Up @@ -558,7 +578,6 @@ cedar_apply_top_attr(php_cedar_eval_ctx_t *ctx, cedar_attr_target_t tgt,
if (set == NULL) return PHP_CEDAR_ERROR;
return cedar_apply_set_children(set, inner);
}
/* datetime / duration are not supported (upstream gap). */
return PHP_CEDAR_ERROR;
}

Expand Down Expand Up @@ -598,6 +617,14 @@ cedar_apply_record_attr(php_cedar_record_t *rec,
if (cedar_zval_to_cedar_str(inner, &v) != PHP_CEDAR_OK) return PHP_CEDAR_ERROR;
return php_cedar_record_add_decimal(rec, name, &v);
}
if (zend_string_equals_literal(kind, "datetime")) {
if (cedar_zval_to_cedar_str(inner, &v) != PHP_CEDAR_OK) return PHP_CEDAR_ERROR;
return php_cedar_record_add_datetime(rec, name, &v);
}
if (zend_string_equals_literal(kind, "duration")) {
if (cedar_zval_to_cedar_str(inner, &v) != PHP_CEDAR_OK) return PHP_CEDAR_ERROR;
return php_cedar_record_add_duration(rec, name, &v);
}
if (zend_string_equals_literal(kind, "entityIdentifier")) {
php_cedar_str_t et, eid;
if (cedar_pick_entity_ids(inner,
Expand Down Expand Up @@ -656,6 +683,14 @@ cedar_apply_set_element(php_cedar_set_t *set, zval *attr_val)
if (cedar_zval_to_cedar_str(inner, &v) != PHP_CEDAR_OK) return PHP_CEDAR_ERROR;
return php_cedar_set_add_decimal(set, &v);
}
if (zend_string_equals_literal(kind, "datetime")) {
if (cedar_zval_to_cedar_str(inner, &v) != PHP_CEDAR_OK) return PHP_CEDAR_ERROR;
return php_cedar_set_add_datetime(set, &v);
}
if (zend_string_equals_literal(kind, "duration")) {
if (cedar_zval_to_cedar_str(inner, &v) != PHP_CEDAR_OK) return PHP_CEDAR_ERROR;
return php_cedar_set_add_duration(set, &v);
}
if (zend_string_equals_literal(kind, "entityIdentifier")) {
php_cedar_str_t et, eid;
if (cedar_pick_entity_ids(inner,
Expand Down
5 changes: 2 additions & 3 deletions src/cedar/UPSTREAM.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ symbols and dependencies fit a PHP extension.
## Snapshot commit

- Upstream repository: <https://github.com/kjdev/nxe-cedar>
- Commit SHA: `cd3d1df5c5642a75b27f40fa502022c864272ed3`
- Commit SHA: `4f120bd1d1c05868b09e307f5636c5d52a604a2b` (tag `v0.3.0`)
- Source path: `src/`
- Snapshot date: 2026-05-27
- Snapshot date: 2026-06-01

## File mapping

Expand Down Expand Up @@ -63,7 +63,6 @@ needed, it should go to upstream first and come back via a fresh import.
The features below follow whatever the snapshot supports; gaps listed
here are upstream limitations that this extension does **not** plug:

- No `datetime` / `duration` types or their methods
- No entity tag operators (`hasTag` / `getTag`)
- No policy templates (`?principal`, `?resource`)
- No schema validation
Expand Down
Loading