# Decisions for partial evaluation API
## Top level response options (allow/deny/partial)
How should we indicate, at the top-level, whether an evaluation is partial or full with a given result?
### Deny and allow operators
``` json
{
"decision": {
"operator": "allow"
}
}
```
``` json
{
"decision": {
"operator": "deny"
}
}
```
Given that operators can be nested; how should the below case be interpreted though?
``` json
{
"decision": {
"operator": "or",
"terms": [
{
"operator": "eq",
"field": "author",
"value": "bob@example.com"
},
{
"operator": "allow"
}
]
}
}
```
### Fixed value operator
An operator can be introduced that always returns a fixed value; which can then be used to indicate allow or deny decisions.
``` json
{
"decision": {
"operator": "fixedValue",
"value" : false
}
}
```
### Equality operator
The equality operator could be used to create the equivalent of `WHERE 1 == 2`.
``` json
{
"decision": {
"operator": "eq",
"field": "1",
"value" : "2"
}
}
```
### Top-level decision object with result type
A top-level object could be introduced to explicitly describe the type of decision.
``` json
{
"decision": {
"result-type": "allow"
}
}
```
``` json
{
"decision": {
"result-type": "deny"
}
}
```
``` json
{
"decision": {
"result-type": "partial",
"residual-filter": {
"operator": "eq",
"field": "author",
"value": "bob@example.com"
}
}
}
```
## Enabling logical composition
How do we want do enable multiple operators to be logically combined with and/or/not/xor logic etc.
### Logical composition as 'just another operator'
``` json
{
"operator": "or",
"terms": [
{
"operator": "eq",
"field": "author",
"value": "bob@example.com"
},
{
"operator": "and",
"terms": [
{
"operator": "eq",
"field": "public",
"value": true
},
{
"operator": "not",
"term": {
"operator": "in",
"field": "tags",
"value": "sensitive"
}
}
]
}
]
}
```
### Special casing for logical composition
``` json
{
"or": [
{
"operator": "eq",
"field": "author",
"value": "bob@example.com"
},
{
"and": [
{
"operator": "eq",
"field": "public",
"value": true
},
{ "not": {
"operator": "in",
"field": "tags",
"value": "sensitive"
}
}
]
}
]
}
```
## Custom operators
How do we want to enable custom operators not defined by AuthZEN standard itself?
### Namespaced operator names
Define a mechanism for namespacing; such as dot notation, and reserve the main namespace for AuthZEN
For example
```
{
"operator": "eq"
}
```
and
```
{
"operator": "org.fhir.query",
"query": "Patient?_has:Observation:patient:_has:AuditEvent:entity:agent:Practitioner.name=janedoe"
}
```
### Namespacing field
Define a dedicated field in the operator object to indicate the source of the operator.
The fieldname could be something like `source`, `module` or just `namespace`.
Third party operators would then look something like this:
```
{
"namespace": "org.fhir"
"operator": "query",
"query": "Patient?_has:Observation:patient:_has:AuditEvent:entity:agent:Practitioner.name=janedoe"
}
```
And AuthZEN's own operators would be taken as default value.
```
{
"operator": "eq"
}
```
is equivalent to
```
{
"namespace": "net.openid.authzen",
"operator": "eq"
}
```
## Function composition
### String expressions in regular operators
``` json
{
"operator": "eq",
"field": "lowercase(author)",
"value": "bob@example.com"
}
```
Question: do we allow multiple fields there? So e.g.
``` json
{
"operator": "eq",
"field": "concat(username,\"@\",domain)",
"value": "bob@example.com"
}
```
Question: do we allow other operators there as well? So e.g.
``` json
{
"operator": "eq",
"field": "not(length(author)>99)",
"value": true
}
```
### Nested operators
``` json
{
"operator": "eq",
"field": {
"operator": "lowercase",
"value": "author"
},
"value": "bob@example.com"
}
```
## Differentiating between values and references to fields/variables
When allowing operators to be composed/nested the inputs to operators can sometimes by values and sometimes references to fields. For example when you concatenate fieds together into a URL or email; concat(username,"@",domain).
### Placeholder syntax
We can specify explicitly which values are references to a field/variable by e.g placing it inside a `${...}` block or something of that sort.
Then you would get examples like this:
``` json
{
"operator": "eq",
"field": "${author}",
"value": "bob@example.com"
}
```
``` json
{
"operator": "eq",
"field": "lowercase(${author})",
"value": "bob@example.com"
}
```
``` json
{
"operator": "in",
"field": "merge(${author},${editors})",
"value": "bob@example.com"
}
```
``` json
{
"operator": "eq",
"field": "concat(${username},\"@\",${domain})",
"value": "bob@example.com"
}
```
Note: `field` and `value` make less sense as names anymore in this case. `leftHand` and `rightHand` or `first` and `second` would then be more logica
### Nested operators with `field` vs `value` convention
Another way to approach this is to adopt nested operators instead and use the convention that in an operator a `field` is resolved while a `value` is used directly.
This would get you things like
``` json
{
"operator": "eq",
"field": "author",
"value": "bob@example.com"
}
```
``` json
{
"operator": "eq",
"field": {
"operator": "lowercase",
"field": "author"
},
"value": {
"operator": "lowercase",
"value": "Bob@example.com"
}
}
```
``` json
{
"operator": "in",
"field": {
"operator": "merge",
"fields": ["author","editors"]
},
"value": "bob@example.com"
}
```
``` json
{
"operator": "eq",
"field": {
"operator": "concat",
"values": ["??username??","@","??domain??"]
},
"value": "bob@example.com"
}
```
Note: I can't really see how to make the switching between values and references in the concatenation values would work.
### Dedicated "field" operator to resolve fields
You could specify a special operator that resolves fields and assume that everything else is just a value. I've renamed the equality operator fields to 'firstValue' and 'secondValue' for clarity.
``` json
{
"operator": "eq",
"firstValue": {
"operator": "field",
"name": "author"
},
"secondValue": "bob@example.com"
}
```
``` json
{
"operator": "eq",
"firstValue": {
"operator": "lowercase",
"value": {
"operator": "field",
"name": "author"
}
},
"secondValue": {
"operator": "lowercase",
"value": "Bob@example.com"
}
}
```
``` json
{
"operator": "in",
"firstValue": {
"operator": "merge",
"lists": [
{
"operator": "field",
"name": "author"
},
{
"operator": "field",
"name": "editors"
}
]
},
"secondValue": "bob@example.com"
}
```
``` json
{
"operator": "eq",
"firstValue": {
"operator": "concat",
"values": [
{
"operator": "field",
"name": "username"
},
"@",
{
"operator": "field",
"name": "domain"
}
]
},
"secondValue": "bob@example.com"
}
```