cedar-policy / cedar

Implementation of the Cedar Policy Language
https://www.cedarpolicy.com
Apache License 2.0
830 stars 71 forks source link

Converted JSON schemas use "EntityOrCommon" #1161

Open khieta opened 2 weeks ago

khieta commented 2 weeks ago

Describe the improvement you'd like to request

Due to recent changes introduced on main (which are currently unreleased, but will be released as part of 4.0), converting a Cedar schema to JSON will now introduce "EntityOrCommon" types. These seems like an internal detail that is not useful to expose to users. Is there a way to hide this detail when returning JSON data from SchemaFragment::to_json_string?

As an example, here's a snippet from the translation of the TinyTodo schema:

{
  "": {
    "commonTypes": {
      "Task": {
        "type": "Record",
        "attributes": {
          "id": {
            "type": "EntityOrCommon",
            "name": "Long"
          },
          "name": {
            "type": "EntityOrCommon",
            "name": "String"
          },
          "state": {
            "type": "EntityOrCommon",
            "name": "String"
          }
        }
      },
      "Tasks": {
        "type": "Set",
        "element": {
          "type": "EntityOrCommon",
          "name": "Task"
        }
      }
    },
    "entityTypes": {
      "Team": {
        "memberOfTypes": [
          "Team",
          "Application"
        ]
      },
      "User": {
        "memberOfTypes": [
          "Team",
          "Application"
        ],
        "shape": {
          "type": "Record",
          "attributes": {
            "joblevel": {
              "type": "EntityOrCommon",
              "name": "Long"
            },
            "location": {
              "type": "EntityOrCommon",
              "name": "String"
            }
          }
        }
      },
...

The more natural way for a user to write this would be:

{
  "": {
    "commonTypes": {
      "Task": {
        "type": "Record",
        "attributes": {
          "id": {
            "type": "Long"
          },
          "name": {
            "type": "String"
          },
          "state": {
            "type": "String"
          }
        }
      },
      "Tasks": {
        "type": "Set",
        "element": {
          "type": "Task"
        }
      }
    },
    "entityTypes": {
      "Team": {
        "memberOfTypes": [
          "Team",
          "Application"
        ]
      },
      "User": {
        "memberOfTypes": [
          "Team",
          "Application"
        ],
        "shape": {
          "type": "Record",
          "attributes": {
            "joblevel": {
              "type": "Long"
            },
            "location": {
              "type": "String"
            }
          }
        }
      },
...

Describe alternatives you've considered

No response

Additional context

Related: the Display trait for the Cedar schema format is also not as pretty as it could be. See #682.

Is this something that you'd be interested in working on?

cdisselkoen commented 2 weeks ago

some context: in some ways, EntityOrCommon is more correct than the previous status quo. The Cedar syntax Long will actually refer to an entity type Long if it exists, in preference to the builtin type Long, as specified by RFC 24. (This is why RFC 24 introduced the __cedar::Long notation in the first place.) This remains true after #1150, which only introduced restrictions on the names of common types, not entity types. So, translating Cedar syntax Long to JSON EntityOrCommon is an accurate reflection of the semantics of the Cedar syntax.

To resolve this issue, we would have to actually resolve the typenames in the Cedar syntax (e.g., to know that Long does indeed refer to the builtin type Long) in order to write a more accurate JSON-syntax typename.