You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@casbin.apache.org by hs...@apache.org on 2026/10/20 17:49:09 UTC

(casbin) branch master updated: feat: add cross-language conformance cases

This is an automated email from the ASF dual-hosted git repository.

hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin.git


The following commit(s) were added to refs/heads/master by this push:
     new 8f5173b  feat: add cross-language conformance cases
8f5173b is described below

commit 8f5173b17bee2675025e7b46c9a8116ee352ec84
Author: Yang Luo <hs...@gmail.com>
AuthorDate: Wed Oct 21 01:49:02 2026 +0800

    feat: add cross-language conformance cases
---
 conformance/README.md                              |   48 +
 conformance/cases/basic.json                       |  257 ++
 conformance/cases/basic__basic_inverse.json        |  257 ++
 .../cases/basic_model_without_spaces__basic.json   |  257 ++
 conformance/cases/basic_with_root__basic.json      |  257 ++
 conformance/cases/basic_without_resources.json     |   84 +
 conformance/cases/basic_without_users.json         |   84 +
 conformance/cases/comment__basic.json              |  257 ++
 conformance/cases/eval_operator.json               |  586 ++++
 conformance/cases/glob.json                        |  476 +++
 conformance/cases/ipmatch.json                     | 2718 ++++++++++++++++
 conformance/cases/keymatch.json                    |  926 ++++++
 conformance/cases/keymatch2.json                   |  122 +
 .../cases/keymatch_with_rbac_in_domain.json        | 3246 +++++++++++++++++++
 conformance/cases/orbac.json                       | 3286 ++++++++++++++++++++
 conformance/cases/priority.json                    | 2246 +++++++++++++
 .../cases/priority__priority_indeterminate.json    |   78 +
 ...y_model_explicit__priority_policy_explicit.json | 2754 ++++++++++++++++
 conformance/cases/rbac.json                        |  930 ++++++
 conformance/cases/rbac__rbac_with_hierarchy.json   | 2704 ++++++++++++++++
 .../cases/rbac_model_in_multi_line__rbac.json      |  930 ++++++
 .../rbac_model_matcher_using_in_op__rbac.json      |  990 ++++++
 ...ac_model_matcher_using_in_op_bracket__rbac.json |  990 ++++++
 conformance/cases/rbac_with_deny.json              |  936 ++++++
 .../cases/rbac_with_different_types_of_roles.json  | 2846 +++++++++++++++++
 conformance/cases/rbac_with_domains.json           | 3046 ++++++++++++++++++
 ...ac_with_domains__rbac_with_domains_policy2.json | 3066 ++++++++++++++++++
 ..._domains__rbac_with_hierarchy_with_domains.json | 3046 ++++++++++++++++++
 conformance/cases/rbac_with_multiple_policy.json   | 1466 +++++++++
 .../cases/rbac_with_not_deny__rbac_with_deny.json  |  911 ++++++
 conformance/cases/rbac_with_resource_roles.json    | 2738 ++++++++++++++++
 conformance/cases/rebac.json                       | 2726 ++++++++++++++++
 conformance/cases/subject_priority.json            | 2726 ++++++++++++++++
 ...omain__subject_priority_policy_with_domain.json | 3024 ++++++++++++++++++
 conformance/data/basic_inverse_policy.csv          |    2 +
 conformance/data/basic_model.conf                  |   11 +
 conformance/data/basic_model_without_spaces.conf   |   11 +
 conformance/data/basic_policy.csv                  |    2 +
 conformance/data/basic_with_root_model.conf        |   11 +
 .../data/basic_without_resources_model.conf        |   11 +
 .../data/basic_without_resources_policy.csv        |    2 +
 conformance/data/basic_without_users_model.conf    |   11 +
 conformance/data/basic_without_users_policy.csv    |    2 +
 conformance/data/comment_model.conf                |   12 +
 conformance/data/eval_operator_model.conf          |   11 +
 conformance/data/eval_operator_policy.csv          |    1 +
 conformance/data/glob_model.conf                   |   11 +
 conformance/data/glob_policy.csv                   |    4 +
 conformance/data/ipmatch_model.conf                |   11 +
 conformance/data/ipmatch_policy.csv                |    2 +
 conformance/data/keymatch2_model.conf              |   11 +
 conformance/data/keymatch2_policy.csv              |    2 +
 conformance/data/keymatch_model.conf               |   11 +
 conformance/data/keymatch_policy.csv               |    7 +
 conformance/data/keymatch_with_rbac_in_domain.conf |   14 +
 conformance/data/keymatch_with_rbac_in_domain.csv  |    6 +
 conformance/data/orbac_model.conf                  |   16 +
 conformance/data/orbac_policy.csv                  |   25 +
 conformance/data/priority_indeterminate_policy.csv |    1 +
 conformance/data/priority_model.conf               |   14 +
 conformance/data/priority_model_explicit.conf      |   14 +
 conformance/data/priority_policy.csv               |   12 +
 conformance/data/priority_policy_explicit.csv      |   12 +
 conformance/data/rbac_model.conf                   |   14 +
 conformance/data/rbac_model_in_multi_line.conf     |   15 +
 .../data/rbac_model_matcher_using_in_op.conf       |   14 +
 .../rbac_model_matcher_using_in_op_bracket.conf    |   14 +
 conformance/data/rbac_policy.csv                   |    5 +
 conformance/data/rbac_with_deny_model.conf         |   14 +
 conformance/data/rbac_with_deny_policy.csv         |    7 +
 .../rbac_with_different_types_of_roles_model.conf  |   15 +
 .../rbac_with_different_types_of_roles_policy.csv  |   12 +
 conformance/data/rbac_with_domains_model.conf      |   14 +
 conformance/data/rbac_with_domains_policy.csv      |    6 +
 conformance/data/rbac_with_domains_policy2.csv     |    9 +
 conformance/data/rbac_with_hierarchy_policy.csv    |   10 +
 .../rbac_with_hierarchy_with_domains_policy.csv    |   11 +
 .../data/rbac_with_multiple_policy_model.conf      |   17 +
 .../data/rbac_with_multiple_policy_policy.csv      |    9 +
 conformance/data/rbac_with_not_deny_model.conf     |   14 +
 .../data/rbac_with_resource_roles_model.conf       |   15 +
 .../data/rbac_with_resource_roles_policy.csv       |    7 +
 conformance/data/rebac_model.conf                  |   15 +
 conformance/data/rebac_policy.csv                  |    7 +
 conformance/data/subject_priority_model.conf       |   14 +
 .../data/subject_priority_model_with_domain.conf   |   14 +
 conformance/data/subject_priority_policy.csv       |   16 +
 .../data/subject_priority_policy_with_domain.csv   |    7 +
 conformance_test.go                                |  295 ++
 89 files changed, 51864 insertions(+)

diff --git a/conformance/README.md b/conformance/README.md
new file mode 100644
index 0000000..ffad7fa
--- /dev/null
+++ b/conformance/README.md
@@ -0,0 +1,48 @@
+# Casbin conformance cases
+
+Shared test cases that every Casbin implementation should pass. They are generated from the Go implementation, which is the reference: each test records what Go's `EnforceEx()` returns for one request.
+
+## Layout
+
+- `data/`: model (`.conf`) and policy (`.csv`) files, copied from `examples/`.
+- `cases/*.json`: one file per model and policy pair:
+
+```json
+{
+  "model": "rbac_model.conf",
+  "policy": "rbac_policy.csv",
+  "tests": [
+    {"request": ["alice", "data1", "read"], "allow": true, "explain": ["alice", "data1", "read"]},
+    {"request": ["bob", "data1", "read"], "allow": false, "explain": []}
+  ]
+}
+```
+
+`model` and `policy` are file names in `data/`. Every request value is a string. `explain` is the policy rule returned by `EnforceEx()`, or `[]` when no rule decided the result.
+
+## Running the cases
+
+Load the enforcer from the two files with the default file adapter, call the implementation's `enforceEx` for every request, and compare both `allow` and `explain`. The Go test is [`conformance_test.go`](../conformance_test.go).
+
+Other implementations read the cases from the directory in the `CASBIN_CONFORMANCE_DIR` environment variable and skip the test when it is not set. In CI, check out this directory from `apache/casbin`:
+
+```yaml
+- uses: actions/checkout@v4
+  with:
+    repository: apache/casbin
+    path: casbin-conformance
+    sparse-checkout: conformance
+- run: <test command>
+  env:
+    CASBIN_CONFORMANCE_DIR: ${{ github.workspace }}/casbin-conformance/conformance
+```
+
+## Regenerating
+
+Add a model and policy pair to `conformanceSources` in `conformance_test.go`, then run:
+
+```shell
+go test -run '^TestConformance$' -update-conformance .
+```
+
+Requests are generated from the values in the policy, and at most 300 are kept per case, half of them allowed where possible.
diff --git a/conformance/cases/basic.json b/conformance/cases/basic.json
new file mode 100644
index 0000000..7ce9158
--- /dev/null
+++ b/conformance/cases/basic.json
@@ -0,0 +1,257 @@
+{
+  "model": "basic_model.conf",
+  "policy": "basic_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "alice",
+        "data1",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "data1",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "write"
+      ],
+      "allow": true,
+      "explain": [
+        "bob",
+        "data2",
+        "write"
+      ]
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/basic__basic_inverse.json b/conformance/cases/basic__basic_inverse.json
new file mode 100644
index 0000000..36c9050
--- /dev/null
+++ b/conformance/cases/basic__basic_inverse.json
@@ -0,0 +1,257 @@
+{
+  "model": "basic_model.conf",
+  "policy": "basic_inverse_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "alice",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data1",
+        "write"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "data1",
+        "write"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "bob",
+        "data2",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/basic_model_without_spaces__basic.json b/conformance/cases/basic_model_without_spaces__basic.json
new file mode 100644
index 0000000..a88988d
--- /dev/null
+++ b/conformance/cases/basic_model_without_spaces__basic.json
@@ -0,0 +1,257 @@
+{
+  "model": "basic_model_without_spaces.conf",
+  "policy": "basic_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "alice",
+        "data1",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "data1",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "write"
+      ],
+      "allow": true,
+      "explain": [
+        "bob",
+        "data2",
+        "write"
+      ]
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/basic_with_root__basic.json b/conformance/cases/basic_with_root__basic.json
new file mode 100644
index 0000000..4d0f77c
--- /dev/null
+++ b/conformance/cases/basic_with_root__basic.json
@@ -0,0 +1,257 @@
+{
+  "model": "basic_with_root_model.conf",
+  "policy": "basic_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "alice",
+        "data1",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "data1",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "write"
+      ],
+      "allow": true,
+      "explain": [
+        "bob",
+        "data2",
+        "write"
+      ]
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/basic_without_resources.json b/conformance/cases/basic_without_resources.json
new file mode 100644
index 0000000..8309151
--- /dev/null
+++ b/conformance/cases/basic_without_resources.json
@@ -0,0 +1,84 @@
+{
+  "model": "basic_without_resources_model.conf",
+  "policy": "basic_without_resources_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "alice",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "write"
+      ],
+      "allow": true,
+      "explain": [
+        "bob",
+        "write"
+      ]
+    },
+    {
+      "request": [
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/basic_without_users.json b/conformance/cases/basic_without_users.json
new file mode 100644
index 0000000..9edb8ed
--- /dev/null
+++ b/conformance/cases/basic_without_users.json
@@ -0,0 +1,84 @@
+{
+  "model": "basic_without_users_model.conf",
+  "policy": "basic_without_users_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "data1",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "data1",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "data2",
+        "write"
+      ],
+      "allow": true,
+      "explain": [
+        "data2",
+        "write"
+      ]
+    },
+    {
+      "request": [
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/comment__basic.json b/conformance/cases/comment__basic.json
new file mode 100644
index 0000000..7b0f321
--- /dev/null
+++ b/conformance/cases/comment__basic.json
@@ -0,0 +1,257 @@
+{
+  "model": "comment_model.conf",
+  "policy": "basic_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "alice",
+        "data1",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "data1",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "data2",
+        "write"
+      ],
+      "allow": true,
+      "explain": [
+        "bob",
+        "data2",
+        "write"
+      ]
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/eval_operator.json b/conformance/cases/eval_operator.json
new file mode 100644
index 0000000..00283db
--- /dev/null
+++ b/conformance/cases/eval_operator.json
@@ -0,0 +1,586 @@
+{
+  "model": "eval_operator_model.conf",
+  "policy": "eval_operator_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "admin",
+        "admin",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "admin",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "admin",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "admin",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "r.obj == 'users'",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "r.obj == 'users'",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "r.obj == 'users'",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "r.obj == 'users'",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "unknown",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "unknown",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "users",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "users",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "users",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "admin",
+        "users",
+        "write"
+      ],
+      "allow": true,
+      "explain": [
+        "r.sub == 'admin' || false",
+        "r.obj == 'users'",
+        "write"
+      ]
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "admin",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "admin",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "admin",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "admin",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "r.obj == 'users'",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "r.obj == 'users'",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "r.obj == 'users'",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "r.obj == 'users'",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "unknown",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "unknown",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "users",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "users",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "users",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "r.sub == 'admin' || false",
+        "users",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "admin",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "admin",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "admin",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "admin",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "r.obj == 'users'",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "r.obj == 'users'",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "r.obj == 'users'",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "r.obj == 'users'",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "users",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "users",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "users",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "users",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "admin",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "admin",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "admin",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "admin",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "r.obj == 'users'",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "r.obj == 'users'",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "r.obj == 'users'",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "r.obj == 'users'",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "unknown",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "unknown",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "users",
+        "admin"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "users",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "users",
+        "users"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "users",
+        "users",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/glob.json b/conformance/cases/glob.json
new file mode 100644
index 0000000..15c2cd5
--- /dev/null
+++ b/conformance/cases/glob.json
@@ -0,0 +1,476 @@
+{
+  "model": "glob_model.conf",
+  "policy": "glob_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "u1",
+        "*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u1",
+        "*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u1",
+        "/*/foo/*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u1",
+        "/*/foo/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u1",
+        "/foo*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u1",
+        "/foo*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u1",
+        "/foo/*",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "u1",
+        "/foo/*",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "u1",
+        "/foo/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u1",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u1",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u2",
+        "*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u2",
+        "*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u2",
+        "/*/foo/*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u2",
+        "/*/foo/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u2",
+        "/foo*",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "u2",
+        "/foo*",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "u2",
+        "/foo*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u2",
+        "/foo/*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u2",
+        "/foo/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u2",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u2",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u3",
+        "*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u3",
+        "*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u3",
+        "/*/foo/*",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "u3",
+        "/*/foo/*",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "u3",
+        "/*/foo/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u3",
+        "/foo*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u3",
+        "/foo*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u3",
+        "/foo/*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u3",
+        "/foo/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u3",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u3",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u4",
+        "*",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "u4",
+        "*",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "u4",
+        "*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u4",
+        "/*/foo/*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u4",
+        "/*/foo/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u4",
+        "/foo*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u4",
+        "/foo*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u4",
+        "/foo/*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u4",
+        "/foo/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "u4",
+        "unknown",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "u4",
+        "*",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "u4",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/*/foo/*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/*/foo/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/foo*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/foo*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/foo/*",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/foo/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/ipmatch.json b/conformance/cases/ipmatch.json
new file mode 100644
index 0000000..923faab
--- /dev/null
+++ b/conformance/cases/ipmatch.json
@@ -0,0 +1,2718 @@
+{
+  "model": "ipmatch_model.conf",
+  "policy": "ipmatch_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "10.0.0.5",
+        "10.0.0.5",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "10.0.0.5",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "10.0.0.5",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "10.0.0.5",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "10.0.0.5",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "10.0.0.5",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "10.0.0.5",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "10.0.0.5",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "127.0.0.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "127.0.0.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "127.0.0.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "127.0.0.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "127.0.0.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "127.0.0.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "127.0.0.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.0.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.0.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.0.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.0.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.0.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.0.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.0.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.0.1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.123",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.123",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.123",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.123",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.123",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.123",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.123",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "192.168.2.123",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data2",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data2",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data2",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data2",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data2",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "data2",
+        "write"
+      ],
+      "allow": true,
+      "explain": [
+        "10.0.0.0/16",
+        "data2",
+        "write"
+      ]
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "unknown",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "unknown",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "unknown",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "unknown",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "unknown",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "10.0.0.5",
+        "unknown",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "10.0.0.5",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "10.0.0.5",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "10.0.0.5",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "10.0.0.5",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "10.0.0.5",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "10.0.0.5",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "10.0.0.5",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "127.0.0.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "127.0.0.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "127.0.0.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "127.0.0.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "127.0.0.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "127.0.0.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "127.0.0.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "127.0.0.1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.0.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.0.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.0.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.0.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.0.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.0.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.0.1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.123",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.123",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.123",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.123",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.123",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.123",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "192.168.2.123",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data2",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data2",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data2",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data2",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data2",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "unknown",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "unknown",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "unknown",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "unknown",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "unknown",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "127.0.0.1",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "10.0.0.5",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "10.0.0.5",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "10.0.0.5",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "10.0.0.5",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "10.0.0.5",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "10.0.0.5",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "10.0.0.5",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "10.0.0.5",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "127.0.0.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "127.0.0.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "127.0.0.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "127.0.0.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "127.0.0.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "127.0.0.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "127.0.0.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.0.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.0.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.0.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.0.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.0.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.0.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.0.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.0.1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.123",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.123",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.123",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.123",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.123",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.123",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.123",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "192.168.2.123",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data2",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data2",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data2",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data2",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data2",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "unknown",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "unknown",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "unknown",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "unknown",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "unknown",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.0.1",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "10.0.0.5",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "10.0.0.5",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "10.0.0.5",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "10.0.0.5",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "10.0.0.5",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "10.0.0.5",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "10.0.0.5",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "10.0.0.5",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "127.0.0.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "127.0.0.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "127.0.0.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "127.0.0.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "127.0.0.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "127.0.0.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "127.0.0.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.0.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.0.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.0.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.0.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.0.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.0.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.0.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.0.1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.123",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.123",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.123",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.123",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.123",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.123",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.123",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "192.168.2.123",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data1",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "192.168.2.0/24",
+        "data1",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data2",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data2",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data2",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data2",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data2",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "unknown",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "unknown",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "unknown",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "unknown",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "unknown",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.1",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "10.0.0.5",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "10.0.0.5",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "10.0.0.5",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "10.0.0.5",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "10.0.0.5",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "10.0.0.5",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "10.0.0.5",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "10.0.0.5",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "127.0.0.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "127.0.0.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "127.0.0.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "127.0.0.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "127.0.0.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "127.0.0.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "127.0.0.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.0.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.0.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.0.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.0.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.0.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.0.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.0.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.0.1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.1",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.123",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.123",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.123",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.123",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.123",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.123",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.123",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "192.168.2.123",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data1",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data1",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data1",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data1",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data1",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data1",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "192.168.2.0/24",
+        "data1",
+        "read"
+      ]
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data1",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data2",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data2",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data2",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data2",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data2",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "data2",
+        "write"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "unknown",
+        "10.0.0.5"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "unknown",
+        "127.0.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "unknown",
+        "192.168.0.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "unknown",
+        "192.168.2.1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "unknown",
+        "192.168.2.123"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "unknown",
+        "read"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "192.168.2.123",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/keymatch.json b/conformance/cases/keymatch.json
new file mode 100644
index 0000000..040903d
--- /dev/null
+++ b/conformance/cases/keymatch.json
@@ -0,0 +1,926 @@
+{
+  "model": "keymatch_model.conf",
+  "policy": "keymatch_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "alice",
+        "/alice_data/*",
+        "(GET)|(POST)"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "/alice_data/*",
+        "GET"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/*",
+        "GET"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "/alice_data/*",
+        "GET"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/*",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/resource1",
+        "(GET)|(POST)"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "/alice_data/*",
+        "GET"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/resource1",
+        "GET"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "/alice_data/*",
+        "GET"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/resource1",
+        "POST"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "/alice_data/resource1",
+        "POST"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/resource1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/resource2",
+        "(GET)|(POST)"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "/alice_data/*",
+        "GET"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/resource2",
+        "GET"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "/alice_data/*",
+        "GET"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/resource2",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/resource2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/bob_data/*",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/bob_data/*",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/bob_data/*",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/bob_data/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/cathy_data",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/cathy_data",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/cathy_data",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/cathy_data",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/*",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/*",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/*",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/resource1",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/resource1",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/resource1",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/resource1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/resource2",
+        "(GET)|(POST)"
+      ],
+      "allow": true,
+      "explain": [
+        "bob",
+        "/alice_data/resource2",
+        "GET"
+      ]
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/resource2",
+        "GET"
+      ],
+      "allow": true,
+      "explain": [
+        "bob",
+        "/alice_data/resource2",
+        "GET"
+      ]
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/resource2",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/alice_data/resource2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/bob_data/*",
+        "(GET)|(POST)"
+      ],
+      "allow": true,
+      "explain": [
+        "bob",
+        "/bob_data/*",
+        "POST"
+      ]
+    },
+    {
+      "request": [
+        "bob",
+        "/bob_data/*",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/bob_data/*",
+        "POST"
+      ],
+      "allow": true,
+      "explain": [
+        "bob",
+        "/bob_data/*",
+        "POST"
+      ]
+    },
+    {
+      "request": [
+        "bob",
+        "/bob_data/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/cathy_data",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/cathy_data",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/cathy_data",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "/cathy_data",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "bob",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/*",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/*",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/*",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/resource1",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/resource1",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/resource1",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/resource1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/resource2",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/resource2",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/resource2",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/alice_data/resource2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/bob_data/*",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/bob_data/*",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/bob_data/*",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/bob_data/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "/cathy_data",
+        "(GET)|(POST)"
+      ],
+      "allow": true,
+      "explain": [
+        "cathy",
+        "/cathy_data",
+        "(GET)|(POST)"
+      ]
+    },
+    {
+      "request": [
+        "cathy",
+        "/cathy_data",
+        "GET"
+      ],
+      "allow": true,
+      "explain": [
+        "cathy",
+        "/cathy_data",
+        "(GET)|(POST)"
+      ]
+    },
+    {
+      "request": [
+        "cathy",
+        "/cathy_data",
+        "POST"
+      ],
+      "allow": true,
+      "explain": [
+        "cathy",
+        "/cathy_data",
+        "(GET)|(POST)"
+      ]
+    },
+    {
+      "request": [
+        "cathy",
+        "/cathy_data",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "unknown",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "unknown",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "unknown",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "cathy",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/*",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/*",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/*",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/resource1",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/resource1",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/resource1",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/resource1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/resource2",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/resource2",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/resource2",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/resource2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/bob_data/*",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/bob_data/*",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/bob_data/*",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/bob_data/*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/cathy_data",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/cathy_data",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/cathy_data",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/cathy_data",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "(GET)|(POST)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "POST"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/keymatch2.json b/conformance/cases/keymatch2.json
new file mode 100644
index 0000000..cd9b080
--- /dev/null
+++ b/conformance/cases/keymatch2.json
@@ -0,0 +1,122 @@
+{
+  "model": "keymatch2_model.conf",
+  "policy": "keymatch2_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "alice",
+        "/alice_data/:resource",
+        "GET"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "/alice_data/:resource",
+        "GET"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data/:resource",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data2/:id/using/:resId",
+        "GET"
+      ],
+      "allow": true,
+      "explain": [
+        "alice",
+        "/alice_data2/:id/using/:resId",
+        "GET"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "/alice_data2/:id/using/:resId",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/:resource",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data/:resource",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data2/:id/using/:resId",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "/alice_data2/:id/using/:resId",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "GET"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/keymatch_with_rbac_in_domain.json b/conformance/cases/keymatch_with_rbac_in_domain.json
new file mode 100644
index 0000000..28aaf37
--- /dev/null
+++ b/conformance/cases/keymatch_with_rbac_in_domain.json
@@ -0,0 +1,3246 @@
+{
+  "model": "keymatch_with_rbac_in_domain.conf",
+  "policy": "keymatch_with_rbac_in_domain.csv",
+  "tests": [
+    {
+      "request": [
+        "*",
+        "*",
+        "*",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "*",
+        "*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "*",
+        "Username==test2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "*",
+        "can_manage",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "*",
+        "can_use",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "*",
+        "engines/engine1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "*",
+        "unknown",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "Username==test2",
+        "*",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "Username==test2",
+        "Username==test2",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "Username==test2",
+        "can_manage",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "Username==test2",
+        "can_use",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "Username==test2",
+        "engines/engine1",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "Username==test2",
+        "unknown",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_manage",
+        "*",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_manage",
+        "Username==test2",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_manage",
+        "can_manage",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_manage",
+        "can_use",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_manage",
+        "engines/engine1",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_manage",
+        "unknown",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_use",
+        "*",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_use",
+        "Username==test2",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_use",
+        "can_manage",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_use",
+        "can_use",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_use",
+        "engines/engine1",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "can_use",
+        "unknown",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/*",
+        "*",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/*",
+        "Username==test2",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/*",
+        "can_manage",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/*",
+        "can_use",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/*",
+        "engines/engine1",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/*",
+        "unknown",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/engine1",
+        "*",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/engine1",
+        "Username==test2",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/engine1",
+        "can_manage",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/engine1",
+        "can_use",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/engine1",
+        "engines/engine1",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "engines/engine1",
+        "unknown",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "unknown",
+        "*",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "unknown",
+        "Username==test2",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "unknown",
+        "can_manage",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "unknown",
+        "can_use",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "unknown",
+        "engines/engine1",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "unknown",
+        "unknown",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "*",
+        "unknown",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "*",
+        "*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "*",
+        "Username==test2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "*",
+        "can_manage",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "*",
+        "can_use",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "*",
+        "engines/engine1",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "*",
+        "unknown",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "Username==test2",
+        "*",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "Username==test2",
+        "Username==test2",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "Username==test2",
+        "can_manage",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "Username==test2",
+        "can_use",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "Username==test2",
+        "engines/engine1",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "Username==test2",
+        "unknown",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_manage",
+        "*",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_manage",
+        "Username==test2",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_manage",
+        "can_manage",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_manage",
+        "can_use",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_manage",
+        "engines/engine1",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_manage",
+        "unknown",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_use",
+        "*",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_use",
+        "Username==test2",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_use",
+        "can_manage",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_use",
+        "can_use",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_use",
+        "engines/engine1",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "can_use",
+        "unknown",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/*",
+        "*",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/*",
+        "Username==test2",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/*",
+        "can_manage",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/*",
+        "can_use",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/*",
+        "engines/engine1",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/*",
+        "unknown",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "*",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "*",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "*",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "Username==test2",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "Username==test2",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "Username==test2",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "can_manage",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "can_manage",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "can_manage",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "can_use",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "can_use",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "engines/engine1",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "engines/engine1",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "engines/engine1",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "unknown",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "unknown",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "Username==test2",
+        "engines/engine1",
+        "unknown",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "unknown",
+        "*",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "unknown",
+        "Username==test2",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "unknown",
+        "can_manage",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "unknown",
+        "can_use",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "unknown",
+        "engines/engine1",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "Username==test2",
+        "unknown",
+        "unknown",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "*",
+        "*",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "*",
+        "Username==test2",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "*",
+        "can_manage",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "*",
+        "can_use",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "*",
+        "engines/engine1",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "*",
+        "unknown",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "Username==test2",
+        "*",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "Username==test2",
+        "Username==test2",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "Username==test2",
+        "can_manage",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "Username==test2",
+        "can_use",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "Username==test2",
+        "engines/engine1",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "Username==test2",
+        "unknown",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_manage",
+        "*",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_manage",
+        "Username==test2",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_manage",
+        "can_manage",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_manage",
+        "can_use",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_manage",
+        "engines/engine1",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_manage",
+        "unknown",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_use",
+        "*",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_use",
+        "Username==test2",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_use",
+        "can_manage",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_use",
+        "can_manage",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_use",
+        "can_use",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_use",
+        "engines/engine1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "can_use",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "Username==test2",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "Username==test2",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "Username==test2",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "can_manage",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "can_manage",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "can_manage",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "can_use",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "can_use",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "can_use",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "engines/engine1",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "engines/engine1",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "unknown",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "unknown",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/*",
+        "unknown",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "*",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "*",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "*",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "Username==test2",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "Username==test2",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "Username==test2",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "can_manage",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "can_manage",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "can_manage",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "can_use",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "can_use",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "engines/engine1",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "engines/engine1",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "engines/engine1",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "unknown",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "unknown",
+        "(pause)|(resume)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_manage",
+        "engines/*",
+        "*",
+        "(pause)|(resume)"
+      ]
+    },
+    {
+      "request": [
+        "can_manage",
+        "engines/engine1",
+        "unknown",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "unknown",
+        "*",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "unknown",
+        "Username==test2",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "unknown",
+        "can_manage",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "unknown",
+        "can_use",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "unknown",
+        "engines/engine1",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_manage",
+        "unknown",
+        "unknown",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "*",
+        "*",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "*",
+        "Username==test2",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "*",
+        "can_manage",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "*",
+        "can_use",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "*",
+        "engines/engine1",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "*",
+        "unknown",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "Username==test2",
+        "*",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "Username==test2",
+        "Username==test2",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "Username==test2",
+        "can_manage",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "Username==test2",
+        "can_use",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "Username==test2",
+        "engines/engine1",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "Username==test2",
+        "unknown",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_manage",
+        "*",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_manage",
+        "Username==test2",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_manage",
+        "can_manage",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_manage",
+        "can_use",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_manage",
+        "engines/engine1",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_manage",
+        "unknown",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_use",
+        "*",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_use",
+        "Username==test2",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_use",
+        "can_manage",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_use",
+        "can_use",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_use",
+        "engines/engine1",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_use",
+        "engines/engine1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "can_use",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/*",
+        "Username==test2",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/*",
+        "Username==test2",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/*",
+        "can_manage",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/*",
+        "can_manage",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/*",
+        "can_use",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/*",
+        "can_use",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/*",
+        "engines/engine1",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/*",
+        "engines/engine1",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/*",
+        "unknown",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/*",
+        "unknown",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/engine1",
+        "*",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/engine1",
+        "*",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/engine1",
+        "Username==test2",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/engine1",
+        "Username==test2",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/engine1",
+        "can_manage",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/engine1",
+        "can_manage",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/engine1",
+        "can_use",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/engine1",
+        "can_use",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/engine1",
+        "engines/engine1",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/engine1",
+        "unknown",
+        "(attach)|(detach)"
+      ],
+      "allow": true,
+      "explain": [
+        "can_use",
+        "engines/*",
+        "*",
+        "(attach)|(detach)"
+      ]
+    },
+    {
+      "request": [
+        "can_use",
+        "engines/engine1",
+        "unknown",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "unknown",
+        "*",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "unknown",
+        "Username==test2",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "unknown",
+        "can_manage",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "unknown",
+        "can_use",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "unknown",
+        "engines/engine1",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "can_use",
+        "unknown",
+        "unknown",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "*",
+        "*",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "*",
+        "Username==test2",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "*",
+        "can_manage",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "*",
+        "can_manage",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "*",
+        "can_use",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "*",
+        "engines/engine1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "*",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "Username==test2",
+        "*",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "Username==test2",
+        "Username==test2",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "Username==test2",
+        "can_manage",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "Username==test2",
+        "can_use",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "Username==test2",
+        "engines/engine1",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "Username==test2",
+        "unknown",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_manage",
+        "*",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_manage",
+        "Username==test2",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_manage",
+        "can_manage",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_manage",
+        "can_use",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_manage",
+        "engines/engine1",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_manage",
+        "unknown",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_use",
+        "*",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_use",
+        "Username==test2",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_use",
+        "can_manage",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_use",
+        "can_use",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_use",
+        "engines/engine1",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "can_use",
+        "unknown",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/*",
+        "*",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/*",
+        "Username==test2",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/*",
+        "can_manage",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/*",
+        "can_use",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/*",
+        "engines/engine1",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/*",
+        "unknown",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/engine1",
+        "*",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/engine1",
+        "Username==test2",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/engine1",
+        "can_manage",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/engine1",
+        "can_use",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/engine1",
+        "engines/engine1",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "engines/engine1",
+        "unknown",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "unknown",
+        "*",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "unknown",
+        "Username==test2",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "unknown",
+        "can_manage",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "unknown",
+        "can_use",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "unknown",
+        "engines/engine1",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "engines/engine1",
+        "unknown",
+        "unknown",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "*",
+        "*",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "*",
+        "Username==test2",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "*",
+        "Username==test2",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "*",
+        "can_manage",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "*",
+        "can_use",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "*",
+        "engines/engine1",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "*",
+        "unknown",
+        "unknown"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "Username==test2",
+        "*",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "Username==test2",
+        "Username==test2",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "Username==test2",
+        "can_manage",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "Username==test2",
+        "can_use",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "Username==test2",
+        "engines/engine1",
+        "engines/engine1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "Username==test2",
+        "unknown",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_manage",
+        "*",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_manage",
+        "Username==test2",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_manage",
+        "can_manage",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_manage",
+        "can_use",
+        "can_use"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_manage",
+        "engines/engine1",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_manage",
+        "unknown",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_use",
+        "*",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_use",
+        "Username==test2",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_use",
+        "can_manage",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_use",
+        "can_use",
+        "can_manage"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_use",
+        "engines/engine1",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "can_use",
+        "unknown",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/*",
+        "*",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/*",
+        "Username==test2",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/*",
+        "can_manage",
+        "Username==test2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/*",
+        "can_use",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/*",
+        "engines/engine1",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/*",
+        "unknown",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/engine1",
+        "*",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/engine1",
+        "Username==test2",
+        "*"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/engine1",
+        "can_manage",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/engine1",
+        "can_use",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/engine1",
+        "engines/engine1",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "engines/engine1",
+        "unknown",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "*",
+        "(pause)|(resume)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "Username==test2",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "can_manage",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "can_use",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "engines/engine1",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "unknown",
+        "unknown",
+        "unknown",
+        "(attach)|(detach)"
+      ],
+      "allow": false,
+      "explain": []
+    }
+  ]
+}
diff --git a/conformance/cases/orbac.json b/conformance/cases/orbac.json
new file mode 100644
index 0000000..951ba11
--- /dev/null
+++ b/conformance/cases/orbac.json
@@ -0,0 +1,3286 @@
+{
+  "model": "orbac_model.conf",
+  "policy": "orbac_policy.csv",
+  "tests": [
+    {
+      "request": [
+        "alice",
+        "alice",
+        "alice",
+        "alice"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "bob",
+        "manager",
+        "bob"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "charlie",
+        "write",
+        "consult"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data1",
+        "employee",
+        "data1"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "data2",
+        "unknown",
+        "david"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "document",
+        "document",
+        "employee"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "employee",
+        "report2",
+        "manager"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "modify",
+        "david",
+        "org2"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "org1",
+        "data1",
+        "consult"
+      ],
+      "allow": true,
+      "explain": [
+        "manager",
+        "consult",
+        "document",
+        "org1"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "org1",
+        "data1",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "manager",
+        "consult",
+        "document",
+        "org1"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "org1",
+        "data2",
+        "consult"
+      ],
+      "allow": true,
+      "explain": [
+        "manager",
+        "consult",
+        "document",
+        "org1"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "org1",
+        "data2",
+        "modify"
+      ],
+      "allow": true,
+      "explain": [
+        "manager",
+        "modify",
+        "document",
+        "org1"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "org1",
+        "data2",
+        "read"
+      ],
+      "allow": true,
+      "explain": [
+        "manager",
+        "consult",
+        "document",
+        "org1"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "org1",
+        "data2",
+        "write"
+      ],
+      "allow": true,
+      "explain": [
+        "manager",
+        "modify",
+        "document",
+        "org1"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "org1",
+        "document",
+        "consult"
+      ],
+      "allow": true,
+      "explain": [
+        "manager",
+        "consult",
+        "document",
+        "org1"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "org1",
+        "document",
+        "modify"
+      ],
+      "allow": true,
+      "explain": [
+        "manager",
+        "modify",
+        "document",
+        "org1"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "org1",
+        "document",
+        "write"
+      ],
+      "allow": true,
+      "explain": [
+        "manager",
+        "modify",
+        "document",
+        "org1"
+      ]
+    },
+    {
+      "request": [
+        "alice",
+        "org1",
+        "report2",
+        "david"
+      ],
+      "allow": false,
+      "explain": []
+    },
+    {
+      "request": [
+        "alice",
+        "read",
+        "david",
... 42543 lines suppressed ...


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@casbin.apache.org
For additional commands, e-mail: commits-help@casbin.apache.org