Skip to content

feat(schema): accept empty principal/resource lists in human schema#2311

Draft
olehbozhok wants to merge 1 commit intocedar-policy:mainfrom
olehbozhok:feat/human-schema-empty-principal
Draft

feat(schema): accept empty principal/resource lists in human schema#2311
olehbozhok wants to merge 1 commit intocedar-policy:mainfrom
olehbozhok:feat/human-schema-empty-principal

Conversation

@olehbozhok
Copy link
Copy Markdown

@olehbozhok olehbozhok commented Apr 14, 2026

Description of changes

Align the human-readable schema parser with RFC 55 semantics, which already define an empty principal / resource list as "the action applies to no entities of that kind" and are honored by the JSON parser and the validator. Before this change, the human parser alone rejected principal: [] / resource: [] with "is '[]', which is invalid", breaking JSON ⇄ human round-tripping and forcing downstream users of partial authorization (e.g. multi-issuer flows calling is_authorized_partial) to declare a sentinel entity solely to pacify the parser.

What changes:

  • to_json_schema.rs: accept an empty entity_tys and lower it to principal_types: vec![] / resource_types: vec![].
  • err.rs: drop the MissingOrEmpty::Empty variant and the empty_principal / empty_resource constructors. NoPrincipalOrResource now covers only the still-rejected "clause omitted" case. Help text updated to suggest principal: [] when that is the author's intent.
  • fmt.rs: when principal_types or resource_types is empty, emit the explicit [] form rather than suppressing the entire appliesTo block. Restores round-trippability for JSON schemas that use empty lists.
  • test.rs: invert empty_principal / empty_resource rejection assertions into acceptance assertions; add a both_empty test; update print_actions to assert the new formatter output.

Scope guarantees:

  • Omitting the principal / resource clause entirely remains a parse error, per RFC 55.
  • No change to JSON schema parsing, validator, evaluator, or authorization APIs.
  • No currently-valid schema changes meaning. No currently-valid schema becomes invalid.

This is the reference implementation for cedar-policy/rfcs#113. Please do not merge until that RFC is accepted; I'm opening this PR as a draft so maintainers have code to discuss alongside the RFC.

Issue #, if available

Related: #1335 (improved the error message for this case but did not revisit the rejection), #351 (predecessor discussion, requires-RFC).

Checklist for requesting a review

The change in this PR is:

  • A change "invisible" to users (e.g., documentation, changes to "internal" crates like cedar-policy-core, cedar-validator, etc.)

Note: marked as the closest-fitting option because this is a human-schema parser change in cedar-policy-core, with no cedar-policy Rust API change. It is a language-level behavior change (a schema form that used to fail to parse now parses), so I have marked the CHANGELOG entry with (*) per the repo convention.

I confirm that this PR:

  • Updates the "Unreleased" section of the CHANGELOG with a description of my change (required for major/minor version bumps).

I confirm that cedar-spec:

  • I'm not sure how my change impacts cedar-spec.

The formal model in cedar-spec covers authorization; the human-schema parser is outside that scope, but I'd like confirmation from maintainers whether the Lean formalization of the schema surface syntax needs updating.

I confirm that docs.cedarpolicy.com:

  • 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. PRs should be targeted at a staging-X.Y branch, not main.)

Once this PR and RFC #113 are accepted, I will open a companion PR in cedar-docs updating the schema-syntax reference to document the accepted principal: [] / resource: [] form and the motivating partial-authorization use case.

Align the human-readable schema parser with RFC 55 semantics, which
already defines an empty principal/resource list as "the action applies
to no entities of that kind" and is honored by the JSON parser and the
validator. Before this change, the human parser alone rejected
`principal: []` / `resource: []` with "is `[]`, which is invalid",
breaking JSON-to-human round-tripping and forcing downstream users of
partial authorization (e.g. multi-issuer flows calling
`is_authorized_partial`) to declare a sentinel entity solely to pacify
the parser.

Changes:
- `to_json_schema.rs`: accept an empty `entity_tys` and lower it to
  `principal_types: vec![]` / `resource_types: vec![]`.
- `err.rs`: drop the `MissingOrEmpty::Empty` variant and the
  `empty_principal` / `empty_resource` constructors. `NoPrincipalOrResource`
  now covers only the still-rejected "clause omitted" case. Help text
  updated to point users at `principal: []` when that is the intent.
- `fmt.rs`: when `principal_types` or `resource_types` is empty, emit
  the explicit `[]` form rather than suppressing the entire `appliesTo`
  block, restoring round-trippability for JSON schemas that use empty
  lists.
- `test.rs`: invert `empty_principal` / `empty_resource` rejection
  assertions into acceptance assertions; add a `both_empty` test; update
  `print_actions` to assert the new formatter output.

Omitting the `principal` / `resource` clause entirely remains a parse
error, per RFC 55.

No change to JSON schema parsing, validator, evaluator, or authorization
APIs. No currently-valid schema changes meaning; no currently-valid
schema becomes invalid.

Reference implementation for cedar-policy/rfcs#113.

Signed-off-by: Oleh <6554798+olehbozhok@users.noreply.github.com>
@olehbozhok olehbozhok marked this pull request as draft April 14, 2026 18:09
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