How should we indicate, at the top-level, whether an evaluation is partial or full with a given result?
{
"decision": {
"operator": "allow"
}
}
{
"decision": {
"operator": "deny"
}
}
Given that operators can be nested; how should the below case be interpreted though?
{
"decision": {
"operator": "or",
"terms": [
{
"operator": "eq",
"field": "author",
"value": "bob@example.com"
},
{
"operator": "allow"
}
]
}
}
An operator can be introduced that always returns a fixed value; which can then be used to indicate allow or deny decisions.
{
"decision": {
"operator": "fixedValue",
"value" : false
}
}
The equality operator could be used to create the equivalent of WHERE 1 == 2
.
{
"decision": {
"operator": "eq",
"field": "1",
"value" : "2"
}
}
A top-level object could be introduced to explicitly describe the type of decision.
{
"decision": {
"result-type": "allow"
}
}
{
"decision": {
"result-type": "deny"
}
}
{
"decision": {
"result-type": "partial",
"residual-filter": {
"operator": "eq",
"field": "author",
"value": "bob@example.com"
}
}
}
How do we want do enable multiple operators to be logically combined with and/or/not/xor logic etc.
{
"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"
}
}
]
}
]
}
{
"or": [
{
"operator": "eq",
"field": "author",
"value": "bob@example.com"
},
{
"and": [
{
"operator": "eq",
"field": "public",
"value": true
},
{ "not": {
"operator": "in",
"field": "tags",
"value": "sensitive"
}
}
]
}
]
}
How do we want to enable custom operators not defined by AuthZEN standard itself?
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"
}
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"
}
{
"operator": "eq",
"field": "lowercase(author)",
"value": "bob@example.com"
}
Question: do we allow multiple fields there? So e.g.
{
"operator": "eq",
"field": "concat(username,\"@\",domain)",
"value": "bob@example.com"
}
Question: do we allow other operators there as well? So e.g.
{
"operator": "eq",
"field": "not(length(author)>99)",
"value": true
}
{
"operator": "eq",
"field": {
"operator": "lowercase",
"value": "author"
},
"value": "bob@example.com"
}
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).
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:
{
"operator": "eq",
"field": "${author}",
"value": "bob@example.com"
}
{
"operator": "eq",
"field": "lowercase(${author})",
"value": "bob@example.com"
}
{
"operator": "in",
"field": "merge(${author},${editors})",
"value": "bob@example.com"
}
{
"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
field
vs value
conventionAnother 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
{
"operator": "eq",
"field": "author",
"value": "bob@example.com"
}
{
"operator": "eq",
"field": {
"operator": "lowercase",
"field": "author"
},
"value": {
"operator": "lowercase",
"value": "Bob@example.com"
}
}
{
"operator": "in",
"field": {
"operator": "merge",
"fields": ["author","editors"]
},
"value": "bob@example.com"
}
{
"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.
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.
{
"operator": "eq",
"firstValue": {
"operator": "field",
"name": "author"
},
"secondValue": "bob@example.com"
}
{
"operator": "eq",
"firstValue": {
"operator": "lowercase",
"value": {
"operator": "field",
"name": "author"
}
},
"secondValue": {
"operator": "lowercase",
"value": "Bob@example.com"
}
}
{
"operator": "in",
"firstValue": {
"operator": "merge",
"lists": [
{
"operator": "field",
"name": "author"
},
{
"operator": "field",
"name": "editors"
}
]
},
"secondValue": "bob@example.com"
}
{
"operator": "eq",
"firstValue": {
"operator": "concat",
"values": [
{
"operator": "field",
"name": "username"
},
"@",
{
"operator": "field",
"name": "domain"
}
]
},
"secondValue": "bob@example.com"
}