From c1568d48e4d05dcf153e3eb3ec6d35cd44866de6 Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Thu, 29 Jun 2023 18:09:41 +0200 Subject: [PATCH 01/11] spec: support for `reject if` --- SPECIFICATIONS.md | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/SPECIFICATIONS.md b/SPECIFICATIONS.md index 9d0a672..b27f12b 100644 --- a/SPECIFICATIONS.md +++ b/SPECIFICATIONS.md @@ -291,23 +291,27 @@ To validate an operation, all of a token's checks must succeed. One block can contain one or more checks. -Their text representation is `check if` or `check all` followed by the body of the query. +Their text representation is `check if`, `check all` or `reject if` followed by the body of the query. There can be multiple queries inside of a check, it will succeed if any of them -succeeds. They are separated by a `or` token. +succeeds (in the case of `reject if`, the check will fail if any query matches). They are separated by a `or` token. - a `check if` query succeeds if it finds one set of facts that matches the body and expressions - a `check all` query succeeds if all the sets of facts that match the body also succeed the expression. -`check all` can only be used starting from block version 4 +- a `reject if` query succeeds if no set of facts matches the body and expressions + +`check all` can only be used starting from block version 4. +`reject if` can only be used starting from block version 5. Here are some examples of writing checks: #### Basic token This first token defines a list of authority facts giving `read` and `write` -rights on `file1`, `read` on `file2`. The first caveat checks that the operation +rights on `file1`, `read` on `file2`. The first check ensures that the operation is `read` (and will not allow any other `operation` fact), and then that we have -the `read` right over the resource. -The second caveat checks that the resource is `file1`. +the `read` right over the resource. +The second check ensures that the resource is either `file1` or `file2`. +The third check ensures that the resource is not `file1`. ``` authority: @@ -323,20 +327,24 @@ check if ---------- Block 2: check if - resource("file1") // restrict to file1 resource + resource("file1") + or resource("file2") // restrict to file1 or file2 +---------- +Block 3: +reject if + resource("file1") // forbid using the token on file1 ``` The verifier side provides the `resource` and `operation` facts with information from the request. -If the verifier provided the facts `resource("file2")` and +If the verifier provided the facts `resource("file1")` and `operation("read")`, the rule application of the first check would see -`resource("file2"), operation("read"), right("file2", "read")` -with `X = "file2"`, so it would succeed, but the second check would fail -because it expects `resource("file1")`. +`resource("file1"), operation("read"), right("file1", "read")` +with `X = "file1"`, so it would succeed, the second check would also succeed because it expects `resource("file1")` or `resource("file2")`. The third check would then fail because it would match on `resource("file1")`. -If the verifier provided the facts `resource("file1")` and -`operation("read")`, both checks would succeed. +If the verifier provided the facts `resource("file2")` and +`operation("read")`, all checks would succeed. #### Broad authority rules @@ -661,7 +669,7 @@ each block must carry its own version. when possible, especially for biscuit versions that are only additive in terms of features. - The lowest supported biscuit version is `3`; -- The highest supported biscuit version is `4`; +- The highest supported biscuit version is `5`; # Version 2 From 7e6e347f8f51437dba2281402e02109d7c873a0a Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Sun, 12 May 2024 19:15:09 +0200 Subject: [PATCH 02/11] Reject if samples (#161) * add samples for reject if * missing change --- samples/current/README.md | 92 ++++++++++++++++++++++++- samples/current/samples.json | 92 ++++++++++++++++++++++++- samples/current/test017_expressions.bc | Bin 1725 -> 1799 bytes samples/current/test029_reject_if.bc | Bin 0 -> 182 bytes 4 files changed, 180 insertions(+), 4 deletions(-) create mode 100644 samples/current/test029_reject_if.bc diff --git a/samples/current/README.md b/samples/current/README.md index e123c7c..bec8ced 100644 --- a/samples/current/README.md +++ b/samples/current/README.md @@ -1214,7 +1214,7 @@ result: `Err(FailedLogic(Unauthorized { policy: Allow(0), checks: [Block(FailedB ### token authority: -symbols: ["hello world", "hello", "world", "aaabde", "a*c?.e", "abd", "aaa", "b", "de", "abcD12", "abc", "def"] +symbols: ["hello world", "hello", "world", "aaabde", "a*c?.e", "abd", "aaa", "b", "de", "abcD12", "é", "abc", "def"] public keys: [] @@ -1239,6 +1239,8 @@ check if "aaabde".matches("a*c?.e"); check if "aaabde".contains("abd"); check if "aaabde" == "aaa" + "b" + "de"; check if "abcD12" == "abcD12"; +check if "abcD12".length() == 6; +check if "é".length() == 2; check if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z; check if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z; check if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z; @@ -1268,7 +1270,7 @@ allow if true; ``` revocation ids: -- `f61b4cb4fc58777fec6c8d39fe62259dc3c78511868236c391e9f67ffd03a3a8b8e3042d4bacce0d5756d053f5afccd4c5e4df0597af44b36bdfab492e5fe50e` +- `3d5b23b502b3dd920bfb68b9039164d1563bb8927210166fa5c17f41b76b31bb957bc2ed3318452958f658baa2d398fe4cf25c58a27e6c8bc42c9702c8aa1b0c` authorizer world: ``` @@ -1287,7 +1289,9 @@ World { "check if \"aaabde\".contains(\"abd\")", "check if \"aaabde\".matches(\"a*c?.e\")", "check if \"abcD12\" == \"abcD12\"", + "check if \"abcD12\".length() == 6", "check if \"hello world\".starts_with(\"hello\") && \"hello world\".ends_with(\"world\")", + "check if \"é\".length() == 2", "check if (true || false) && true", "check if 1 + 2 * 3 - 4 / 2 == 5", "check if 1 < 2", @@ -2357,3 +2361,87 @@ World { result: `Ok(0)` + +------------------------------ + +## test reject if: test029_reject_if.bc +### token + +authority: +symbols: ["test"] + +public keys: [] + +``` +reject if test($test), $test; +``` + +### validation + +authorizer code: +``` +test(false); + +allow if true; +``` + +revocation ids: +- `2060031eb9968b492123440fa9cbc781f18be812961e765a34a8702d3eee0ed54910710efbb41b3141f60748a815012fe0e703a5b5604f4262d1ac7e79766b07` + +authorizer world: +``` +World { + facts: { + ( + "test(false)", + { + None, + }, + ), +} + rules: {} + checks: { + "reject if test($test), $test", +} + policies: { + "allow if true", +} +} +``` + +result: `Ok(0)` +### validation for "rejection" + +authorizer code: +``` +test(true); + +allow if true; +``` + +revocation ids: +- `2060031eb9968b492123440fa9cbc781f18be812961e765a34a8702d3eee0ed54910710efbb41b3141f60748a815012fe0e703a5b5604f4262d1ac7e79766b07` + +authorizer world: +``` +World { + facts: { + ( + "test(true)", + { + None, + }, + ), +} + rules: {} + checks: { + "reject if test($test), $test", +} + policies: { + "allow if true", +} +} +``` + +result: `Err(FailedLogic(Unauthorized { policy: Allow(0), checks: [Block(FailedBlockCheck { block_id: 0, check_id: 0, rule: "reject if test($test), $test" })] }))` + diff --git a/samples/current/samples.json b/samples/current/samples.json index 432c45d..28730f3 100644 --- a/samples/current/samples.json +++ b/samples/current/samples.json @@ -1239,12 +1239,13 @@ "b", "de", "abcD12", + "é", "abc", "def" ], "public_keys": [], "external_key": null, - "code": "check if true;\ncheck if !false;\ncheck if !false && true;\ncheck if false || true;\ncheck if (true || false) && true;\ncheck if true == true;\ncheck if false == false;\ncheck if 1 < 2;\ncheck if 2 > 1;\ncheck if 1 <= 2;\ncheck if 1 <= 1;\ncheck if 2 >= 1;\ncheck if 2 >= 2;\ncheck if 3 == 3;\ncheck if 1 + 2 * 3 - 4 / 2 == 5;\ncheck if \"hello world\".starts_with(\"hello\") && \"hello world\".ends_with(\"world\");\ncheck if \"aaabde\".matches(\"a*c?.e\");\ncheck if \"aaabde\".contains(\"abd\");\ncheck if \"aaabde\" == \"aaa\" + \"b\" + \"de\";\ncheck if \"abcD12\" == \"abcD12\";\ncheck if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z;\ncheck if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z == 2020-12-04T09:46:41Z;\ncheck if hex:12ab == hex:12ab;\ncheck if [1, 2].contains(2);\ncheck if [2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z].contains(2020-12-04T09:46:41Z);\ncheck if [false, true].contains(true);\ncheck if [\"abc\", \"def\"].contains(\"abc\");\ncheck if [hex:12ab, hex:34de].contains(hex:34de);\ncheck if [1, 2].contains([2]);\ncheck if [1, 2] == [1, 2];\ncheck if [1, 2].intersection([2, 3]) == [2];\ncheck if [1, 2].union([2, 3]) == [1, 2, 3];\ncheck if [1, 2, 3].intersection([1, 2]).contains(1);\ncheck if [1, 2, 3].intersection([1, 2]).length() == 2;\n" + "code": "check if true;\ncheck if !false;\ncheck if !false && true;\ncheck if false || true;\ncheck if (true || false) && true;\ncheck if true == true;\ncheck if false == false;\ncheck if 1 < 2;\ncheck if 2 > 1;\ncheck if 1 <= 2;\ncheck if 1 <= 1;\ncheck if 2 >= 1;\ncheck if 2 >= 2;\ncheck if 3 == 3;\ncheck if 1 + 2 * 3 - 4 / 2 == 5;\ncheck if \"hello world\".starts_with(\"hello\") && \"hello world\".ends_with(\"world\");\ncheck if \"aaabde\".matches(\"a*c?.e\");\ncheck if \"aaabde\".contains(\"abd\");\ncheck if \"aaabde\" == \"aaa\" + \"b\" + \"de\";\ncheck if \"abcD12\" == \"abcD12\";\ncheck if \"abcD12\".length() == 6;\ncheck if \"é\".length() == 2;\ncheck if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z;\ncheck if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z == 2020-12-04T09:46:41Z;\ncheck if hex:12ab == hex:12ab;\ncheck if [1, 2].contains(2);\ncheck if [2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z].contains(2020-12-04T09:46:41Z);\ncheck if [false, true].contains(true);\ncheck if [\"abc\", \"def\"].contains(\"abc\");\ncheck if [hex:12ab, hex:34de].contains(hex:34de);\ncheck if [1, 2].contains([2]);\ncheck if [1, 2] == [1, 2];\ncheck if [1, 2].intersection([2, 3]) == [2];\ncheck if [1, 2].union([2, 3]) == [1, 2, 3];\ncheck if [1, 2, 3].intersection([1, 2]).contains(1);\ncheck if [1, 2, 3].intersection([1, 2]).length() == 2;\n" } ], "validations": { @@ -1262,7 +1263,9 @@ "check if \"aaabde\".contains(\"abd\")", "check if \"aaabde\".matches(\"a*c?.e\")", "check if \"abcD12\" == \"abcD12\"", + "check if \"abcD12\".length() == 6", "check if \"hello world\".starts_with(\"hello\") && \"hello world\".ends_with(\"world\")", + "check if \"é\".length() == 2", "check if (true || false) && true", "check if 1 + 2 * 3 - 4 / 2 == 5", "check if 1 < 2", @@ -1307,7 +1310,7 @@ }, "authorizer_code": "allow if true;\n", "revocation_ids": [ - "f61b4cb4fc58777fec6c8d39fe62259dc3c78511868236c391e9f67ffd03a3a8b8e3042d4bacce0d5756d053f5afccd4c5e4df0597af44b36bdfab492e5fe50e" + "3d5b23b502b3dd920bfb68b9039164d1563bb8927210166fa5c17f41b76b31bb957bc2ed3318452958f658baa2d398fe4cf25c58a27e6c8bc42c9702c8aa1b0c" ] } } @@ -2174,6 +2177,91 @@ ] } } + }, + { + "title": "test reject if", + "filename": "test029_reject_if.bc", + "token": [ + { + "symbols": [ + "test" + ], + "public_keys": [], + "external_key": null, + "code": "reject if test($test), $test;\n" + } + ], + "validations": { + "": { + "world": { + "facts": [ + [ + "test(false)", + [ + null + ] + ] + ], + "rules": [], + "checks": [ + "reject if test($test), $test" + ], + "policies": [ + "allow if true" + ] + }, + "result": { + "Ok": 0 + }, + "authorizer_code": "test(false);\n\nallow if true;\n", + "revocation_ids": [ + "2060031eb9968b492123440fa9cbc781f18be812961e765a34a8702d3eee0ed54910710efbb41b3141f60748a815012fe0e703a5b5604f4262d1ac7e79766b07" + ] + }, + "rejection": { + "world": { + "facts": [ + [ + "test(true)", + [ + null + ] + ] + ], + "rules": [], + "checks": [ + "reject if test($test), $test" + ], + "policies": [ + "allow if true" + ] + }, + "result": { + "Err": { + "FailedLogic": { + "Unauthorized": { + "policy": { + "Allow": 0 + }, + "checks": [ + { + "Block": { + "block_id": 0, + "check_id": 0, + "rule": "reject if test($test), $test" + } + } + ] + } + } + } + }, + "authorizer_code": "test(true);\n\nallow if true;\n", + "revocation_ids": [ + "2060031eb9968b492123440fa9cbc781f18be812961e765a34a8702d3eee0ed54910710efbb41b3141f60748a815012fe0e703a5b5604f4262d1ac7e79766b07" + ] + } + } } ] } diff --git a/samples/current/test017_expressions.bc b/samples/current/test017_expressions.bc index 10f50241d96621a4a6d9b28f9e7386e98f21d91a..1f3234c07694321afef884cd0b547baa27d64096 100644 GIT binary patch delta 178 zcmdnX+s?--^njP^>qJ&JW~Rd{H+pSkvRCAi=VIcJmXhRRmKxm1*V^WcTSpL$3^^V)K4R=qiKJ?aD!c{ZkTg0wKmuLL*`4khes4l1bh|YAT6RV_o JCeLJ30RV53IiC62nq!X0~m_4_ynr~K=vC< zwES3if9!0HIsRfLox{h45r%>`!;$IsfBgfasJP<de*gdg diff --git a/samples/current/test029_reject_if.bc b/samples/current/test029_reject_if.bc new file mode 100644 index 0000000000000000000000000000000000000000..9d6c4d360c6d4231eef5e1dd89e0851cb5561823 GIT binary patch literal 182 zcmV;n07?H6j{yoL3Iudzb95L5G8+mP3IYfl5(o%@2oeJbfCw4~3Iz%S2!IF>0um$$ z01_Y&RmV`Vp-@>juN61OCb}|XnOrlbM_8(_u_s#t65@m!Kp4*RqlF+uhRNT?M7FW~0`rL|yBLSoUZetC9l2O=U0 kAercU4v|<>9`3aR{}m=~DIQVI&ef5&!@I literal 0 HcmV?d00001 From 5cddb2ea3d1cf1c8e70a803d223e847b4a01b03b Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 23 May 2024 14:25:30 +0200 Subject: [PATCH 03/11] Add support for the null type (#166) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Clément Delafargue --- SPECIFICATIONS.md | 9 +- samples/current/README.md | 419 +++++++++++++++++++++++++-------- samples/current/samples.json | 259 +++++++++++++++++++- samples/current/test30_null.bc | Bin 0 -> 248 bytes 4 files changed, 571 insertions(+), 116 deletions(-) create mode 100644 samples/current/test30_null.bc diff --git a/SPECIFICATIONS.md b/SPECIFICATIONS.md index bfe4ad1..c0d5861 100644 --- a/SPECIFICATIONS.md +++ b/SPECIFICATIONS.md @@ -75,6 +75,7 @@ _predicates_ over the following types: - _byte array_ - _date_ - _boolean_ +- _null_ - _set_ a deduplicated list of values of any type, except _variable_ or _set_ While a Biscuit token does not use a textual representation for storage, we @@ -117,6 +118,7 @@ We will represent the various types as follows: - byte array: `hex:01A2` - date in RFC 3339 format: `1985-04-12T23:20:50.52Z` - boolean: `true` or `false` +- null: `null`, supported since block version 5 - set: `[ "a", "b", "c"]` As an example, assuming we have the following facts: `parent("a", "b")`, @@ -154,6 +156,8 @@ not equal, set inclusion. A _boolean_ is `true` or `false`. It supports the following operations: `==`, `!=`, `||`, `&&`, set inclusion. +A _null_ is a default type indicating the absence of value. It supports the operations `==` and `!=` with any other type. _null_ is always equal to itself, and not equal to any other type + A _set_ is a deduplicated list of terms of the same type. It cannot contain variables or other sets. It supports equal, not equal, , intersection, union, set inclusion. @@ -184,13 +188,14 @@ The logic language is described by the following EBNF grammar: ::= "(" ? (? "," ? )* ? ")" ::= | - ::= | | | ("hex:" ) | | - ::= | | | | + ::= | | | ("hex:" ) | | | + ::= | | | | | ::= "-"? [0-9]+ ::= ([a-z] | [0-9])+ ::= "true" | "false" + ::= "null" ::= [0-9]* "-" [0-9] [0-9] "-" [0-9] [0-9] "T" [0-9] [0-9] ":" [0-9] [0-9] ":" [0-9] [0-9] ( "Z" | ( ("+" | "-") [0-9] [0-9] ":" [0-9] [0-9] )) ::= "[" ? ( ( ? "," ? )* ? )? "]" diff --git a/samples/current/README.md b/samples/current/README.md index bec8ced..e7a0ae1 100644 --- a/samples/current/README.md +++ b/samples/current/README.md @@ -45,7 +45,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -53,7 +53,7 @@ World { "resource(\"file1\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -68,7 +68,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 1, ), @@ -296,7 +296,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -305,7 +305,7 @@ World { "resource(\"file2\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -316,7 +316,7 @@ World { "user_id(\"alice\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 2, @@ -328,7 +328,7 @@ World { }, ] rules: [ - AuthorizerRuleSet { + Rules { origin: Some( 1, ), @@ -338,7 +338,7 @@ World { }, ] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 1, ), @@ -407,7 +407,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -416,7 +416,7 @@ World { "resource(\"file2\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -426,7 +426,7 @@ World { "right(\"file1\", \"read\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 2, @@ -439,7 +439,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 1, ), @@ -499,7 +499,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -512,7 +512,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 1, ), @@ -574,7 +574,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -583,7 +583,7 @@ World { "resource(\"file2\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -593,7 +593,7 @@ World { "right(\"file1\", \"read\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 1, @@ -606,7 +606,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 18446744073709551615, ), @@ -657,7 +657,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -666,7 +666,7 @@ World { "resource(\"file2\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -679,7 +679,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 18446744073709551615, ), @@ -728,7 +728,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -740,7 +740,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -773,7 +773,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -785,7 +785,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -847,7 +847,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -856,7 +856,7 @@ World { "time(2020-12-21T09:23:12Z)", ], }, - AuthorizerFactSet { + Facts { origin: { None, Some( @@ -867,7 +867,7 @@ World { "valid_date(\"file1\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -880,7 +880,7 @@ World { }, ] rules: [ - AuthorizerRuleSet { + Rules { origin: Some( 1, ), @@ -891,7 +891,7 @@ World { }, ] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 1, ), @@ -925,7 +925,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -934,7 +934,7 @@ World { "time(2020-12-21T09:23:12Z)", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -947,7 +947,7 @@ World { }, ] rules: [ - AuthorizerRuleSet { + Rules { origin: Some( 1, ), @@ -958,7 +958,7 @@ World { }, ] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 1, ), @@ -1006,7 +1006,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -1017,7 +1017,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -1049,7 +1049,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -1060,7 +1060,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -1108,7 +1108,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -1121,7 +1121,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 18446744073709551615, ), @@ -1177,7 +1177,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { Some( 1, @@ -1190,7 +1190,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -1278,7 +1278,7 @@ World { facts: [] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -1404,7 +1404,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -1412,7 +1412,7 @@ World { "operation(\"write\")", ], }, - AuthorizerFactSet { + Facts { origin: { None, Some( @@ -1425,7 +1425,7 @@ World { }, ] rules: [ - AuthorizerRuleSet { + Rules { origin: Some( 1, ), @@ -1435,7 +1435,7 @@ World { }, ] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -1496,7 +1496,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -1505,7 +1505,7 @@ World { "resource(\"file1\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -1520,7 +1520,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 1, ), @@ -1568,7 +1568,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -1581,7 +1581,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 18446744073709551615, ), @@ -1656,7 +1656,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -1696,7 +1696,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 18446744073709551615, ), @@ -1763,7 +1763,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -1773,7 +1773,7 @@ World { "authority_fact(1)", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 1, @@ -1786,7 +1786,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 2, ), @@ -1847,7 +1847,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -1857,7 +1857,7 @@ World { "right(\"read\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 1, @@ -1870,7 +1870,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -1878,7 +1878,7 @@ World { "check if group(\"admin\") trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189", ], }, - AuthorizerCheckSet { + Checks { origin: Some( 1, ), @@ -1928,7 +1928,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -1937,7 +1937,7 @@ World { "operation(\"B\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -1950,7 +1950,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -1983,7 +1983,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { None, }, @@ -1992,7 +1992,7 @@ World { "operation(\"invalid\")", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -2005,7 +2005,7 @@ World { ] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -2112,7 +2112,7 @@ authorizer world: ``` World { facts: [ - AuthorizerFactSet { + Facts { origin: { Some( 0, @@ -2122,7 +2122,7 @@ World { "query(0)", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 1, @@ -2132,7 +2132,7 @@ World { "query(1)", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 1, @@ -2145,7 +2145,7 @@ World { "query(1, 2)", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 2, @@ -2155,7 +2155,7 @@ World { "query(2)", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 3, @@ -2165,7 +2165,7 @@ World { "query(3)", ], }, - AuthorizerFactSet { + Facts { origin: { Some( 4, @@ -2177,7 +2177,7 @@ World { }, ] rules: [ - AuthorizerRuleSet { + Rules { origin: Some( 1, ), @@ -2187,7 +2187,7 @@ World { }, ] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -2195,7 +2195,7 @@ World { "check if true trusting previous, ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189", ], }, - AuthorizerCheckSet { + Checks { origin: Some( 1, ), @@ -2204,7 +2204,7 @@ World { "check if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", ], }, - AuthorizerCheckSet { + Checks { origin: Some( 2, ), @@ -2213,7 +2213,7 @@ World { "check if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", ], }, - AuthorizerCheckSet { + Checks { origin: Some( 3, ), @@ -2222,7 +2222,7 @@ World { "check if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", ], }, - AuthorizerCheckSet { + Checks { origin: Some( 4, ), @@ -2231,7 +2231,7 @@ World { "check if query(4) trusting ed25519/f98da8c1cf907856431bfc3dc87531e0eaadba90f919edc232405b85877ef136", ], }, - AuthorizerCheckSet { + Checks { origin: Some( 18446744073709551615, ), @@ -2284,7 +2284,7 @@ World { facts: [] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -2339,7 +2339,7 @@ World { facts: [] rules: [] checks: [ - AuthorizerCheckSet { + Checks { origin: Some( 0, ), @@ -2391,21 +2391,30 @@ revocation ids: authorizer world: ``` World { - facts: { - ( - "test(false)", - { + facts: [ + Facts { + origin: { None, }, - ), -} - rules: {} - checks: { - "reject if test($test), $test", -} - policies: { + facts: [ + "test(false)", + ], + }, +] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "reject if test($test), $test", + ], + }, +] + policies: [ "allow if true", -} +] } ``` @@ -2425,23 +2434,225 @@ revocation ids: authorizer world: ``` World { - facts: { - ( - "test(true)", - { + facts: [ + Facts { + origin: { None, }, - ), + facts: [ + "test(true)", + ], + }, +] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "reject if test($test), $test", + ], + }, +] + policies: [ + "allow if true", +] } - rules: {} - checks: { - "reject if test($test), $test", +``` + +result: `Err(FailedLogic(Unauthorized { policy: Allow(0), checks: [Block(FailedBlockCheck { block_id: 0, check_id: 0, rule: "reject if test($test), $test" })] }))` + + +------------------------------ + +## test null: test30_null.bc +### token + +authority: +symbols: ["fact", "value"] + +public keys: [] + +``` +check if fact(null, $value), $value == null; +reject if fact(null, $value), $value != null; +``` + +### validation + +authorizer code: +``` +fact(null, null); + +allow if true; +``` + +revocation ids: +- `bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003` + +authorizer world: +``` +World { + facts: [ + Facts { + origin: { + None, + }, + facts: [ + "fact(null, null)", + ], + }, +] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "check if fact(null, $value), $value == null", + "reject if fact(null, $value), $value != null", + ], + }, +] + policies: [ + "allow if true", +] } - policies: { +``` + +result: `Ok(0)` +### validation for "rejection1" + +authorizer code: +``` +fact(null, 1); + +allow if true; +``` + +revocation ids: +- `bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003` + +authorizer world: +``` +World { + facts: [ + Facts { + origin: { + None, + }, + facts: [ + "fact(null, 1)", + ], + }, +] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "check if fact(null, $value), $value == null", + "reject if fact(null, $value), $value != null", + ], + }, +] + policies: [ "allow if true", +] } +``` + +result: `Err(FailedLogic(Unauthorized { policy: Allow(0), checks: [Block(FailedBlockCheck { block_id: 0, check_id: 0, rule: "check if fact(null, $value), $value == null" }), Block(FailedBlockCheck { block_id: 0, check_id: 1, rule: "reject if fact(null, $value), $value != null" })] }))` +### validation for "rejection2" + +authorizer code: +``` +fact(null, true); + +allow if true; +``` + +revocation ids: +- `bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003` + +authorizer world: +``` +World { + facts: [ + Facts { + origin: { + None, + }, + facts: [ + "fact(null, true)", + ], + }, +] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "check if fact(null, $value), $value == null", + "reject if fact(null, $value), $value != null", + ], + }, +] + policies: [ + "allow if true", +] } ``` -result: `Err(FailedLogic(Unauthorized { policy: Allow(0), checks: [Block(FailedBlockCheck { block_id: 0, check_id: 0, rule: "reject if test($test), $test" })] }))` +result: `Err(FailedLogic(Unauthorized { policy: Allow(0), checks: [Block(FailedBlockCheck { block_id: 0, check_id: 0, rule: "check if fact(null, $value), $value == null" }), Block(FailedBlockCheck { block_id: 0, check_id: 1, rule: "reject if fact(null, $value), $value != null" })] }))` +### validation for "rejection3" + +authorizer code: +``` +fact(null, "abcd"); + +allow if true; +``` + +revocation ids: +- `bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003` + +authorizer world: +``` +World { + facts: [ + Facts { + origin: { + None, + }, + facts: [ + "fact(null, \"abcd\")", + ], + }, +] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "check if fact(null, $value), $value == null", + "reject if fact(null, $value), $value != null", + ], + }, +] + policies: [ + "allow if true", +] +} +``` + +result: `Err(FailedLogic(Unauthorized { policy: Allow(0), checks: [Block(FailedBlockCheck { block_id: 0, check_id: 0, rule: "check if fact(null, $value), $value == null" }), Block(FailedBlockCheck { block_id: 0, check_id: 1, rule: "reject if fact(null, $value), $value != null" })] }))` diff --git a/samples/current/samples.json b/samples/current/samples.json index 28730f3..4af6b9c 100644 --- a/samples/current/samples.json +++ b/samples/current/samples.json @@ -2195,16 +2195,23 @@ "": { "world": { "facts": [ - [ - "test(false)", - [ + { + "origin": [ null + ], + "facts": [ + "test(false)" ] - ] + } ], "rules": [], "checks": [ - "reject if test($test), $test" + { + "origin": 0, + "checks": [ + "reject if test($test), $test" + ] + } ], "policies": [ "allow if true" @@ -2221,16 +2228,23 @@ "rejection": { "world": { "facts": [ - [ - "test(true)", - [ + { + "origin": [ null + ], + "facts": [ + "test(true)" ] - ] + } ], "rules": [], "checks": [ - "reject if test($test), $test" + { + "origin": 0, + "checks": [ + "reject if test($test), $test" + ] + } ], "policies": [ "allow if true" @@ -2262,6 +2276,231 @@ ] } } + }, + { + "title": "test null", + "filename": "test30_null.bc", + "token": [ + { + "symbols": [ + "fact", + "value" + ], + "public_keys": [], + "external_key": null, + "code": "check if fact(null, $value), $value == null;\nreject if fact(null, $value), $value != null;\n" + } + ], + "validations": { + "": { + "world": { + "facts": [ + { + "origin": [ + null + ], + "facts": [ + "fact(null, null)" + ] + } + ], + "rules": [], + "checks": [ + { + "origin": 0, + "checks": [ + "check if fact(null, $value), $value == null", + "reject if fact(null, $value), $value != null" + ] + } + ], + "policies": [ + "allow if true" + ] + }, + "result": { + "Ok": 0 + }, + "authorizer_code": "fact(null, null);\n\nallow if true;\n", + "revocation_ids": [ + "bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003" + ] + }, + "rejection1": { + "world": { + "facts": [ + { + "origin": [ + null + ], + "facts": [ + "fact(null, 1)" + ] + } + ], + "rules": [], + "checks": [ + { + "origin": 0, + "checks": [ + "check if fact(null, $value), $value == null", + "reject if fact(null, $value), $value != null" + ] + } + ], + "policies": [ + "allow if true" + ] + }, + "result": { + "Err": { + "FailedLogic": { + "Unauthorized": { + "policy": { + "Allow": 0 + }, + "checks": [ + { + "Block": { + "block_id": 0, + "check_id": 0, + "rule": "check if fact(null, $value), $value == null" + } + }, + { + "Block": { + "block_id": 0, + "check_id": 1, + "rule": "reject if fact(null, $value), $value != null" + } + } + ] + } + } + } + }, + "authorizer_code": "fact(null, 1);\n\nallow if true;\n", + "revocation_ids": [ + "bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003" + ] + }, + "rejection2": { + "world": { + "facts": [ + { + "origin": [ + null + ], + "facts": [ + "fact(null, true)" + ] + } + ], + "rules": [], + "checks": [ + { + "origin": 0, + "checks": [ + "check if fact(null, $value), $value == null", + "reject if fact(null, $value), $value != null" + ] + } + ], + "policies": [ + "allow if true" + ] + }, + "result": { + "Err": { + "FailedLogic": { + "Unauthorized": { + "policy": { + "Allow": 0 + }, + "checks": [ + { + "Block": { + "block_id": 0, + "check_id": 0, + "rule": "check if fact(null, $value), $value == null" + } + }, + { + "Block": { + "block_id": 0, + "check_id": 1, + "rule": "reject if fact(null, $value), $value != null" + } + } + ] + } + } + } + }, + "authorizer_code": "fact(null, true);\n\nallow if true;\n", + "revocation_ids": [ + "bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003" + ] + }, + "rejection3": { + "world": { + "facts": [ + { + "origin": [ + null + ], + "facts": [ + "fact(null, \"abcd\")" + ] + } + ], + "rules": [], + "checks": [ + { + "origin": 0, + "checks": [ + "check if fact(null, $value), $value == null", + "reject if fact(null, $value), $value != null" + ] + } + ], + "policies": [ + "allow if true" + ] + }, + "result": { + "Err": { + "FailedLogic": { + "Unauthorized": { + "policy": { + "Allow": 0 + }, + "checks": [ + { + "Block": { + "block_id": 0, + "check_id": 0, + "rule": "check if fact(null, $value), $value == null" + } + }, + { + "Block": { + "block_id": 0, + "check_id": 1, + "rule": "reject if fact(null, $value), $value != null" + } + } + ] + } + } + } + }, + "authorizer_code": "fact(null, \"abcd\");\n\nallow if true;\n", + "revocation_ids": [ + "bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003" + ] + } + } } ] } diff --git a/samples/current/test30_null.bc b/samples/current/test30_null.bc new file mode 100644 index 0000000000000000000000000000000000000000..2337a1114ef4e0530bb0283a7e36ff07aa920989 GIT binary patch literal 248 zcmWf-$jFt>#gdkoT*Ad#mY7qTD#2=`$)(Q4#33!j!_mMY#N@;v#LUsiAtlVk$^~L@ zv2X#!xLBl^I9QCdiB&2hz$B!?!62j{5PCddPP$2UNR<`+DIN%IdD0A-g5zynHfbpoUMiR^0))% znoDzSVrjhE<0dI#*E#)giF@0N2h2)JTnaN^RP#-Y2$p-dmHEG@TAsG@p+y1J!aZ}P M<+Zj%+}BM60M+S53jhEB literal 0 HcmV?d00001 From 1514dd5efa07ee201362a789c6c88b03e7f6ab7a Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Thu, 24 Oct 2024 17:59:37 +0200 Subject: [PATCH 04/11] update samples and schema based on the latest v5 branch in biscuit-rust --- samples/current/README.md | 452 +++++++++++++++--- samples/current/samples.json | 366 ++++++++++++-- samples/current/test017_expressions.bc | Bin 1799 -> 1687 bytes samples/current/test024_third_party.bc | Bin 458 -> 458 bytes .../current/test026_public_keys_interning.bc | Bin 1316 -> 1547 bytes samples/current/test027_integer_wraparound.bc | Bin 329 -> 293 bytes samples/current/test029_reject_if.bc | Bin 182 -> 182 bytes samples/current/test030_null.bc | Bin 0 -> 248 bytes .../current/test031_heterogeneous_equal.bc | Bin 0 -> 253 bytes samples/current/test032_laziness_closures.bc | Bin 0 -> 758 bytes samples/current/test033_typeof.bc | Bin 0 -> 882 bytes schema.proto | 17 +- 12 files changed, 715 insertions(+), 120 deletions(-) create mode 100644 samples/current/test030_null.bc create mode 100644 samples/current/test031_heterogeneous_equal.bc create mode 100644 samples/current/test032_laziness_closures.bc create mode 100644 samples/current/test033_typeof.bc diff --git a/samples/current/README.md b/samples/current/README.md index e7a0ae1..7ff9275 100644 --- a/samples/current/README.md +++ b/samples/current/README.md @@ -1221,45 +1221,42 @@ public keys: [] ``` check if true; check if !false; -check if !false && true; -check if false || true; -check if (true || false) && true; -check if true == true; -check if false == false; +check if true === true; +check if false === false; check if 1 < 2; check if 2 > 1; check if 1 <= 2; check if 1 <= 1; check if 2 >= 1; check if 2 >= 2; -check if 3 == 3; -check if 1 + 2 * 3 - 4 / 2 == 5; -check if "hello world".starts_with("hello") && "hello world".ends_with("world"); +check if 3 === 3; +check if 1 + 2 * 3 - 4 / 2 === 5; +check if "hello world".starts_with("hello"), "hello world".ends_with("world"); check if "aaabde".matches("a*c?.e"); check if "aaabde".contains("abd"); -check if "aaabde" == "aaa" + "b" + "de"; -check if "abcD12" == "abcD12"; -check if "abcD12".length() == 6; -check if "é".length() == 2; +check if "aaabde" === "aaa" + "b" + "de"; +check if "abcD12" === "abcD12"; +check if "abcD12".length() === 6; +check if "é".length() === 2; check if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z; check if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z; check if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z; check if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z; check if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z; check if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z; -check if 2020-12-04T09:46:41Z == 2020-12-04T09:46:41Z; -check if hex:12ab == hex:12ab; +check if 2020-12-04T09:46:41Z === 2020-12-04T09:46:41Z; +check if hex:12ab === hex:12ab; check if [1, 2].contains(2); check if [2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z].contains(2020-12-04T09:46:41Z); check if [false, true].contains(true); check if ["abc", "def"].contains("abc"); check if [hex:12ab, hex:34de].contains(hex:34de); check if [1, 2].contains([2]); -check if [1, 2] == [1, 2]; -check if [1, 2].intersection([2, 3]) == [2]; -check if [1, 2].union([2, 3]) == [1, 2, 3]; +check if [1, 2] === [1, 2]; +check if [1, 2].intersection([2, 3]) === [2]; +check if [1, 2].union([2, 3]) === [1, 2, 3]; check if [1, 2, 3].intersection([1, 2]).contains(1); -check if [1, 2, 3].intersection([1, 2]).length() == 2; +check if [1, 2, 3].intersection([1, 2]).length() === 2; ``` ### validation @@ -1270,7 +1267,7 @@ allow if true; ``` revocation ids: -- `3d5b23b502b3dd920bfb68b9039164d1563bb8927210166fa5c17f41b76b31bb957bc2ed3318452958f658baa2d398fe4cf25c58a27e6c8bc42c9702c8aa1b0c` +- `d0420227266e3583a42dfaa0e38550d99f681d150dd18856f3af9a697bc9c5c8bf06b4b0fe5b9df0377d1b963574e2fd210a0a76a8b0756a65f640c602bebd07` authorizer world: ``` @@ -1284,16 +1281,14 @@ World { ), checks: [ "check if !false", - "check if !false && true", - "check if \"aaabde\" == \"aaa\" + \"b\" + \"de\"", + "check if \"aaabde\" === \"aaa\" + \"b\" + \"de\"", "check if \"aaabde\".contains(\"abd\")", "check if \"aaabde\".matches(\"a*c?.e\")", - "check if \"abcD12\" == \"abcD12\"", - "check if \"abcD12\".length() == 6", - "check if \"hello world\".starts_with(\"hello\") && \"hello world\".ends_with(\"world\")", - "check if \"é\".length() == 2", - "check if (true || false) && true", - "check if 1 + 2 * 3 - 4 / 2 == 5", + "check if \"abcD12\" === \"abcD12\"", + "check if \"abcD12\".length() === 6", + "check if \"hello world\".starts_with(\"hello\"), \"hello world\".ends_with(\"world\")", + "check if \"é\".length() === 2", + "check if 1 + 2 * 3 - 4 / 2 === 5", "check if 1 < 2", "check if 1 <= 1", "check if 1 <= 2", @@ -1302,28 +1297,27 @@ World { "check if 2 >= 2", "check if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z", "check if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z", - "check if 2020-12-04T09:46:41Z == 2020-12-04T09:46:41Z", + "check if 2020-12-04T09:46:41Z === 2020-12-04T09:46:41Z", "check if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z", "check if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z", "check if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z", "check if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z", - "check if 3 == 3", + "check if 3 === 3", "check if [\"abc\", \"def\"].contains(\"abc\")", "check if [1, 2, 3].intersection([1, 2]).contains(1)", - "check if [1, 2, 3].intersection([1, 2]).length() == 2", - "check if [1, 2] == [1, 2]", + "check if [1, 2, 3].intersection([1, 2]).length() === 2", + "check if [1, 2] === [1, 2]", "check if [1, 2].contains(2)", "check if [1, 2].contains([2])", - "check if [1, 2].intersection([2, 3]) == [2]", - "check if [1, 2].union([2, 3]) == [1, 2, 3]", + "check if [1, 2].intersection([2, 3]) === [2]", + "check if [1, 2].union([2, 3]) === [1, 2, 3]", "check if [2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z].contains(2020-12-04T09:46:41Z)", "check if [false, true].contains(true)", "check if [hex:12ab, hex:34de].contains(hex:34de)", - "check if false == false", - "check if false || true", - "check if hex:12ab == hex:12ab", + "check if false === false", + "check if hex:12ab === hex:12ab", "check if true", - "check if true == true", + "check if true === true", ], }, ] @@ -1841,7 +1835,7 @@ allow if true; revocation ids: - `470e4bf7aa2a01ab39c98150bd06aa15b4aa5d86509044a8809a8634cd8cf2b42269a51a774b65d10bac9369d013070b00187925196a8e680108473f11cf8f03` -- `93a7315ab1272da9eeef015f6fecbc9ac96fe4660e6204bf64ea2105ebe309e9c9cadc0a26c5604f13910fae3f2cd0800756afb6b6b208bf77adeb1ab2f42405` +- `342167bc54bc642b6718a276875e55b6d39e9b21e4ce13b926a3d398b6c057fc436385bf4c817a16f9ecdf0b0d950e8b8258a20aeb3fd8896c5e9c1f0a53da03` authorizer world: ``` @@ -2041,7 +2035,7 @@ check if true trusting previous, ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755 1: symbols: [] -public keys: ["ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463"] +public keys: ["ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189"] external signature by: "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189" @@ -2055,7 +2049,7 @@ check if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5 2: symbols: [] -public keys: [] +public keys: ["ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189"] external signature by: "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463" @@ -2068,7 +2062,7 @@ check if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5 3: symbols: [] -public keys: [] +public keys: ["ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189"] external signature by: "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463" @@ -2081,7 +2075,7 @@ check if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5 4: symbols: [] -public keys: ["ed25519/f98da8c1cf907856431bfc3dc87531e0eaadba90f919edc232405b85877ef136"] +public keys: ["ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", "ed25519/f98da8c1cf907856431bfc3dc87531e0eaadba90f919edc232405b85877ef136"] ``` query(4); @@ -2103,10 +2097,10 @@ allow if true; revocation ids: - `3771cefe71beb21ead35a59c8116ee82627a5717c0295f35980662abccb159fe1b37848cb1818e548656bd4fd882d0094a2daab631c76b2b72e3a093914bfe04` -- `45133b90f228a81fe4d3042a79f6c6b7608e656e903d6b1f4db32cd774b09b8315af360879a5f210ad7be37ff55e3eb34f237bcc9711407b6329ac6018bfb400` -- `179f054f3c572646aba5013159ae192ac42f5666dbdd984129955f4652b6829e59f54aa251e451f96329d42a2524ce569c3e1ec52e708b642dd8994af51dd703` -- `edab54789d6656936fcd28200b9c61643434842d531f09f209fad555e11ff53174db174dafba126e6de448983a56f78d2042bc5782d71a45799c022fe69fb30d` -- `6a62306831e9dbe83e7b33db96b758c77dd690930f2d2d87e239b210b1944c5582bf6d7e1bfea8e7f928c27f2fff0e2ee2e0adc41e11e0c3abe8d7b96b9ede07` +- `6528db2c9a561ada9086268549a600a8a52ff434ea8183812623eec0e9b6c5d3c41ab7868808623021d92294d583afdf92f4354bcdaa1bc50453e1b89afd630d` +- `5d5679fe69bfe74b7919323515e9ecba9d01422b16be9341b57f88e695b2bb0bd7966b781001d2b9e00ee618fdc239c96e17e32cb379f13f12d6bd7b1b47ad04` +- `c37bf24c063f0310eccab8864e48dbeffcdd7240b4f8d1e01eba4fc703e6c9082b845bb55543b10f008dc7f4e78540411912ac1f36fa2aa90011dca40f323b09` +- `3f675d6c364e06405d4868c904e40f3d81c32b083d91586db814d4cb4bf536b4ba209d82f11b4cb6da293b60b20d6122fc3e0e08e80c381dee83edd848211900` authorizer world: ``` @@ -2263,9 +2257,9 @@ symbols: [] public keys: [] ``` -check if true || 10000000000 * 10000000000 != 0; -check if true || 9223372036854775807 + 1 != 0; -check if true || -9223372036854775808 - 1 != 0; +check if 10000000000 * 10000000000 != 0; +check if 9223372036854775807 + 1 != 0; +check if -9223372036854775808 - 1 != 0; ``` ### validation @@ -2276,7 +2270,7 @@ allow if true; ``` revocation ids: -- `3346a22aae0abfc1ffa526f02f7650e90af909e5e519989026441e78cdc245b7fd126503cfdc8831325fc04307edc65238db319724477915f7040a2f6a719a05` +- `31f01031b8d9cc312c346674625a2218b19a126e931318dc02d8d53aec2775faecd3f848f60c1446573c37ea0664fefc768f35ba5ce4365b83ff06f0c0409b0e` authorizer world: ``` @@ -2289,9 +2283,9 @@ World { 0, ), checks: [ - "check if true || -9223372036854775808 - 1 != 0", - "check if true || 10000000000 * 10000000000 != 0", - "check if true || 9223372036854775807 + 1 != 0", + "check if -9223372036854775808 - 1 != 0", + "check if 10000000000 * 10000000000 != 0", + "check if 9223372036854775807 + 1 != 0", ], }, ] @@ -2315,12 +2309,12 @@ symbols: ["abcD12x", "abcD12"] public keys: [] ``` -check if 1 != 3; -check if 1 | 2 ^ 3 == 0; -check if "abcD12x" != "abcD12"; -check if 2022-12-04T09:46:41Z != 2020-12-04T09:46:41Z; -check if hex:12abcd != hex:12ab; -check if [1, 4] != [1, 2]; +check if 1 !== 3; +check if 1 | 2 ^ 3 === 0; +check if "abcD12x" !== "abcD12"; +check if 2022-12-04T09:46:41Z !== 2020-12-04T09:46:41Z; +check if hex:12abcd !== hex:12ab; +check if [1, 4] !== [1, 2]; ``` ### validation @@ -2344,12 +2338,12 @@ World { 0, ), checks: [ - "check if \"abcD12x\" != \"abcD12\"", - "check if 1 != 3", - "check if 1 | 2 ^ 3 == 0", - "check if 2022-12-04T09:46:41Z != 2020-12-04T09:46:41Z", - "check if [1, 4] != [1, 2]", - "check if hex:12abcd != hex:12ab", + "check if \"abcD12x\" !== \"abcD12\"", + "check if 1 !== 3", + "check if 1 | 2 ^ 3 === 0", + "check if 2022-12-04T09:46:41Z !== 2020-12-04T09:46:41Z", + "check if [1, 4] !== [1, 2]", + "check if hex:12abcd !== hex:12ab", ], }, ] @@ -2386,7 +2380,7 @@ allow if true; ``` revocation ids: -- `2060031eb9968b492123440fa9cbc781f18be812961e765a34a8702d3eee0ed54910710efbb41b3141f60748a815012fe0e703a5b5604f4262d1ac7e79766b07` +- `2e6dcafe4061dd86f61ad038a0a1bea816b85898bb86a14b16177e78ee249fcfb2455e2eed52ccfe8eafc679b1f34f9ef98e92e3719981dd4098b901b6cb040b` authorizer world: ``` @@ -2429,7 +2423,7 @@ allow if true; ``` revocation ids: -- `2060031eb9968b492123440fa9cbc781f18be812961e765a34a8702d3eee0ed54910710efbb41b3141f60748a815012fe0e703a5b5604f4262d1ac7e79766b07` +- `2e6dcafe4061dd86f61ad038a0a1bea816b85898bb86a14b16177e78ee249fcfb2455e2eed52ccfe8eafc679b1f34f9ef98e92e3719981dd4098b901b6cb040b` authorizer world: ``` @@ -2466,7 +2460,7 @@ result: `Err(FailedLogic(Unauthorized { policy: Allow(0), checks: [Block(FailedB ------------------------------ -## test null: test30_null.bc +## test null: test030_null.bc ### token authority: @@ -2489,7 +2483,7 @@ allow if true; ``` revocation ids: -- `bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003` +- `c6c60ff84938908ca2bfcc7d674a400857c3349bdb373646c825e946ad0d08d76fd4734cd40f09884db0a41aee0c078897750e27706959d785750ef24acf100f` authorizer world: ``` @@ -2533,7 +2527,7 @@ allow if true; ``` revocation ids: -- `bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003` +- `c6c60ff84938908ca2bfcc7d674a400857c3349bdb373646c825e946ad0d08d76fd4734cd40f09884db0a41aee0c078897750e27706959d785750ef24acf100f` authorizer world: ``` @@ -2577,7 +2571,7 @@ allow if true; ``` revocation ids: -- `bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003` +- `c6c60ff84938908ca2bfcc7d674a400857c3349bdb373646c825e946ad0d08d76fd4734cd40f09884db0a41aee0c078897750e27706959d785750ef24acf100f` authorizer world: ``` @@ -2621,7 +2615,7 @@ allow if true; ``` revocation ids: -- `bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003` +- `c6c60ff84938908ca2bfcc7d674a400857c3349bdb373646c825e946ad0d08d76fd4734cd40f09884db0a41aee0c078897750e27706959d785750ef24acf100f` authorizer world: ``` @@ -2656,3 +2650,317 @@ World { result: `Err(FailedLogic(Unauthorized { policy: Allow(0), checks: [Block(FailedBlockCheck { block_id: 0, check_id: 0, rule: "check if fact(null, $value), $value == null" }), Block(FailedBlockCheck { block_id: 0, check_id: 1, rule: "reject if fact(null, $value), $value != null" })] }))` + +------------------------------ + +## test heterogeneous equal: test031_heterogeneous_equal.bc +### token + +authority: +symbols: ["fact", "value", "fact2"] + +public keys: [] + +``` +check if fact(1, $value), 1 == $value; +check if fact2(1, $value), 1 != $value; +``` + +### validation for "authorized same type" + +authorizer code: +``` +fact(1, 1); +fact2(1, 2); + +allow if true; +``` + +revocation ids: +- `d65b3aeceb6268124190f5eb87788a5eb81c89a3fc8370c9a3ea362731c55660b2b390ca6270e68afab90862bd2bbb808aa6b5576c975ae773a992a2434c930d` + +authorizer world: +``` +World { + facts: [ + Facts { + origin: { + None, + }, + facts: [ + "fact(1, 1)", + "fact2(1, 2)", + ], + }, +] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "check if fact(1, $value), 1 == $value", + "check if fact2(1, $value), 1 != $value", + ], + }, +] + policies: [ + "allow if true", +] +} +``` + +result: `Ok(0)` +### validation for "unauthorized failed logic different type" + +authorizer code: +``` +fact(1, true); +fact2(1, false); + +allow if true; +``` + +revocation ids: +- `d65b3aeceb6268124190f5eb87788a5eb81c89a3fc8370c9a3ea362731c55660b2b390ca6270e68afab90862bd2bbb808aa6b5576c975ae773a992a2434c930d` + +authorizer world: +``` +World { + facts: [ + Facts { + origin: { + None, + }, + facts: [ + "fact(1, true)", + "fact2(1, false)", + ], + }, +] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "check if fact(1, $value), 1 == $value", + "check if fact2(1, $value), 1 != $value", + ], + }, +] + policies: [ + "allow if true", +] +} +``` + +result: `Err(FailedLogic(Unauthorized { policy: Allow(0), checks: [Block(FailedBlockCheck { block_id: 0, check_id: 0, rule: "check if fact(1, $value), 1 == $value" })] }))` + + +------------------------------ + +## test laziness and closures: test032_laziness_closures.bc +### token + +authority: +symbols: ["x", "p", "q"] + +public keys: [] + +``` +check if !false && true; +check if false || true; +check if (true || false) && true; +check if !(false && "x".intersection("x")); +check if true || "x".intersection("x"); +check if [1, 2, 3].all($p -> $p > 0); +check if ![1, 2, 3].all($p -> $p == 2); +check if [1, 2, 3].any($p -> $p > 2); +check if ![1, 2, 3].any($p -> $p > 3); +check if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q)); +``` + +### validation + +authorizer code: +``` +allow if true; +``` + +revocation ids: +- `ef75002a071b56293152a4c9eb69ba0793614993e667736a6a92275ddd5aa35a287de5b13acaec72b5af6ba2ee8a3629b1a33cfa51597ae5afbebd8aa35dbe08` + +authorizer world: +``` +World { + facts: [] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "check if !(false && \"x\".intersection(\"x\"))", + "check if ![1, 2, 3].all($p -> $p == 2)", + "check if ![1, 2, 3].any($p -> $p > 3)", + "check if !false && true", + "check if (true || false) && true", + "check if [1, 2, 3].all($p -> $p > 0)", + "check if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q))", + "check if [1, 2, 3].any($p -> $p > 2)", + "check if false || true", + "check if true || \"x\".intersection(\"x\")", + ], + }, +] + policies: [ + "allow if true", +] +} +``` + +result: `Ok(0)` +### validation for "shadowing" + +authorizer code: +``` +allow if [true].any($p -> [true].all($p -> $p)); +``` + +revocation ids: +- `ef75002a071b56293152a4c9eb69ba0793614993e667736a6a92275ddd5aa35a287de5b13acaec72b5af6ba2ee8a3629b1a33cfa51597ae5afbebd8aa35dbe08` + +authorizer world: +``` +World { + facts: [] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "check if !(false && \"x\".intersection(\"x\"))", + "check if ![1, 2, 3].all($p -> $p == 2)", + "check if ![1, 2, 3].any($p -> $p > 3)", + "check if !false && true", + "check if (true || false) && true", + "check if [1, 2, 3].all($p -> $p > 0)", + "check if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q))", + "check if [1, 2, 3].any($p -> $p > 2)", + "check if false || true", + "check if true || \"x\".intersection(\"x\")", + ], + }, +] + policies: [ + "allow if [true].any($p -> [true].all($p -> $p))", +] +} +``` + +result: `Err(Execution(ShadowedVariable))` + + +------------------------------ + +## test .type(): test033_typeof.bc +### token + +authority: +symbols: ["integer", "string", "test", "date", "bytes", "bool", "set", "null", "t"] + +public keys: [] + +``` +integer(1); +string("test"); +date(2023-12-28T00:00:00Z); +bytes(hex:aa); +bool(true); +set([false, true]); +null(null); +check if 1.type() == "integer"; +check if integer($t), $t.type() == "integer"; +check if "test".type() == "string"; +check if string($t), $t.type() == "string"; +check if (2023-12-28T00:00:00Z).type() == "date"; +check if date($t), $t.type() == "date"; +check if hex:aa.type() == "bytes"; +check if bytes($t), $t.type() == "bytes"; +check if true.type() == "bool"; +check if bool($t), $t.type() == "bool"; +check if [false, true].type() == "set"; +check if set($t), $t.type() == "set"; +check if null.type() == "null"; +check if null($t), $t.type() == "null"; +``` + +### validation + +authorizer code: +``` +allow if true; +``` + +revocation ids: +- `be401996253dce45ac3d8b2f4b289af1f2cc2a4447a8265a1a2ca879c43377978ffc5ac6633053cd7c30e7c33cf258a37767226834bc80b005c48eb0229c4502` + +authorizer world: +``` +World { + facts: [ + Facts { + origin: { + Some( + 0, + ), + }, + facts: [ + "bool(true)", + "bytes(hex:aa)", + "date(2023-12-28T00:00:00Z)", + "integer(1)", + "null(null)", + "set([false, true])", + "string(\"test\")", + ], + }, +] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "check if \"test\".type() == \"string\"", + "check if (2023-12-28T00:00:00Z).type() == \"date\"", + "check if 1.type() == \"integer\"", + "check if [false, true].type() == \"set\"", + "check if bool($t), $t.type() == \"bool\"", + "check if bytes($t), $t.type() == \"bytes\"", + "check if date($t), $t.type() == \"date\"", + "check if hex:aa.type() == \"bytes\"", + "check if integer($t), $t.type() == \"integer\"", + "check if null($t), $t.type() == \"null\"", + "check if null.type() == \"null\"", + "check if set($t), $t.type() == \"set\"", + "check if string($t), $t.type() == \"string\"", + "check if true.type() == \"bool\"", + ], + }, +] + policies: [ + "allow if true", +] +} +``` + +result: `Ok(0)` + diff --git a/samples/current/samples.json b/samples/current/samples.json index 4af6b9c..a68baa6 100644 --- a/samples/current/samples.json +++ b/samples/current/samples.json @@ -1245,7 +1245,7 @@ ], "public_keys": [], "external_key": null, - "code": "check if true;\ncheck if !false;\ncheck if !false && true;\ncheck if false || true;\ncheck if (true || false) && true;\ncheck if true == true;\ncheck if false == false;\ncheck if 1 < 2;\ncheck if 2 > 1;\ncheck if 1 <= 2;\ncheck if 1 <= 1;\ncheck if 2 >= 1;\ncheck if 2 >= 2;\ncheck if 3 == 3;\ncheck if 1 + 2 * 3 - 4 / 2 == 5;\ncheck if \"hello world\".starts_with(\"hello\") && \"hello world\".ends_with(\"world\");\ncheck if \"aaabde\".matches(\"a*c?.e\");\ncheck if \"aaabde\".contains(\"abd\");\ncheck if \"aaabde\" == \"aaa\" + \"b\" + \"de\";\ncheck if \"abcD12\" == \"abcD12\";\ncheck if \"abcD12\".length() == 6;\ncheck if \"é\".length() == 2;\ncheck if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z;\ncheck if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z == 2020-12-04T09:46:41Z;\ncheck if hex:12ab == hex:12ab;\ncheck if [1, 2].contains(2);\ncheck if [2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z].contains(2020-12-04T09:46:41Z);\ncheck if [false, true].contains(true);\ncheck if [\"abc\", \"def\"].contains(\"abc\");\ncheck if [hex:12ab, hex:34de].contains(hex:34de);\ncheck if [1, 2].contains([2]);\ncheck if [1, 2] == [1, 2];\ncheck if [1, 2].intersection([2, 3]) == [2];\ncheck if [1, 2].union([2, 3]) == [1, 2, 3];\ncheck if [1, 2, 3].intersection([1, 2]).contains(1);\ncheck if [1, 2, 3].intersection([1, 2]).length() == 2;\n" + "code": "check if true;\ncheck if !false;\ncheck if true === true;\ncheck if false === false;\ncheck if 1 < 2;\ncheck if 2 > 1;\ncheck if 1 <= 2;\ncheck if 1 <= 1;\ncheck if 2 >= 1;\ncheck if 2 >= 2;\ncheck if 3 === 3;\ncheck if 1 + 2 * 3 - 4 / 2 === 5;\ncheck if \"hello world\".starts_with(\"hello\"), \"hello world\".ends_with(\"world\");\ncheck if \"aaabde\".matches(\"a*c?.e\");\ncheck if \"aaabde\".contains(\"abd\");\ncheck if \"aaabde\" === \"aaa\" + \"b\" + \"de\";\ncheck if \"abcD12\" === \"abcD12\";\ncheck if \"abcD12\".length() === 6;\ncheck if \"é\".length() === 2;\ncheck if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z;\ncheck if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z === 2020-12-04T09:46:41Z;\ncheck if hex:12ab === hex:12ab;\ncheck if [1, 2].contains(2);\ncheck if [2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z].contains(2020-12-04T09:46:41Z);\ncheck if [false, true].contains(true);\ncheck if [\"abc\", \"def\"].contains(\"abc\");\ncheck if [hex:12ab, hex:34de].contains(hex:34de);\ncheck if [1, 2].contains([2]);\ncheck if [1, 2] === [1, 2];\ncheck if [1, 2].intersection([2, 3]) === [2];\ncheck if [1, 2].union([2, 3]) === [1, 2, 3];\ncheck if [1, 2, 3].intersection([1, 2]).contains(1);\ncheck if [1, 2, 3].intersection([1, 2]).length() === 2;\n" } ], "validations": { @@ -1258,16 +1258,14 @@ "origin": 0, "checks": [ "check if !false", - "check if !false && true", - "check if \"aaabde\" == \"aaa\" + \"b\" + \"de\"", + "check if \"aaabde\" === \"aaa\" + \"b\" + \"de\"", "check if \"aaabde\".contains(\"abd\")", "check if \"aaabde\".matches(\"a*c?.e\")", - "check if \"abcD12\" == \"abcD12\"", - "check if \"abcD12\".length() == 6", - "check if \"hello world\".starts_with(\"hello\") && \"hello world\".ends_with(\"world\")", - "check if \"é\".length() == 2", - "check if (true || false) && true", - "check if 1 + 2 * 3 - 4 / 2 == 5", + "check if \"abcD12\" === \"abcD12\"", + "check if \"abcD12\".length() === 6", + "check if \"hello world\".starts_with(\"hello\"), \"hello world\".ends_with(\"world\")", + "check if \"é\".length() === 2", + "check if 1 + 2 * 3 - 4 / 2 === 5", "check if 1 < 2", "check if 1 <= 1", "check if 1 <= 2", @@ -1276,28 +1274,27 @@ "check if 2 >= 2", "check if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z", "check if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z", - "check if 2020-12-04T09:46:41Z == 2020-12-04T09:46:41Z", + "check if 2020-12-04T09:46:41Z === 2020-12-04T09:46:41Z", "check if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z", "check if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z", "check if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z", "check if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z", - "check if 3 == 3", + "check if 3 === 3", "check if [\"abc\", \"def\"].contains(\"abc\")", "check if [1, 2, 3].intersection([1, 2]).contains(1)", - "check if [1, 2, 3].intersection([1, 2]).length() == 2", - "check if [1, 2] == [1, 2]", + "check if [1, 2, 3].intersection([1, 2]).length() === 2", + "check if [1, 2] === [1, 2]", "check if [1, 2].contains(2)", "check if [1, 2].contains([2])", - "check if [1, 2].intersection([2, 3]) == [2]", - "check if [1, 2].union([2, 3]) == [1, 2, 3]", + "check if [1, 2].intersection([2, 3]) === [2]", + "check if [1, 2].union([2, 3]) === [1, 2, 3]", "check if [2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z].contains(2020-12-04T09:46:41Z)", "check if [false, true].contains(true)", "check if [hex:12ab, hex:34de].contains(hex:34de)", - "check if false == false", - "check if false || true", - "check if hex:12ab == hex:12ab", + "check if false === false", + "check if hex:12ab === hex:12ab", "check if true", - "check if true == true" + "check if true === true" ] } ], @@ -1310,7 +1307,7 @@ }, "authorizer_code": "allow if true;\n", "revocation_ids": [ - "3d5b23b502b3dd920bfb68b9039164d1563bb8927210166fa5c17f41b76b31bb957bc2ed3318452958f658baa2d398fe4cf25c58a27e6c8bc42c9702c8aa1b0c" + "d0420227266e3583a42dfaa0e38550d99f681d150dd18856f3af9a697bc9c5c8bf06b4b0fe5b9df0377d1b963574e2fd210a0a76a8b0756a65f640c602bebd07" ] } } @@ -1798,7 +1795,7 @@ "authorizer_code": "allow if true;\n", "revocation_ids": [ "470e4bf7aa2a01ab39c98150bd06aa15b4aa5d86509044a8809a8634cd8cf2b42269a51a774b65d10bac9369d013070b00187925196a8e680108473f11cf8f03", - "93a7315ab1272da9eeef015f6fecbc9ac96fe4660e6204bf64ea2105ebe309e9c9cadc0a26c5604f13910fae3f2cd0800756afb6b6b208bf77adeb1ab2f42405" + "342167bc54bc642b6718a276875e55b6d39e9b21e4ce13b926a3d398b6c057fc436385bf4c817a16f9ecdf0b0d950e8b8258a20aeb3fd8896c5e9c1f0a53da03" ] } } @@ -1939,26 +1936,34 @@ { "symbols": [], "public_keys": [ - "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463" + "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", + "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189" ], "external_key": "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189", "code": "query(1);\nquery(1, 2) <- query(1), query(2) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n" }, { "symbols": [], - "public_keys": [], + "public_keys": [ + "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", + "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189" + ], "external_key": "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", "code": "query(2);\ncheck if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n" }, { "symbols": [], - "public_keys": [], + "public_keys": [ + "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", + "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189" + ], "external_key": "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", "code": "query(3);\ncheck if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n" }, { "symbols": [], "public_keys": [ + "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", "ed25519/f98da8c1cf907856431bfc3dc87531e0eaadba90f919edc232405b85877ef136" ], "external_key": null, @@ -2082,10 +2087,10 @@ "authorizer_code": "check if query(1, 2) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189, ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\n\ndeny if query(3);\ndeny if query(1, 2);\ndeny if query(0) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\nallow if true;\n", "revocation_ids": [ "3771cefe71beb21ead35a59c8116ee82627a5717c0295f35980662abccb159fe1b37848cb1818e548656bd4fd882d0094a2daab631c76b2b72e3a093914bfe04", - "45133b90f228a81fe4d3042a79f6c6b7608e656e903d6b1f4db32cd774b09b8315af360879a5f210ad7be37ff55e3eb34f237bcc9711407b6329ac6018bfb400", - "179f054f3c572646aba5013159ae192ac42f5666dbdd984129955f4652b6829e59f54aa251e451f96329d42a2524ce569c3e1ec52e708b642dd8994af51dd703", - "edab54789d6656936fcd28200b9c61643434842d531f09f209fad555e11ff53174db174dafba126e6de448983a56f78d2042bc5782d71a45799c022fe69fb30d", - "6a62306831e9dbe83e7b33db96b758c77dd690930f2d2d87e239b210b1944c5582bf6d7e1bfea8e7f928c27f2fff0e2ee2e0adc41e11e0c3abe8d7b96b9ede07" + "6528db2c9a561ada9086268549a600a8a52ff434ea8183812623eec0e9b6c5d3c41ab7868808623021d92294d583afdf92f4354bcdaa1bc50453e1b89afd630d", + "5d5679fe69bfe74b7919323515e9ecba9d01422b16be9341b57f88e695b2bb0bd7966b781001d2b9e00ee618fdc239c96e17e32cb379f13f12d6bd7b1b47ad04", + "c37bf24c063f0310eccab8864e48dbeffcdd7240b4f8d1e01eba4fc703e6c9082b845bb55543b10f008dc7f4e78540411912ac1f36fa2aa90011dca40f323b09", + "3f675d6c364e06405d4868c904e40f3d81c32b083d91586db814d4cb4bf536b4ba209d82f11b4cb6da293b60b20d6122fc3e0e08e80c381dee83edd848211900" ] } } @@ -2098,7 +2103,7 @@ "symbols": [], "public_keys": [], "external_key": null, - "code": "check if true || 10000000000 * 10000000000 != 0;\ncheck if true || 9223372036854775807 + 1 != 0;\ncheck if true || -9223372036854775808 - 1 != 0;\n" + "code": "check if 10000000000 * 10000000000 != 0;\ncheck if 9223372036854775807 + 1 != 0;\ncheck if -9223372036854775808 - 1 != 0;\n" } ], "validations": { @@ -2110,9 +2115,9 @@ { "origin": 0, "checks": [ - "check if true || -9223372036854775808 - 1 != 0", - "check if true || 10000000000 * 10000000000 != 0", - "check if true || 9223372036854775807 + 1 != 0" + "check if -9223372036854775808 - 1 != 0", + "check if 10000000000 * 10000000000 != 0", + "check if 9223372036854775807 + 1 != 0" ] } ], @@ -2127,7 +2132,7 @@ }, "authorizer_code": "allow if true;\n", "revocation_ids": [ - "3346a22aae0abfc1ffa526f02f7650e90af909e5e519989026441e78cdc245b7fd126503cfdc8831325fc04307edc65238db319724477915f7040a2f6a719a05" + "31f01031b8d9cc312c346674625a2218b19a126e931318dc02d8d53aec2775faecd3f848f60c1446573c37ea0664fefc768f35ba5ce4365b83ff06f0c0409b0e" ] } } @@ -2143,7 +2148,7 @@ ], "public_keys": [], "external_key": null, - "code": "check if 1 != 3;\ncheck if 1 | 2 ^ 3 == 0;\ncheck if \"abcD12x\" != \"abcD12\";\ncheck if 2022-12-04T09:46:41Z != 2020-12-04T09:46:41Z;\ncheck if hex:12abcd != hex:12ab;\ncheck if [1, 4] != [1, 2];\n" + "code": "check if 1 !== 3;\ncheck if 1 | 2 ^ 3 === 0;\ncheck if \"abcD12x\" !== \"abcD12\";\ncheck if 2022-12-04T09:46:41Z !== 2020-12-04T09:46:41Z;\ncheck if hex:12abcd !== hex:12ab;\ncheck if [1, 4] !== [1, 2];\n" } ], "validations": { @@ -2155,12 +2160,12 @@ { "origin": 0, "checks": [ - "check if \"abcD12x\" != \"abcD12\"", - "check if 1 != 3", - "check if 1 | 2 ^ 3 == 0", - "check if 2022-12-04T09:46:41Z != 2020-12-04T09:46:41Z", - "check if [1, 4] != [1, 2]", - "check if hex:12abcd != hex:12ab" + "check if \"abcD12x\" !== \"abcD12\"", + "check if 1 !== 3", + "check if 1 | 2 ^ 3 === 0", + "check if 2022-12-04T09:46:41Z !== 2020-12-04T09:46:41Z", + "check if [1, 4] !== [1, 2]", + "check if hex:12abcd !== hex:12ab" ] } ], @@ -2222,7 +2227,7 @@ }, "authorizer_code": "test(false);\n\nallow if true;\n", "revocation_ids": [ - "2060031eb9968b492123440fa9cbc781f18be812961e765a34a8702d3eee0ed54910710efbb41b3141f60748a815012fe0e703a5b5604f4262d1ac7e79766b07" + "2e6dcafe4061dd86f61ad038a0a1bea816b85898bb86a14b16177e78ee249fcfb2455e2eed52ccfe8eafc679b1f34f9ef98e92e3719981dd4098b901b6cb040b" ] }, "rejection": { @@ -2272,14 +2277,14 @@ }, "authorizer_code": "test(true);\n\nallow if true;\n", "revocation_ids": [ - "2060031eb9968b492123440fa9cbc781f18be812961e765a34a8702d3eee0ed54910710efbb41b3141f60748a815012fe0e703a5b5604f4262d1ac7e79766b07" + "2e6dcafe4061dd86f61ad038a0a1bea816b85898bb86a14b16177e78ee249fcfb2455e2eed52ccfe8eafc679b1f34f9ef98e92e3719981dd4098b901b6cb040b" ] } } }, { "title": "test null", - "filename": "test30_null.bc", + "filename": "test030_null.bc", "token": [ { "symbols": [ @@ -2323,7 +2328,7 @@ }, "authorizer_code": "fact(null, null);\n\nallow if true;\n", "revocation_ids": [ - "bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003" + "c6c60ff84938908ca2bfcc7d674a400857c3349bdb373646c825e946ad0d08d76fd4734cd40f09884db0a41aee0c078897750e27706959d785750ef24acf100f" ] }, "rejection1": { @@ -2381,7 +2386,7 @@ }, "authorizer_code": "fact(null, 1);\n\nallow if true;\n", "revocation_ids": [ - "bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003" + "c6c60ff84938908ca2bfcc7d674a400857c3349bdb373646c825e946ad0d08d76fd4734cd40f09884db0a41aee0c078897750e27706959d785750ef24acf100f" ] }, "rejection2": { @@ -2439,7 +2444,7 @@ }, "authorizer_code": "fact(null, true);\n\nallow if true;\n", "revocation_ids": [ - "bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003" + "c6c60ff84938908ca2bfcc7d674a400857c3349bdb373646c825e946ad0d08d76fd4734cd40f09884db0a41aee0c078897750e27706959d785750ef24acf100f" ] }, "rejection3": { @@ -2497,7 +2502,274 @@ }, "authorizer_code": "fact(null, \"abcd\");\n\nallow if true;\n", "revocation_ids": [ - "bbf3ad51a70e935126b334f37be2bf66e90162353c19c524c0d3579ee71034996872b8433b132e6e0b519d371b0ab20481d58c4619183e8997c3744786e8e003" + "c6c60ff84938908ca2bfcc7d674a400857c3349bdb373646c825e946ad0d08d76fd4734cd40f09884db0a41aee0c078897750e27706959d785750ef24acf100f" + ] + } + } + }, + { + "title": "test heterogeneous equal", + "filename": "test031_heterogeneous_equal.bc", + "token": [ + { + "symbols": [ + "fact", + "value", + "fact2" + ], + "public_keys": [], + "external_key": null, + "code": "check if fact(1, $value), 1 == $value;\ncheck if fact2(1, $value), 1 != $value;\n" + } + ], + "validations": { + "authorized same type": { + "world": { + "facts": [ + { + "origin": [ + null + ], + "facts": [ + "fact(1, 1)", + "fact2(1, 2)" + ] + } + ], + "rules": [], + "checks": [ + { + "origin": 0, + "checks": [ + "check if fact(1, $value), 1 == $value", + "check if fact2(1, $value), 1 != $value" + ] + } + ], + "policies": [ + "allow if true" + ] + }, + "result": { + "Ok": 0 + }, + "authorizer_code": "fact(1, 1);\nfact2(1, 2);\n\nallow if true;\n", + "revocation_ids": [ + "d65b3aeceb6268124190f5eb87788a5eb81c89a3fc8370c9a3ea362731c55660b2b390ca6270e68afab90862bd2bbb808aa6b5576c975ae773a992a2434c930d" + ] + }, + "unauthorized failed logic different type": { + "world": { + "facts": [ + { + "origin": [ + null + ], + "facts": [ + "fact(1, true)", + "fact2(1, false)" + ] + } + ], + "rules": [], + "checks": [ + { + "origin": 0, + "checks": [ + "check if fact(1, $value), 1 == $value", + "check if fact2(1, $value), 1 != $value" + ] + } + ], + "policies": [ + "allow if true" + ] + }, + "result": { + "Err": { + "FailedLogic": { + "Unauthorized": { + "policy": { + "Allow": 0 + }, + "checks": [ + { + "Block": { + "block_id": 0, + "check_id": 0, + "rule": "check if fact(1, $value), 1 == $value" + } + } + ] + } + } + } + }, + "authorizer_code": "fact(1, true);\nfact2(1, false);\n\nallow if true;\n", + "revocation_ids": [ + "d65b3aeceb6268124190f5eb87788a5eb81c89a3fc8370c9a3ea362731c55660b2b390ca6270e68afab90862bd2bbb808aa6b5576c975ae773a992a2434c930d" + ] + } + } + }, + { + "title": "test laziness and closures", + "filename": "test032_laziness_closures.bc", + "token": [ + { + "symbols": [ + "x", + "p", + "q" + ], + "public_keys": [], + "external_key": null, + "code": "check if !false && true;\ncheck if false || true;\ncheck if (true || false) && true;\ncheck if !(false && \"x\".intersection(\"x\"));\ncheck if true || \"x\".intersection(\"x\");\ncheck if [1, 2, 3].all($p -> $p > 0);\ncheck if ![1, 2, 3].all($p -> $p == 2);\ncheck if [1, 2, 3].any($p -> $p > 2);\ncheck if ![1, 2, 3].any($p -> $p > 3);\ncheck if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q));\n" + } + ], + "validations": { + "": { + "world": { + "facts": [], + "rules": [], + "checks": [ + { + "origin": 0, + "checks": [ + "check if !(false && \"x\".intersection(\"x\"))", + "check if ![1, 2, 3].all($p -> $p == 2)", + "check if ![1, 2, 3].any($p -> $p > 3)", + "check if !false && true", + "check if (true || false) && true", + "check if [1, 2, 3].all($p -> $p > 0)", + "check if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q))", + "check if [1, 2, 3].any($p -> $p > 2)", + "check if false || true", + "check if true || \"x\".intersection(\"x\")" + ] + } + ], + "policies": [ + "allow if true" + ] + }, + "result": { + "Ok": 0 + }, + "authorizer_code": "allow if true;\n", + "revocation_ids": [ + "ef75002a071b56293152a4c9eb69ba0793614993e667736a6a92275ddd5aa35a287de5b13acaec72b5af6ba2ee8a3629b1a33cfa51597ae5afbebd8aa35dbe08" + ] + }, + "shadowing": { + "world": { + "facts": [], + "rules": [], + "checks": [ + { + "origin": 0, + "checks": [ + "check if !(false && \"x\".intersection(\"x\"))", + "check if ![1, 2, 3].all($p -> $p == 2)", + "check if ![1, 2, 3].any($p -> $p > 3)", + "check if !false && true", + "check if (true || false) && true", + "check if [1, 2, 3].all($p -> $p > 0)", + "check if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q))", + "check if [1, 2, 3].any($p -> $p > 2)", + "check if false || true", + "check if true || \"x\".intersection(\"x\")" + ] + } + ], + "policies": [ + "allow if [true].any($p -> [true].all($p -> $p))" + ] + }, + "result": { + "Err": { + "Execution": "ShadowedVariable" + } + }, + "authorizer_code": "allow if [true].any($p -> [true].all($p -> $p));\n", + "revocation_ids": [ + "ef75002a071b56293152a4c9eb69ba0793614993e667736a6a92275ddd5aa35a287de5b13acaec72b5af6ba2ee8a3629b1a33cfa51597ae5afbebd8aa35dbe08" + ] + } + } + }, + { + "title": "test .type()", + "filename": "test033_typeof.bc", + "token": [ + { + "symbols": [ + "integer", + "string", + "test", + "date", + "bytes", + "bool", + "set", + "null", + "t" + ], + "public_keys": [], + "external_key": null, + "code": "integer(1);\nstring(\"test\");\ndate(2023-12-28T00:00:00Z);\nbytes(hex:aa);\nbool(true);\nset([false, true]);\nnull(null);\ncheck if 1.type() == \"integer\";\ncheck if integer($t), $t.type() == \"integer\";\ncheck if \"test\".type() == \"string\";\ncheck if string($t), $t.type() == \"string\";\ncheck if (2023-12-28T00:00:00Z).type() == \"date\";\ncheck if date($t), $t.type() == \"date\";\ncheck if hex:aa.type() == \"bytes\";\ncheck if bytes($t), $t.type() == \"bytes\";\ncheck if true.type() == \"bool\";\ncheck if bool($t), $t.type() == \"bool\";\ncheck if [false, true].type() == \"set\";\ncheck if set($t), $t.type() == \"set\";\ncheck if null.type() == \"null\";\ncheck if null($t), $t.type() == \"null\";\n" + } + ], + "validations": { + "": { + "world": { + "facts": [ + { + "origin": [ + 0 + ], + "facts": [ + "bool(true)", + "bytes(hex:aa)", + "date(2023-12-28T00:00:00Z)", + "integer(1)", + "null(null)", + "set([false, true])", + "string(\"test\")" + ] + } + ], + "rules": [], + "checks": [ + { + "origin": 0, + "checks": [ + "check if \"test\".type() == \"string\"", + "check if (2023-12-28T00:00:00Z).type() == \"date\"", + "check if 1.type() == \"integer\"", + "check if [false, true].type() == \"set\"", + "check if bool($t), $t.type() == \"bool\"", + "check if bytes($t), $t.type() == \"bytes\"", + "check if date($t), $t.type() == \"date\"", + "check if hex:aa.type() == \"bytes\"", + "check if integer($t), $t.type() == \"integer\"", + "check if null($t), $t.type() == \"null\"", + "check if null.type() == \"null\"", + "check if set($t), $t.type() == \"set\"", + "check if string($t), $t.type() == \"string\"", + "check if true.type() == \"bool\"" + ] + } + ], + "policies": [ + "allow if true" + ] + }, + "result": { + "Ok": 0 + }, + "authorizer_code": "allow if true;\n", + "revocation_ids": [ + "be401996253dce45ac3d8b2f4b289af1f2cc2a4447a8265a1a2ca879c43377978ffc5ac6633053cd7c30e7c33cf258a37767226834bc80b005c48eb0229c4502" ] } } diff --git a/samples/current/test017_expressions.bc b/samples/current/test017_expressions.bc index 1f3234c07694321afef884cd0b547baa27d64096..7be7a4fda92f3feecff08e8c3a68d1c53bea2100 100644 GIT binary patch delta 143 zcmZqYo6gHB^nr(~bs}rc#qOR?Yy~bkE+!6XDG4qXE+zv8E*2ps4j>6+Gjg#=F>&x3NpVSl zRS3aUz~%Uibhxy@aw;$#5Ho=K_`oIs&48=s-PqvCXl}-30@k6&#mdDj(ZB(w8acpr zu_22!LB!Z0uGsvC(VWG>Hd=Wr)8@OAxPNEtWS*FEG0b|$q#^;a{G|u$9k*v2?w(qG o=&iAYt7gQvh+T^=&-mx_DJEi3T~7BAo#{*`R!Q?rE@o2!0FwDK%K!iX diff --git a/samples/current/test024_third_party.bc b/samples/current/test024_third_party.bc index 7bca415c6f4aeff3f27628adbaa6211f6e263493..d2aef52815e08c1d47cfaaec9ad0b8eaa1bc13e4 100644 GIT binary patch delta 149 zcmV;G0BZlr1Ih!Cxd8={xziGHPFJ%uTceGU^8b6lYjwA DDLF|c delta 149 zcmV;G0BZlr1Ih!Cxd8-`xLCT|;|b}> z%G?Sj#b8epkq@pvEYN@lR@=B?SrtgW zV^p2!&o#v7y*c4|mM^o6M_}!R0WSsp4EnTt{TxTWP@!Q)c>ZFTKI$ z8n(0|HCj$n>(PnFTYn$(eskd3wC?9C`-3g2zTN!0+_K<;QLR;6FRO^E-&dZ=ZyD9u z?=o?90DUl7ib<6y*GDla)yIZa{>$9|+`CfJ$W-*@n_Y7mowUXFO?KQ`-|=kfrrq4v zr)5_NFkagEfbW^a-$Rxs^TZ$PY_9xhFLZ5hwY2+M7LevNg^q|dI*wSk9{@1e4uW`9LOEWUq&z0OaNh!U&xp~*jxgR%7;$Shkx2+&oW>*eJEYL2uEZV%?HJ;TmrpS(M60sXpR+HJ76($$4_&M08$L5&%u{p$gWSnGq!f)GnSewIkVnpr^kt?UYznX2? or7*YYqqNVqTbkAhn|KqI{@C$xyx_5reb@Zrnb^rhX delta 627 zcmeC?S;9482m4JXt`!i(pVw?y=j>@H<1lCqRuKyZm zx7lC0`pk4ehw5a_H3<^?w=gJWa5>~GogeS{`oZscj-T88wbcqbJDWVEK2Da(nfB?( z!Um0>$7J+w+<2ZQt?+*?H`|J6TiHL4ANH&Z-L}(0k4@$>V-$M6HWDn8 z9hp>dxcNAfM!ooaR)3ptHMiAE84V-XNopO@4@->rId*bK^$NOEbZ^Y``YL;!8RXtO+4Z{HS(@K`tV(tIo%CEFT;`tNLCeRj z_9{`%VQXUZ7(WJT@A~xPi}hiV&)e7k+{dz&(eG~m+%H>BXR)VJaPUHA zTn<)e(WrmBI;3K5TG-_Lvlk<Yvmj!{b%zx^MV}AuXE_}v-rPzZbvU_)Vo-caIWN|(ROF64_;!C z4~jSceCyWN)xYe4_sJQj)zSr59cr7QzyGw8+V5>Mf=k#I)OyyifgQ{$b%c>CYVv;; ztI6@K9u8Sa1{sDgZ@;jsHoiS=d&KeDYZE5(>*}^YvfL!Faf(l9)BfB#>3=Jp|I|2C fum7J<@6m&`N8|(_9A5q6`p)cm_t+;tXH@|Jec${W diff --git a/samples/current/test027_integer_wraparound.bc b/samples/current/test027_integer_wraparound.bc index 50aa63b93cca6a963d474c44f4ea66bf90aba4b0..a3a2f712bbe52d427d020ea7d4d4aee910bd6c11 100644 GIT binary patch delta 130 zcmX@fw3JCm=pQ53WJU=#BRwu1E+!6XDYc0bs@!5o+z=2~pGy}kt3Gjp8l%|6y&4XN z9|R0{+&p8bW0F>q6s07wah6ctWMPRrOgFAty-_dy_2%*qk8eC8Zs9iOuh>%l{VD4= X-4*l1EV}tW+lK=Vv-u{gGO7Rorf4d- delta 166 zcmZ3=bdpIzXb}_Fc18&nBP%WoE+!6XDI+cxE+zxUi9)L4B3vv|OdNa|QcegdYc5N$ zE@P;!A~klXu8A`>9E{x-X|3bhfAIfOwGaAb0WZ0Jaz1@3Ib(vFi(JLoL$2HZ3Z*ii lztdr86o0^({q34*RqlF+uhRNT?M7FW~0`rL|yBLSoUZetC9l2a%E_N?jpT diff --git a/samples/current/test030_null.bc b/samples/current/test030_null.bc new file mode 100644 index 0000000000000000000000000000000000000000..8adc4fabf6c5c26ae9874a0392be6add374dcc11 GIT binary patch literal 248 zcmWf-$jFt>#gdkoT*Ad#mY7qTD#2!?$)(Q4#33!j!_mMY#N@;v#LUsiAtlVk$^~L@ zv2X#!xLBl^I7E%KiB&2lz$B!?!62j{5PCddv@WUpvZ=0LBolt%0ww9OUdj6GSpDX;F9ljfu zNWJ4>@0ec7r(Td5dA+ri?~~Vg0e&SVE`^yds`(~H1k1hK%KTqcEl*qd(4v59;hwqD M@>*LW?&~H30P875G5`Po literal 0 HcmV?d00001 diff --git a/samples/current/test031_heterogeneous_equal.bc b/samples/current/test031_heterogeneous_equal.bc new file mode 100644 index 0000000000000000000000000000000000000000..feb38732a79185bad7ddf3f375abfa33d4795d5e GIT binary patch literal 253 zcmWf-#>kb!#gdkoT*Ad#mY7qT%Eb!e7)h`hX>zG^F>y!>@o+S72r&sT3Ndpua!3ht zv2X!7T&!FmE*Faw6Nf00(kA>$#e`Hi7=#oALXQV*To@2(zFyS)nA$F*35~%`Eh&Matn?wAGu}Nf|FTqMC1FM6leut<3*L)$+8J4=oC) Q7VeoVEw8mD;=XPo0G*jkQ~&?~ literal 0 HcmV?d00001 diff --git a/samples/current/test032_laziness_closures.bc b/samples/current/test032_laziness_closures.bc new file mode 100644 index 0000000000000000000000000000000000000000..dfd0c5b2c838bb524adcb281c55d47a593e1c955 GIT binary patch literal 758 zcmWeS&&u_Lg^RI*i?M)=GT|};%jiqK72YQjI6jUz^aY71i1LDc(|AZ7=f4xh?%)0 zl*Bk1!S;bDpq~X8gg~}J+$d?}z-0&4YeAG=Ca_*nu!|)jVM(Ix5ECG_OOa?hGm^`t zpthHDm4e-$kH!6=O2KG;XM~s_WU6E=1Pd!>V3>fyg;hvWNt~kz9#+7Z0`WkBB?=~` zz@#|X^HM@891KDV0-?tPHZBZ^G+!@jeoSqbQS!_f<7Ms{u8?8>gDcZU|d(pctGtG^QZGHtt zRy|$6Z*SM)*nJ#IN?ZyvUsUr=j0l!{x0U(7s9K)3@}Wfm)xte<3;6N8Z=mpm5}hqRO=7Yi5A zd@dFtCJtsURxW0V1`aM3DJBk4BONX+kP;ydkQV0_~;7_J({rA`b;2DW1w z2uv-w41}o`QsH0_QV<9|9Tc z>}lA*dZcfI(i~SNC19k@d{NCeF(O#*-B#xRqH1~C%7+#OR15dam6q4q5^-NQ5diyo Bim(6x literal 0 HcmV?d00001 diff --git a/schema.proto b/schema.proto index bc6cb29..e2dfda2 100644 --- a/schema.proto +++ b/schema.proto @@ -80,6 +80,7 @@ message CheckV2 { enum Kind { One = 0; All = 1; + Reject = 2; } } @@ -97,6 +98,7 @@ message TermV2 { bytes bytes = 5; bool bool = 6; TermSet set = 7; + Empty null = 8; } } @@ -113,6 +115,7 @@ message Op { TermV2 value = 1; OpUnary unary = 2; OpBinary Binary = 3; + OpClosure closure = 4; } } @@ -121,6 +124,7 @@ message OpUnary { Negate = 0; Parens = 1; Length = 2; + TypeOf = 3; } required Kind kind = 1; @@ -149,11 +153,22 @@ message OpBinary { BitwiseOr = 18; BitwiseXor = 19; NotEqual = 20; + HeterogeneousEqual = 21; + HeterogeneousNotEqual = 22; + LazyAnd = 23; + LazyOr = 24; + All = 25; + Any = 26; } required Kind kind = 1; } +message OpClosure { + repeated uint32 params = 1; + repeated Op ops = 2; +} + message Policy { enum Kind { Allow = 0; @@ -228,4 +243,4 @@ message SnapshotBlock { repeated CheckV2 checks_v2 = 5; repeated Scope scope = 6; optional PublicKey externalKey = 7; -} \ No newline at end of file +} From 79e1b696722336582151022b24ed961eeaa9a486 Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Thu, 24 Oct 2024 18:13:31 +0200 Subject: [PATCH 05/11] Document lenient (heterogeneous) equality --- SPECIFICATIONS.md | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/SPECIFICATIONS.md b/SPECIFICATIONS.md index c0d5861..bdb89f4 100644 --- a/SPECIFICATIONS.md +++ b/SPECIFICATIONS.md @@ -138,29 +138,29 @@ rules application does not generate any new facts, we can stop. #### Data types An _integer_ is a signed 64 bits integer. It supports the following operations: -lower than, greater than, lower than or equal, greater than or equal, equal, -not equal, set inclusion, addition, subtraction, mutiplication, division, -bitwise and, bitwise or, bitwise xor. +lower than, greater than, lower than or equal, greater than or equal, strict equal, +strict not equal, set inclusion, addition, subtraction, mutiplication, division, +bitwise and, bitwise or, bitwise xor, lenient equal, lenient not equal. A _string_ is a suite of UTF-8 characters. It supports the following -operations: prefix, suffix, equal, not equal, set inclusion, regular -expression, concatenation (with `+`), substring test (with `.contains()`). +operations: prefix, suffix, strict equal, strict not equal, set inclusion, regular +expression, concatenation (with `+`), substring test (with `.contains()`), lenient equal, lenient not equal. A _byte array_ is a suite of bytes. It supports the following -operations: equal, not equal, set inclusion. +operations: strict equal, strict not equal, set inclusion, lenient equal, lenient not equal. A _date_ is a 64 bit unsigned integer representing a UTC unix timestamp (number of seconds since 1970-01-01T00:00:00Z). It supports -the following operations: `<`, `<=` (before), `>`, `>=` (after), equal, -not equal, set inclusion. +the following operations: `<`, `<=` (before), `>`, `>=` (after), strict equal, +strict not equal, set inclusion, lenient equal, lenient not equal. A _boolean_ is `true` or `false`. It supports the following operations: -`==`, `!=`, `||`, `&&`, set inclusion. +`===` (strict equal), `!==` (strict not equal), `||`, `&&`, set inclusion, `==` (lenient equal), `!=` (lenient not equal). -A _null_ is a default type indicating the absence of value. It supports the operations `==` and `!=` with any other type. _null_ is always equal to itself, and not equal to any other type +A _null_ is a default type indicating the absence of value. It supports `===` (strict equal), `!==` (strict not equal), `==` (lenient equal) and `!=` (lenient not equal). `null` is always equal to itself. A _set_ is a deduplicated list of terms of the same type. It cannot contain -variables or other sets. It supports equal, not equal, , intersection, union, -set inclusion. +variables or other sets. It supports strict equal, strict not equal, intersection, union, +set inclusion, lenient equal, lenient not equal. #### Grammar @@ -206,7 +206,7 @@ The logic language is described by the following EBNF grammar: ::= ([a-z] | [A-Z] ) ([a-z] | [A-Z] | [0-9] | "_" )* ::= | ("(" ? ? ")") - ::= "<" | ">" | "<=" | ">=" | "==" | "!=" | "&&" | "||" | "+" | "-" | "*" | "/" | "&" | "|" | "^" + ::= "<" | ">" | "<=" | ">=" | "===" | "!==" | "&&" | "||" | "+" | "-" | "*" | "/" | "&" | "|" | "^" | "==" | "!==" ::= (" " | "\t" | "\n")+ ``` @@ -454,8 +454,8 @@ Here are the currently defined binary operations: - _greater than_, defined on integers and dates, returns a boolean - _less or equal_, defined on integers and dates, returns a boolean - _greater or equal_, defined on integers and dates, returns a boolean -- _equal_, defined on integers, strings, byte arrays, dates, set, returns a boolean -- _not equal_, defined on integers, strings, byte arrays, dates, set, returns a boolean (v4 only) +- _strict equal_, defined on integers, strings, byte arrays, dates, set, null, returns a boolean +- _strict not equal_, defined on integers, strings, byte arrays, dates, set, null, returns a boolean (v4 only) - _contains_ takes a set and another value as argument, returns a boolean. Between two sets, indicates if the first set is a superset of the second one. between two strings, indicates a substring test. - _prefix_, defined on strings, returns a boolean @@ -472,10 +472,16 @@ Here are the currently defined binary operations: - _bitwiseAnd_, defined on integers, returns an integer (v4 only) - _bitwiseOr_, defined on integers, returns an integer (v4 only) - _bitwiseXor_, defined on integers, returns an integer (v4 only) +- _lenient equal_, defined on all types, returns a boolean (v6 only) +- _lenient not equal_, defined on all types, returns a boolean (v6 only) Integer operations must have overflow checks. If it overflows, the expression fails. +Strict equality fails with a type error when trying to compare different types. + +Lenient equality returns false when trying to compare different types. + #### Example The expression `1 + 2 < 4` will translate to the following opcodes: 1, 2, +, 4, < From e46fbbba961ce2820116c3e254312167eadef1f8 Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Thu, 24 Oct 2024 18:30:39 +0200 Subject: [PATCH 06/11] Document the `.type()` operation --- SPECIFICATIONS.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/SPECIFICATIONS.md b/SPECIFICATIONS.md index bdb89f4..7431192 100644 --- a/SPECIFICATIONS.md +++ b/SPECIFICATIONS.md @@ -140,27 +140,27 @@ rules application does not generate any new facts, we can stop. An _integer_ is a signed 64 bits integer. It supports the following operations: lower than, greater than, lower than or equal, greater than or equal, strict equal, strict not equal, set inclusion, addition, subtraction, mutiplication, division, -bitwise and, bitwise or, bitwise xor, lenient equal, lenient not equal. +bitwise and, bitwise or, bitwise xor, lenient equal, lenient not equal, typeof. A _string_ is a suite of UTF-8 characters. It supports the following operations: prefix, suffix, strict equal, strict not equal, set inclusion, regular -expression, concatenation (with `+`), substring test (with `.contains()`), lenient equal, lenient not equal. +expression, concatenation (with `+`), substring test (with `.contains()`), lenient equal, lenient not equal, typeof. A _byte array_ is a suite of bytes. It supports the following -operations: strict equal, strict not equal, set inclusion, lenient equal, lenient not equal. +operations: strict equal, strict not equal, set inclusion, lenient equal, lenient not equal, typeof. A _date_ is a 64 bit unsigned integer representing a UTC unix timestamp (number of seconds since 1970-01-01T00:00:00Z). It supports the following operations: `<`, `<=` (before), `>`, `>=` (after), strict equal, -strict not equal, set inclusion, lenient equal, lenient not equal. +strict not equal, set inclusion, lenient equal, lenient not equal, typeof. A _boolean_ is `true` or `false`. It supports the following operations: -`===` (strict equal), `!==` (strict not equal), `||`, `&&`, set inclusion, `==` (lenient equal), `!=` (lenient not equal). +`===` (strict equal), `!==` (strict not equal), `||`, `&&`, set inclusion, `==` (lenient equal), `!=` (lenient not equal), typeof. -A _null_ is a default type indicating the absence of value. It supports `===` (strict equal), `!==` (strict not equal), `==` (lenient equal) and `!=` (lenient not equal). `null` is always equal to itself. +A _null_ is a default type indicating the absence of value. It supports `===` (strict equal), `!==` (strict not equal), `==` (lenient equal) and `!=` (lenient not equal). `null` is always equal to itself, typeof. A _set_ is a deduplicated list of terms of the same type. It cannot contain variables or other sets. It supports strict equal, strict not equal, intersection, union, -set inclusion, lenient equal, lenient not equal. +set inclusion, lenient equal, lenient not equal, any, all, typeof. #### Grammar @@ -447,6 +447,14 @@ Here are the currently defined unary operations: - _parens_: returns its argument without modification (this is used when printing the expression, to avoid precedence errors) - _length_: defined on strings, byte arrays and sets (for strings, _length_ is defined as the number of bytes in the UTF-8 encoded string; the alternative of counting grapheme clusters would be inconsistent between languages) +- _type_, defined on all types, returns a string (v6 only) + - `integer` + - `string` + - `date` + - `bytes` + - `bool` + - `set` + - `null` Here are the currently defined binary operations: From 27ec12a66988f15e3f7343a7608e583b67bfda5e Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Thu, 24 Oct 2024 18:59:39 +0200 Subject: [PATCH 07/11] Document closures, any/all, eager/short-circuit boolean operators --- SPECIFICATIONS.md | 74 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 7 deletions(-) diff --git a/SPECIFICATIONS.md b/SPECIFICATIONS.md index 7431192..3c3a959 100644 --- a/SPECIFICATIONS.md +++ b/SPECIFICATIONS.md @@ -154,7 +154,7 @@ the following operations: `<`, `<=` (before), `>`, `>=` (after), strict equal, strict not equal, set inclusion, lenient equal, lenient not equal, typeof. A _boolean_ is `true` or `false`. It supports the following operations: -`===` (strict equal), `!==` (strict not equal), `||`, `&&`, set inclusion, `==` (lenient equal), `!=` (lenient not equal), typeof. +`===` (strict equal), `!==` (strict not equal), eager or, eager and, set inclusion, `==` (lenient equal), `!=` (lenient not equal), typeof, short-circuiting or, short-circuiting and. A _null_ is a default type indicating the absence of value. It supports `===` (strict equal), `!==` (strict not equal), `==` (lenient equal) and `!=` (lenient not equal). `null` is always equal to itself, typeof. @@ -429,7 +429,7 @@ rule. #### Execution Expressions are internally represented as a series of opcodes for a stack based -virtual machine. There are three kinds of opcodes: +virtual machine. There are four kinds of opcodes: - _value_: a raw value of any type. If it is a variable, the variable must also appear in a predicate, so the variable gets a real value for execution. When @@ -438,9 +438,22 @@ virtual machine. There are three kinds of opcodes: it pops a value from the stack, applies the operation, then pushes the result - _binary operation_: an operation that applies on two arguments. When executed, it pops two values from the stack, applies the operation, then pushes the result +- _closure_: a function definition containing the name of parameters and the body of the function expressed as a list of opcodes. Closures can be nested. After executing, the stack must contain only one value, of the boolean type. +##### Closures + +Closures are evaluated recursively. When executing a closure, a new empty stack is created, and the closure opcodes are evaluated. After evaluation, the stack must contain only one value, of any type, which is then pushed on the parent stack. + +The closure arguments are treated the same way as datalog variables and are replaced by their value when the corresponding opcode is evaluated. + +Shadowing (defining a parameter with the same name as a variable already in scope) is not allowed and should be rejected before starting the evaluation. + +Short-circuiting boolean operators (`&&` and `||`) are implemented using closures: the right-hand side is defined in a closure (taking zero arguments) and is only evaluated as needed. + +##### Operations + Here are the currently defined unary operations: - _negate_: boolean negation @@ -473,8 +486,8 @@ Here are the currently defined binary operations: - _sub_, defined on integers, returns an integer - _mul_, defined on integers, returns an integer - _div_, defined on integers, returns an integer -- _and_, defined on booleans, returns a boolean -- _or_, defined on booleans, returns a boolean +- _eager and_, defined on booleans, returns a boolean +- _eager or_, defined on booleans, returns a boolean - _intersection_, defined on sets, return a set that is the intersection of both arguments - _union_, defined on sets, return a set that is the union of both arguments - _bitwiseAnd_, defined on integers, returns an integer (v4 only) @@ -482,6 +495,10 @@ Here are the currently defined binary operations: - _bitwiseXor_, defined on integers, returns an integer (v4 only) - _lenient equal_, defined on all types, returns a boolean (v6 only) - _lenient not equal_, defined on all types, returns a boolean (v6 only) +- _any_, defined on sets, takes a closure term -> boolean, returns a boolean (v6 only) +- _all_, defined on sets, takes a closure term -> boolean, returns a boolean (v6 only) +- _short circuiting and_, defined on booleans, takes a closure () -> boolean, returns a boolean (v6 only) +- _short circuiting or_, defined on booleans, takes a closure () -> boolean, returns a boolean (v6 only) Integer operations must have overflow checks. If it overflows, the expression fails. @@ -492,14 +509,15 @@ Lenient equality returns false when trying to compare different types. #### Example -The expression `1 + 2 < 4` will translate to the following opcodes: 1, 2, +, 4, < +The expression `$a + 2 < 4` will translate to the following opcodes: $a, 2, +, 4, < -Here is how it would be executed: +Here is how it would be executed, given $a is bound to the value 1: ``` +Context: a ~> 1 Op | stack | [ ] -1 | [ 1 ] +$a | [ 1 ] 2 | [ 2, 1 ] + | [ 3 ] 4 | [ 4, 3 ] @@ -508,6 +526,48 @@ Op | stack The stack contains only one value, and it is `true`: the expression succeeds. +##### Closures + +The expression `[1,2].any($x -> $x == $a)` will translate to the following opcodes: [1,2], x->[$x, $a, ==], any. + +Here is how it would be executed, given $a is bound to the value 2: + +``` +Context: a ~> 2 +Op | stack + | [ ] +[1,2] | [ [1,2] ] +x->[$x,$a,==] | [ x->[$x,$a,==],[1,2] ] +any | … starting recursive evaluation … + + +Beginning new evaluation +Context: a ~> 2, x ~> 1 +Op | stack + | [] +$x | [ 1 ] +$a | [ 2, 1 ] +== | [ false ] + +The stack contains one value, false. So the evaluation must continue with the next set element. + +Beggining new evaluation +Context: a ~> 2, x ~> 2 +Op | stack + | [] +$x | [ 2 ] +$a | [ 2, 2 ] +== | [ true ] + +The stack contains one value, true. The evaluation can stop here, the evaluation of any can return true. + +Resuming parent stack +Context: a ~> 2 +Op | stack +any | true +``` +The stack contains only one value, and it is `true`: the expression succeeds. + ### Datalog fact generation Datalog fact generation works by repeatedly extending a Datalog _world_ until no new facts are generated. From 92d1c6767be25158a54212453ace560834239026 Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Mon, 4 Nov 2024 14:06:48 +0100 Subject: [PATCH 08/11] add spec and samples for map and array types --- SPECIFICATIONS.md | 19 +- samples/current/README.md | 210 +++++++++++---- samples/current/samples.json | 245 +++++++++++------- .../current/test031_heterogeneous_equal.bc | Bin 253 -> 748 bytes samples/current/test033_typeof.bc | Bin 882 -> 1034 bytes samples/current/test034_array_map.bc | Bin 0 -> 1951 bytes 6 files changed, 322 insertions(+), 152 deletions(-) create mode 100644 samples/current/test034_array_map.bc diff --git a/SPECIFICATIONS.md b/SPECIFICATIONS.md index 3c3a959..2197233 100644 --- a/SPECIFICATIONS.md +++ b/SPECIFICATIONS.md @@ -77,6 +77,8 @@ _predicates_ over the following types: - _boolean_ - _null_ - _set_ a deduplicated list of values of any type, except _variable_ or _set_ +- _array_ an array of values of any type, expect _variable_ (nested arrays are allowed) +- _map_ a map of key/value pairs. keys must be either strings or integers, values can be of any type, except _variable_ (nested maps are allowed) While a Biscuit token does not use a textual representation for storage, we use one for parsing and pretty printing of Datalog elements. @@ -118,8 +120,10 @@ We will represent the various types as follows: - byte array: `hex:01A2` - date in RFC 3339 format: `1985-04-12T23:20:50.52Z` - boolean: `true` or `false` -- null: `null`, supported since block version 5 -- set: `[ "a", "b", "c"]` +- null: `null`, supported since block version 6 +- set: `{ "a", "b", "c"}` +- array: `[ "a", true, null]`, supported since block version 6 +- map: `{ "a": true, 12: "a" }`, supported since block version 6 As an example, assuming we have the following facts: `parent("a", "b")`, `parent("b", "c")`, `parent("c", "d")`. If we apply the rule @@ -162,6 +166,10 @@ A _set_ is a deduplicated list of terms of the same type. It cannot contain variables or other sets. It supports strict equal, strict not equal, intersection, union, set inclusion, lenient equal, lenient not equal, any, all, typeof. +An _array_ is an ordered list of terms, not necessarily of the same type. It supports `===` (strict equal), `!==` (strict not equal), `==` (lenient equal) and `!=` (lenient not equal), contains, prefix, suffix, get, typeof. + +A _map_ is an unordered collection of key/value pairs, with unique keys. Keys are either strings or integers, values can be any term. It supports `===` (strict equal), `!==` (strict not equal), `==` (lenient equal) and `!=` (lenient not equal), contains, get, typeof. + #### Grammar The logic language is described by the following EBNF grammar: @@ -197,7 +205,10 @@ The logic language is described by the following EBNF grammar: ::= "true" | "false" ::= "null" ::= [0-9]* "-" [0-9] [0-9] "-" [0-9] [0-9] "T" [0-9] [0-9] ":" [0-9] [0-9] ":" [0-9] [0-9] ( "Z" | ( ("+" | "-") [0-9] [0-9] ":" [0-9] [0-9] )) - ::= "[" ? ( ( ? "," ? )* ? )? "]" + ::= "{" ? ( ( ? "," ? )* ? )? "}" + ::= "[" ? ( ( ? "," ? )* ? )? "]" + ::= ( | ) ? ":" ? + ::= "{" ? ( ( ? "," ? )* ? )? "}" ::= (? ? )* ::= | ( ? ) @@ -305,7 +316,7 @@ succeeds (in the case of `reject if`, the check will fail if any query matches). - a `reject if` query succeeds if no set of facts matches the body and expressions `check all` can only be used starting from block version 4. -`reject if` can only be used starting from block version 5. +`reject if` can only be used starting from block version 6. Here are some examples of writing checks: diff --git a/samples/current/README.md b/samples/current/README.md index 7ff9275..06b48e3 100644 --- a/samples/current/README.md +++ b/samples/current/README.md @@ -825,7 +825,7 @@ public keys: [] ``` valid_date("file1") <- time($0), resource("file1"), $0 <= 2030-12-31T12:59:59Z; -valid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, !["file1"].contains($1); +valid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, !{"file1"}.contains($1); check if valid_date($0), resource($0); ``` @@ -886,7 +886,7 @@ World { ), rules: [ "valid_date(\"file1\") <- time($0), resource(\"file1\"), $0 <= 2030-12-31T12:59:59Z", - "valid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, ![\"file1\"].contains($1)", + "valid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, !{\"file1\"}.contains($1)", ], }, ] @@ -953,7 +953,7 @@ World { ), rules: [ "valid_date(\"file1\") <- time($0), resource(\"file1\"), $0 <= 2030-12-31T12:59:59Z", - "valid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, ![\"file1\"].contains($1)", + "valid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, !{\"file1\"}.contains($1)", ], }, ] @@ -1246,17 +1246,17 @@ check if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z; check if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z; check if 2020-12-04T09:46:41Z === 2020-12-04T09:46:41Z; check if hex:12ab === hex:12ab; -check if [1, 2].contains(2); -check if [2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z].contains(2020-12-04T09:46:41Z); -check if [false, true].contains(true); -check if ["abc", "def"].contains("abc"); -check if [hex:12ab, hex:34de].contains(hex:34de); -check if [1, 2].contains([2]); -check if [1, 2] === [1, 2]; -check if [1, 2].intersection([2, 3]) === [2]; -check if [1, 2].union([2, 3]) === [1, 2, 3]; -check if [1, 2, 3].intersection([1, 2]).contains(1); -check if [1, 2, 3].intersection([1, 2]).length() === 2; +check if {1, 2}.contains(2); +check if {2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z}.contains(2020-12-04T09:46:41Z); +check if {false, true}.contains(true); +check if {"abc", "def"}.contains("abc"); +check if {hex:12ab, hex:34de}.contains(hex:34de); +check if {1, 2}.contains({2}); +check if {1, 2} === {1, 2}; +check if {1, 2}.intersection({2, 3}) === {2}; +check if {1, 2}.union({2, 3}) === {1, 2, 3}; +check if {1, 2, 3}.intersection({1, 2}).contains(1); +check if {1, 2, 3}.intersection({1, 2}).length() === 2; ``` ### validation @@ -1303,21 +1303,21 @@ World { "check if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z", "check if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z", "check if 3 === 3", - "check if [\"abc\", \"def\"].contains(\"abc\")", - "check if [1, 2, 3].intersection([1, 2]).contains(1)", - "check if [1, 2, 3].intersection([1, 2]).length() === 2", - "check if [1, 2] === [1, 2]", - "check if [1, 2].contains(2)", - "check if [1, 2].contains([2])", - "check if [1, 2].intersection([2, 3]) === [2]", - "check if [1, 2].union([2, 3]) === [1, 2, 3]", - "check if [2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z].contains(2020-12-04T09:46:41Z)", - "check if [false, true].contains(true)", - "check if [hex:12ab, hex:34de].contains(hex:34de)", "check if false === false", "check if hex:12ab === hex:12ab", "check if true", "check if true === true", + "check if {\"abc\", \"def\"}.contains(\"abc\")", + "check if {1, 2, 3}.intersection({1, 2}).contains(1)", + "check if {1, 2, 3}.intersection({1, 2}).length() === 2", + "check if {1, 2} === {1, 2}", + "check if {1, 2}.contains(2)", + "check if {1, 2}.contains({2})", + "check if {1, 2}.intersection({2, 3}) === {2}", + "check if {1, 2}.union({2, 3}) === {1, 2, 3}", + "check if {2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z}.contains(2020-12-04T09:46:41Z)", + "check if {false, true}.contains(true)", + "check if {hex:12ab, hex:34de}.contains(hex:34de)", ], }, ] @@ -1901,7 +1901,7 @@ symbols: ["allowed_operations", "A", "B", "op", "allowed"] public keys: [] ``` -allowed_operations(["A", "B"]); +allowed_operations({"A", "B"}); check all operation($op), allowed_operations($allowed), $allowed.contains($op); ``` @@ -1938,7 +1938,7 @@ World { ), }, facts: [ - "allowed_operations([\"A\", \"B\"])", + "allowed_operations({\"A\", \"B\"})", ], }, ] @@ -1993,7 +1993,7 @@ World { ), }, facts: [ - "allowed_operations([\"A\", \"B\"])", + "allowed_operations({\"A\", \"B\"})", ], }, ] @@ -2314,7 +2314,7 @@ check if 1 | 2 ^ 3 === 0; check if "abcD12x" !== "abcD12"; check if 2022-12-04T09:46:41Z !== 2020-12-04T09:46:41Z; check if hex:12abcd !== hex:12ab; -check if [1, 4] !== [1, 2]; +check if {1, 4} !== {1, 2}; ``` ### validation @@ -2342,8 +2342,8 @@ World { "check if 1 !== 3", "check if 1 | 2 ^ 3 === 0", "check if 2022-12-04T09:46:41Z !== 2020-12-04T09:46:41Z", - "check if [1, 4] !== [1, 2]", "check if hex:12abcd !== hex:12ab", + "check if {1, 4} !== {1, 2}", ], }, ] @@ -2776,11 +2776,11 @@ check if false || true; check if (true || false) && true; check if !(false && "x".intersection("x")); check if true || "x".intersection("x"); -check if [1, 2, 3].all($p -> $p > 0); -check if ![1, 2, 3].all($p -> $p == 2); -check if [1, 2, 3].any($p -> $p > 2); -check if ![1, 2, 3].any($p -> $p > 3); -check if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q)); +check if {1, 2, 3}.all($p -> $p > 0); +check if !{1, 2, 3}.all($p -> $p == 2); +check if {1, 2, 3}.any($p -> $p > 2); +check if !{1, 2, 3}.any($p -> $p > 3); +check if {1, 2, 3}.any($p -> $p > 1 && {3, 4, 5}.any($q -> $p == $q)); ``` ### validation @@ -2805,15 +2805,15 @@ World { ), checks: [ "check if !(false && \"x\".intersection(\"x\"))", - "check if ![1, 2, 3].all($p -> $p == 2)", - "check if ![1, 2, 3].any($p -> $p > 3)", "check if !false && true", + "check if !{1, 2, 3}.all($p -> $p == 2)", + "check if !{1, 2, 3}.any($p -> $p > 3)", "check if (true || false) && true", - "check if [1, 2, 3].all($p -> $p > 0)", - "check if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q))", - "check if [1, 2, 3].any($p -> $p > 2)", "check if false || true", "check if true || \"x\".intersection(\"x\")", + "check if {1, 2, 3}.all($p -> $p > 0)", + "check if {1, 2, 3}.any($p -> $p > 1 && {3, 4, 5}.any($q -> $p == $q))", + "check if {1, 2, 3}.any($p -> $p > 2)", ], }, ] @@ -2846,15 +2846,15 @@ World { ), checks: [ "check if !(false && \"x\".intersection(\"x\"))", - "check if ![1, 2, 3].all($p -> $p == 2)", - "check if ![1, 2, 3].any($p -> $p > 3)", "check if !false && true", + "check if !{1, 2, 3}.all($p -> $p == 2)", + "check if !{1, 2, 3}.any($p -> $p > 3)", "check if (true || false) && true", - "check if [1, 2, 3].all($p -> $p > 0)", - "check if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q))", - "check if [1, 2, 3].any($p -> $p > 2)", "check if false || true", "check if true || \"x\".intersection(\"x\")", + "check if {1, 2, 3}.all($p -> $p > 0)", + "check if {1, 2, 3}.any($p -> $p > 1 && {3, 4, 5}.any($q -> $p == $q))", + "check if {1, 2, 3}.any($p -> $p > 2)", ], }, ] @@ -2873,7 +2873,7 @@ result: `Err(Execution(ShadowedVariable))` ### token authority: -symbols: ["integer", "string", "test", "date", "bytes", "bool", "set", "null", "t"] +symbols: ["integer", "string", "test", "date", "bytes", "bool", "set", "null", "array", "map", "a", "t"] public keys: [] @@ -2883,8 +2883,10 @@ string("test"); date(2023-12-28T00:00:00Z); bytes(hex:aa); bool(true); -set([false, true]); +set({false, true}); null(null); +array([1, 2, 3]); +map({"a": true}); check if 1.type() == "integer"; check if integer($t), $t.type() == "integer"; check if "test".type() == "string"; @@ -2895,10 +2897,12 @@ check if hex:aa.type() == "bytes"; check if bytes($t), $t.type() == "bytes"; check if true.type() == "bool"; check if bool($t), $t.type() == "bool"; -check if [false, true].type() == "set"; +check if {false, true}.type() == "set"; check if set($t), $t.type() == "set"; check if null.type() == "null"; check if null($t), $t.type() == "null"; +check if array($t), $t.type() == "array"; +check if map($t), $t.type() == "map"; ``` ### validation @@ -2909,7 +2913,7 @@ allow if true; ``` revocation ids: -- `be401996253dce45ac3d8b2f4b289af1f2cc2a4447a8265a1a2ca879c43377978ffc5ac6633053cd7c30e7c33cf258a37767226834bc80b005c48eb0229c4502` +- `c8f7ff152b40a3e8f3ab19a435ccd16c41288762864022895b99d2abb6330c794b3f1378a4651b31d249f4c35b69246d88124d40e05e634a0eb9ca9e54b1ca0a` authorizer world: ``` @@ -2922,12 +2926,14 @@ World { ), }, facts: [ + "array([1, 2, 3])", "bool(true)", "bytes(hex:aa)", "date(2023-12-28T00:00:00Z)", "integer(1)", + "map({\"a\": true})", "null(null)", - "set([false, true])", + "set({false, true})", "string(\"test\")", ], }, @@ -2942,17 +2948,119 @@ World { "check if \"test\".type() == \"string\"", "check if (2023-12-28T00:00:00Z).type() == \"date\"", "check if 1.type() == \"integer\"", - "check if [false, true].type() == \"set\"", + "check if array($t), $t.type() == \"array\"", "check if bool($t), $t.type() == \"bool\"", "check if bytes($t), $t.type() == \"bytes\"", "check if date($t), $t.type() == \"date\"", "check if hex:aa.type() == \"bytes\"", "check if integer($t), $t.type() == \"integer\"", + "check if map($t), $t.type() == \"map\"", "check if null($t), $t.type() == \"null\"", "check if null.type() == \"null\"", "check if set($t), $t.type() == \"set\"", "check if string($t), $t.type() == \"string\"", "check if true.type() == \"bool\"", + "check if {false, true}.type() == \"set\"", + ], + }, +] + policies: [ + "allow if true", +] +} +``` + +result: `Ok(0)` + + +------------------------------ + +## test array and map operations (v5 blocks): test034_array_map.bc +### token + +authority: +symbols: ["a", "b", "c", "p", "d", "A", "kv", "id", "roles"] + +public keys: [] + +``` +check if [1, 2, 1].length() == 3; +check if ["a", "b"] != true; +check if ["a", "b"] != [1, 2, 3]; +check if ["a", "b"] == ["a", "b"]; +check if ["a", "b"] === ["a", "b"]; +check if ["a", "b"] !== ["a", "c"]; +check if ["a", "b", "c"].contains("c"); +check if [1, 2, 3].starts_with([1, 2]); +check if [4, 5, 6].ends_with([6]); +check if [1, 2, "a"].get(2) == "a"; +check if [1, 2].get(3) == null; +check if [1, 2, 3].all($p -> $p > 0); +check if [1, 2, 3].any($p -> $p > 2); +check if {"a": 1, "b": 2, "c": 3, "d": 4}.length() == 4; +check if {1: "a", 2: "b"} != true; +check if {1: "a", 2: "b"} != {"a": 1, "b": 2}; +check if {1: "a", 2: "b"} == {1: "a", 2: "b"}; +check if {1: "a", 2: "b"} !== {"a": 1, "b": 2}; +check if {1: "a", 2: "b"} === {1: "a", 2: "b"}; +check if {"a": 1, "b": 2, "c": 3, "d": 4}.contains("d"); +check if {1: "A", "a": 1, "b": 2}.get("a") == 1; +check if {1: "A", "a": 1, "b": 2}.get(1) == "A"; +check if {1: "A", "a": 1, "b": 2}.get("c") == null; +check if {1: "A", "a": 1, "b": 2}.get(2) == null; +check if {"a": 1, "b": 2}.all($kv -> $kv.get(0) != "c" && $kv.get(1) < 3); +check if {1: "A", "a": 1, "b": 2}.any($kv -> $kv.get(0) == 1 && $kv.get(1) == "A"); +check if {"user": {"id": 1, "roles": ["admin"]}}.get("user").get("roles").contains("admin"); +``` + +### validation + +authorizer code: +``` +allow if true; +``` + +revocation ids: +- `8041144f92616477f1cd00b81e8be79581202a3853b08b3d477797b0d91f30c02fd7c01ca91a00f8a222d6be4794cc287baa361a1a00d5941518c1917967ec03` + +authorizer world: +``` +World { + facts: [] + rules: [] + checks: [ + Checks { + origin: Some( + 0, + ), + checks: [ + "check if [\"a\", \"b\", \"c\"].contains(\"c\")", + "check if [\"a\", \"b\"] != [1, 2, 3]", + "check if [\"a\", \"b\"] != true", + "check if [\"a\", \"b\"] !== [\"a\", \"c\"]", + "check if [\"a\", \"b\"] == [\"a\", \"b\"]", + "check if [\"a\", \"b\"] === [\"a\", \"b\"]", + "check if [1, 2, \"a\"].get(2) == \"a\"", + "check if [1, 2, 1].length() == 3", + "check if [1, 2, 3].all($p -> $p > 0)", + "check if [1, 2, 3].any($p -> $p > 2)", + "check if [1, 2, 3].starts_with([1, 2])", + "check if [1, 2].get(3) == null", + "check if [4, 5, 6].ends_with([6])", + "check if {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}.contains(\"d\")", + "check if {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}.length() == 4", + "check if {\"a\": 1, \"b\": 2}.all($kv -> $kv.get(0) != \"c\" && $kv.get(1) < 3)", + "check if {\"user\": {\"id\": 1, \"roles\": [\"admin\"]}}.get(\"user\").get(\"roles\").contains(\"admin\")", + "check if {1: \"A\", \"a\": 1, \"b\": 2}.any($kv -> $kv.get(0) == 1 && $kv.get(1) == \"A\")", + "check if {1: \"A\", \"a\": 1, \"b\": 2}.get(\"a\") == 1", + "check if {1: \"A\", \"a\": 1, \"b\": 2}.get(\"c\") == null", + "check if {1: \"A\", \"a\": 1, \"b\": 2}.get(1) == \"A\"", + "check if {1: \"A\", \"a\": 1, \"b\": 2}.get(2) == null", + "check if {1: \"a\", 2: \"b\"} != true", + "check if {1: \"a\", 2: \"b\"} != {\"a\": 1, \"b\": 2}", + "check if {1: \"a\", 2: \"b\"} !== {\"a\": 1, \"b\": 2}", + "check if {1: \"a\", 2: \"b\"} == {1: \"a\", 2: \"b\"}", + "check if {1: \"a\", 2: \"b\"} === {1: \"a\", 2: \"b\"}", ], }, ] diff --git a/samples/current/samples.json b/samples/current/samples.json index a68baa6..140d3d7 100644 --- a/samples/current/samples.json +++ b/samples/current/samples.json @@ -862,7 +862,7 @@ ], "public_keys": [], "external_key": null, - "code": "valid_date(\"file1\") <- time($0), resource(\"file1\"), $0 <= 2030-12-31T12:59:59Z;\nvalid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, ![\"file1\"].contains($1);\ncheck if valid_date($0), resource($0);\n" + "code": "valid_date(\"file1\") <- time($0), resource(\"file1\"), $0 <= 2030-12-31T12:59:59Z;\nvalid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, !{\"file1\"}.contains($1);\ncheck if valid_date($0), resource($0);\n" } ], "validations": { @@ -902,7 +902,7 @@ "origin": 1, "rules": [ "valid_date(\"file1\") <- time($0), resource(\"file1\"), $0 <= 2030-12-31T12:59:59Z", - "valid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, ![\"file1\"].contains($1)" + "valid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, !{\"file1\"}.contains($1)" ] } ], @@ -954,7 +954,7 @@ "origin": 1, "rules": [ "valid_date(\"file1\") <- time($0), resource(\"file1\"), $0 <= 2030-12-31T12:59:59Z", - "valid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, ![\"file1\"].contains($1)" + "valid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, !{\"file1\"}.contains($1)" ] } ], @@ -1245,7 +1245,7 @@ ], "public_keys": [], "external_key": null, - "code": "check if true;\ncheck if !false;\ncheck if true === true;\ncheck if false === false;\ncheck if 1 < 2;\ncheck if 2 > 1;\ncheck if 1 <= 2;\ncheck if 1 <= 1;\ncheck if 2 >= 1;\ncheck if 2 >= 2;\ncheck if 3 === 3;\ncheck if 1 + 2 * 3 - 4 / 2 === 5;\ncheck if \"hello world\".starts_with(\"hello\"), \"hello world\".ends_with(\"world\");\ncheck if \"aaabde\".matches(\"a*c?.e\");\ncheck if \"aaabde\".contains(\"abd\");\ncheck if \"aaabde\" === \"aaa\" + \"b\" + \"de\";\ncheck if \"abcD12\" === \"abcD12\";\ncheck if \"abcD12\".length() === 6;\ncheck if \"é\".length() === 2;\ncheck if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z;\ncheck if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z === 2020-12-04T09:46:41Z;\ncheck if hex:12ab === hex:12ab;\ncheck if [1, 2].contains(2);\ncheck if [2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z].contains(2020-12-04T09:46:41Z);\ncheck if [false, true].contains(true);\ncheck if [\"abc\", \"def\"].contains(\"abc\");\ncheck if [hex:12ab, hex:34de].contains(hex:34de);\ncheck if [1, 2].contains([2]);\ncheck if [1, 2] === [1, 2];\ncheck if [1, 2].intersection([2, 3]) === [2];\ncheck if [1, 2].union([2, 3]) === [1, 2, 3];\ncheck if [1, 2, 3].intersection([1, 2]).contains(1);\ncheck if [1, 2, 3].intersection([1, 2]).length() === 2;\n" + "code": "check if true;\ncheck if !false;\ncheck if true === true;\ncheck if false === false;\ncheck if 1 < 2;\ncheck if 2 > 1;\ncheck if 1 <= 2;\ncheck if 1 <= 1;\ncheck if 2 >= 1;\ncheck if 2 >= 2;\ncheck if 3 === 3;\ncheck if 1 + 2 * 3 - 4 / 2 === 5;\ncheck if \"hello world\".starts_with(\"hello\"), \"hello world\".ends_with(\"world\");\ncheck if \"aaabde\".matches(\"a*c?.e\");\ncheck if \"aaabde\".contains(\"abd\");\ncheck if \"aaabde\" === \"aaa\" + \"b\" + \"de\";\ncheck if \"abcD12\" === \"abcD12\";\ncheck if \"abcD12\".length() === 6;\ncheck if \"é\".length() === 2;\ncheck if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z;\ncheck if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z === 2020-12-04T09:46:41Z;\ncheck if hex:12ab === hex:12ab;\ncheck if {1, 2}.contains(2);\ncheck if {2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z}.contains(2020-12-04T09:46:41Z);\ncheck if {false, true}.contains(true);\ncheck if {\"abc\", \"def\"}.contains(\"abc\");\ncheck if {hex:12ab, hex:34de}.contains(hex:34de);\ncheck if {1, 2}.contains({2});\ncheck if {1, 2} === {1, 2};\ncheck if {1, 2}.intersection({2, 3}) === {2};\ncheck if {1, 2}.union({2, 3}) === {1, 2, 3};\ncheck if {1, 2, 3}.intersection({1, 2}).contains(1);\ncheck if {1, 2, 3}.intersection({1, 2}).length() === 2;\n" } ], "validations": { @@ -1280,21 +1280,21 @@ "check if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z", "check if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z", "check if 3 === 3", - "check if [\"abc\", \"def\"].contains(\"abc\")", - "check if [1, 2, 3].intersection([1, 2]).contains(1)", - "check if [1, 2, 3].intersection([1, 2]).length() === 2", - "check if [1, 2] === [1, 2]", - "check if [1, 2].contains(2)", - "check if [1, 2].contains([2])", - "check if [1, 2].intersection([2, 3]) === [2]", - "check if [1, 2].union([2, 3]) === [1, 2, 3]", - "check if [2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z].contains(2020-12-04T09:46:41Z)", - "check if [false, true].contains(true)", - "check if [hex:12ab, hex:34de].contains(hex:34de)", "check if false === false", "check if hex:12ab === hex:12ab", "check if true", - "check if true === true" + "check if true === true", + "check if {\"abc\", \"def\"}.contains(\"abc\")", + "check if {1, 2, 3}.intersection({1, 2}).contains(1)", + "check if {1, 2, 3}.intersection({1, 2}).length() === 2", + "check if {1, 2} === {1, 2}", + "check if {1, 2}.contains(2)", + "check if {1, 2}.contains({2})", + "check if {1, 2}.intersection({2, 3}) === {2}", + "check if {1, 2}.union({2, 3}) === {1, 2, 3}", + "check if {2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z}.contains(2020-12-04T09:46:41Z)", + "check if {false, true}.contains(true)", + "check if {hex:12ab, hex:34de}.contains(hex:34de)" ] } ], @@ -1814,7 +1814,7 @@ ], "public_keys": [], "external_key": null, - "code": "allowed_operations([\"A\", \"B\"]);\ncheck all operation($op), allowed_operations($allowed), $allowed.contains($op);\n" + "code": "allowed_operations({\"A\", \"B\"});\ncheck all operation($op), allowed_operations($allowed), $allowed.contains($op);\n" } ], "validations": { @@ -1835,7 +1835,7 @@ 0 ], "facts": [ - "allowed_operations([\"A\", \"B\"])" + "allowed_operations({\"A\", \"B\"})" ] } ], @@ -1877,7 +1877,7 @@ 0 ], "facts": [ - "allowed_operations([\"A\", \"B\"])" + "allowed_operations({\"A\", \"B\"})" ] } ], @@ -2148,7 +2148,7 @@ ], "public_keys": [], "external_key": null, - "code": "check if 1 !== 3;\ncheck if 1 | 2 ^ 3 === 0;\ncheck if \"abcD12x\" !== \"abcD12\";\ncheck if 2022-12-04T09:46:41Z !== 2020-12-04T09:46:41Z;\ncheck if hex:12abcd !== hex:12ab;\ncheck if [1, 4] !== [1, 2];\n" + "code": "check if 1 !== 3;\ncheck if 1 | 2 ^ 3 === 0;\ncheck if \"abcD12x\" !== \"abcD12\";\ncheck if 2022-12-04T09:46:41Z !== 2020-12-04T09:46:41Z;\ncheck if hex:12abcd !== hex:12ab;\ncheck if {1, 4} !== {1, 2};\n" } ], "validations": { @@ -2164,8 +2164,8 @@ "check if 1 !== 3", "check if 1 | 2 ^ 3 === 0", "check if 2022-12-04T09:46:41Z !== 2020-12-04T09:46:41Z", - "check if [1, 4] !== [1, 2]", - "check if hex:12abcd !== hex:12ab" + "check if hex:12abcd !== hex:12ab", + "check if {1, 4} !== {1, 2}" ] } ], @@ -2513,71 +2513,41 @@ "token": [ { "symbols": [ - "fact", - "value", - "fact2" + "abcD12", + "abcD12x" ], "public_keys": [], "external_key": null, - "code": "check if fact(1, $value), 1 == $value;\ncheck if fact2(1, $value), 1 != $value;\n" + "code": "check if true == true;\ncheck if false != false;\ncheck if 1 != true;\ncheck if 1 == 1;\ncheck if 1 != 3;\ncheck if 1 != true;\ncheck if \"abcD12\" == \"abcD12\";\ncheck if \"abcD12x\" != \"abcD12\";\ncheck if \"abcD12x\" != true;\ncheck if 2022-12-04T09:46:41Z == 2022-12-04T09:46:41Z;\ncheck if 2022-12-04T09:46:41Z != 2020-12-04T09:46:41Z;\ncheck if 2022-12-04T09:46:41Z != true;\ncheck if hex:12abcd == hex:12abcd;\ncheck if hex:12abcd != hex:12ab;\ncheck if hex:12abcd != true;\ncheck if {1, 2} == {1, 2};\ncheck if {1, 4} != {1, 2};\ncheck if {1, 4} != true;\n" } ], "validations": { - "authorized same type": { - "world": { - "facts": [ - { - "origin": [ - null - ], - "facts": [ - "fact(1, 1)", - "fact2(1, 2)" - ] - } - ], - "rules": [], - "checks": [ - { - "origin": 0, - "checks": [ - "check if fact(1, $value), 1 == $value", - "check if fact2(1, $value), 1 != $value" - ] - } - ], - "policies": [ - "allow if true" - ] - }, - "result": { - "Ok": 0 - }, - "authorizer_code": "fact(1, 1);\nfact2(1, 2);\n\nallow if true;\n", - "revocation_ids": [ - "d65b3aeceb6268124190f5eb87788a5eb81c89a3fc8370c9a3ea362731c55660b2b390ca6270e68afab90862bd2bbb808aa6b5576c975ae773a992a2434c930d" - ] - }, - "unauthorized failed logic different type": { + "": { "world": { - "facts": [ - { - "origin": [ - null - ], - "facts": [ - "fact(1, true)", - "fact2(1, false)" - ] - } - ], + "facts": [], "rules": [], "checks": [ { "origin": 0, "checks": [ - "check if fact(1, $value), 1 == $value", - "check if fact2(1, $value), 1 != $value" + "check if \"abcD12\" == \"abcD12\"", + "check if \"abcD12x\" != \"abcD12\"", + "check if \"abcD12x\" != true", + "check if 1 != 3", + "check if 1 != true", + "check if 1 != true", + "check if 1 == 1", + "check if 2022-12-04T09:46:41Z != 2020-12-04T09:46:41Z", + "check if 2022-12-04T09:46:41Z != true", + "check if 2022-12-04T09:46:41Z == 2022-12-04T09:46:41Z", + "check if false != false", + "check if hex:12abcd != hex:12ab", + "check if hex:12abcd != true", + "check if hex:12abcd == hex:12abcd", + "check if true == true", + "check if {1, 2} == {1, 2}", + "check if {1, 4} != true", + "check if {1, 4} != {1, 2}" ] } ], @@ -2596,8 +2566,8 @@ { "Block": { "block_id": 0, - "check_id": 0, - "rule": "check if fact(1, $value), 1 == $value" + "check_id": 1, + "rule": "check if false != false" } } ] @@ -2605,9 +2575,9 @@ } } }, - "authorizer_code": "fact(1, true);\nfact2(1, false);\n\nallow if true;\n", + "authorizer_code": "allow if true;\n", "revocation_ids": [ - "d65b3aeceb6268124190f5eb87788a5eb81c89a3fc8370c9a3ea362731c55660b2b390ca6270e68afab90862bd2bbb808aa6b5576c975ae773a992a2434c930d" + "4af245a2504ec00809bd0cd8d20ceaaac35f8ec5aaa8c7d3fd6652b126d2bf246d64fec8f0e65c409b196d4a60c9723dd4fbb3328988790e97fc4e08e9528208" ] } } @@ -2624,7 +2594,7 @@ ], "public_keys": [], "external_key": null, - "code": "check if !false && true;\ncheck if false || true;\ncheck if (true || false) && true;\ncheck if !(false && \"x\".intersection(\"x\"));\ncheck if true || \"x\".intersection(\"x\");\ncheck if [1, 2, 3].all($p -> $p > 0);\ncheck if ![1, 2, 3].all($p -> $p == 2);\ncheck if [1, 2, 3].any($p -> $p > 2);\ncheck if ![1, 2, 3].any($p -> $p > 3);\ncheck if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q));\n" + "code": "check if !false && true;\ncheck if false || true;\ncheck if (true || false) && true;\ncheck if !(false && \"x\".intersection(\"x\"));\ncheck if true || \"x\".intersection(\"x\");\ncheck if {1, 2, 3}.all($p -> $p > 0);\ncheck if !{1, 2, 3}.all($p -> $p == 2);\ncheck if {1, 2, 3}.any($p -> $p > 2);\ncheck if !{1, 2, 3}.any($p -> $p > 3);\ncheck if {1, 2, 3}.any($p -> $p > 1 && {3, 4, 5}.any($q -> $p == $q));\n" } ], "validations": { @@ -2637,15 +2607,15 @@ "origin": 0, "checks": [ "check if !(false && \"x\".intersection(\"x\"))", - "check if ![1, 2, 3].all($p -> $p == 2)", - "check if ![1, 2, 3].any($p -> $p > 3)", "check if !false && true", + "check if !{1, 2, 3}.all($p -> $p == 2)", + "check if !{1, 2, 3}.any($p -> $p > 3)", "check if (true || false) && true", - "check if [1, 2, 3].all($p -> $p > 0)", - "check if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q))", - "check if [1, 2, 3].any($p -> $p > 2)", "check if false || true", - "check if true || \"x\".intersection(\"x\")" + "check if true || \"x\".intersection(\"x\")", + "check if {1, 2, 3}.all($p -> $p > 0)", + "check if {1, 2, 3}.any($p -> $p > 1 && {3, 4, 5}.any($q -> $p == $q))", + "check if {1, 2, 3}.any($p -> $p > 2)" ] } ], @@ -2670,15 +2640,15 @@ "origin": 0, "checks": [ "check if !(false && \"x\".intersection(\"x\"))", - "check if ![1, 2, 3].all($p -> $p == 2)", - "check if ![1, 2, 3].any($p -> $p > 3)", "check if !false && true", + "check if !{1, 2, 3}.all($p -> $p == 2)", + "check if !{1, 2, 3}.any($p -> $p > 3)", "check if (true || false) && true", - "check if [1, 2, 3].all($p -> $p > 0)", - "check if [1, 2, 3].any($p -> $p > 1 && [3, 4, 5].any($q -> $p == $q))", - "check if [1, 2, 3].any($p -> $p > 2)", "check if false || true", - "check if true || \"x\".intersection(\"x\")" + "check if true || \"x\".intersection(\"x\")", + "check if {1, 2, 3}.all($p -> $p > 0)", + "check if {1, 2, 3}.any($p -> $p > 1 && {3, 4, 5}.any($q -> $p == $q))", + "check if {1, 2, 3}.any($p -> $p > 2)" ] } ], @@ -2712,11 +2682,14 @@ "bool", "set", "null", + "array", + "map", + "a", "t" ], "public_keys": [], "external_key": null, - "code": "integer(1);\nstring(\"test\");\ndate(2023-12-28T00:00:00Z);\nbytes(hex:aa);\nbool(true);\nset([false, true]);\nnull(null);\ncheck if 1.type() == \"integer\";\ncheck if integer($t), $t.type() == \"integer\";\ncheck if \"test\".type() == \"string\";\ncheck if string($t), $t.type() == \"string\";\ncheck if (2023-12-28T00:00:00Z).type() == \"date\";\ncheck if date($t), $t.type() == \"date\";\ncheck if hex:aa.type() == \"bytes\";\ncheck if bytes($t), $t.type() == \"bytes\";\ncheck if true.type() == \"bool\";\ncheck if bool($t), $t.type() == \"bool\";\ncheck if [false, true].type() == \"set\";\ncheck if set($t), $t.type() == \"set\";\ncheck if null.type() == \"null\";\ncheck if null($t), $t.type() == \"null\";\n" + "code": "integer(1);\nstring(\"test\");\ndate(2023-12-28T00:00:00Z);\nbytes(hex:aa);\nbool(true);\nset({false, true});\nnull(null);\narray([1, 2, 3]);\nmap({\"a\": true});\ncheck if 1.type() == \"integer\";\ncheck if integer($t), $t.type() == \"integer\";\ncheck if \"test\".type() == \"string\";\ncheck if string($t), $t.type() == \"string\";\ncheck if (2023-12-28T00:00:00Z).type() == \"date\";\ncheck if date($t), $t.type() == \"date\";\ncheck if hex:aa.type() == \"bytes\";\ncheck if bytes($t), $t.type() == \"bytes\";\ncheck if true.type() == \"bool\";\ncheck if bool($t), $t.type() == \"bool\";\ncheck if {false, true}.type() == \"set\";\ncheck if set($t), $t.type() == \"set\";\ncheck if null.type() == \"null\";\ncheck if null($t), $t.type() == \"null\";\ncheck if array($t), $t.type() == \"array\";\ncheck if map($t), $t.type() == \"map\";\n" } ], "validations": { @@ -2728,12 +2701,14 @@ 0 ], "facts": [ + "array([1, 2, 3])", "bool(true)", "bytes(hex:aa)", "date(2023-12-28T00:00:00Z)", "integer(1)", + "map({\"a\": true})", "null(null)", - "set([false, true])", + "set({false, true})", "string(\"test\")" ] } @@ -2746,17 +2721,93 @@ "check if \"test\".type() == \"string\"", "check if (2023-12-28T00:00:00Z).type() == \"date\"", "check if 1.type() == \"integer\"", - "check if [false, true].type() == \"set\"", + "check if array($t), $t.type() == \"array\"", "check if bool($t), $t.type() == \"bool\"", "check if bytes($t), $t.type() == \"bytes\"", "check if date($t), $t.type() == \"date\"", "check if hex:aa.type() == \"bytes\"", "check if integer($t), $t.type() == \"integer\"", + "check if map($t), $t.type() == \"map\"", "check if null($t), $t.type() == \"null\"", "check if null.type() == \"null\"", "check if set($t), $t.type() == \"set\"", "check if string($t), $t.type() == \"string\"", - "check if true.type() == \"bool\"" + "check if true.type() == \"bool\"", + "check if {false, true}.type() == \"set\"" + ] + } + ], + "policies": [ + "allow if true" + ] + }, + "result": { + "Ok": 0 + }, + "authorizer_code": "allow if true;\n", + "revocation_ids": [ + "c8f7ff152b40a3e8f3ab19a435ccd16c41288762864022895b99d2abb6330c794b3f1378a4651b31d249f4c35b69246d88124d40e05e634a0eb9ca9e54b1ca0a" + ] + } + } + }, + { + "title": "test array and map operations (v5 blocks)", + "filename": "test034_array_map.bc", + "token": [ + { + "symbols": [ + "a", + "b", + "c", + "p", + "d", + "A", + "kv", + "id", + "roles" + ], + "public_keys": [], + "external_key": null, + "code": "check if [1, 2, 1].length() == 3;\ncheck if [\"a\", \"b\"] != true;\ncheck if [\"a\", \"b\"] != [1, 2, 3];\ncheck if [\"a\", \"b\"] == [\"a\", \"b\"];\ncheck if [\"a\", \"b\"] === [\"a\", \"b\"];\ncheck if [\"a\", \"b\"] !== [\"a\", \"c\"];\ncheck if [\"a\", \"b\", \"c\"].contains(\"c\");\ncheck if [1, 2, 3].starts_with([1, 2]);\ncheck if [4, 5, 6].ends_with([6]);\ncheck if [1, 2, \"a\"].get(2) == \"a\";\ncheck if [1, 2].get(3) == null;\ncheck if [1, 2, 3].all($p -> $p > 0);\ncheck if [1, 2, 3].any($p -> $p > 2);\ncheck if {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}.length() == 4;\ncheck if {1: \"a\", 2: \"b\"} != true;\ncheck if {1: \"a\", 2: \"b\"} != {\"a\": 1, \"b\": 2};\ncheck if {1: \"a\", 2: \"b\"} == {1: \"a\", 2: \"b\"};\ncheck if {1: \"a\", 2: \"b\"} !== {\"a\": 1, \"b\": 2};\ncheck if {1: \"a\", 2: \"b\"} === {1: \"a\", 2: \"b\"};\ncheck if {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}.contains(\"d\");\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(\"a\") == 1;\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(1) == \"A\";\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(\"c\") == null;\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(2) == null;\ncheck if {\"a\": 1, \"b\": 2}.all($kv -> $kv.get(0) != \"c\" && $kv.get(1) < 3);\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.any($kv -> $kv.get(0) == 1 && $kv.get(1) == \"A\");\ncheck if {\"user\": {\"id\": 1, \"roles\": [\"admin\"]}}.get(\"user\").get(\"roles\").contains(\"admin\");\n" + } + ], + "validations": { + "": { + "world": { + "facts": [], + "rules": [], + "checks": [ + { + "origin": 0, + "checks": [ + "check if [\"a\", \"b\", \"c\"].contains(\"c\")", + "check if [\"a\", \"b\"] != [1, 2, 3]", + "check if [\"a\", \"b\"] != true", + "check if [\"a\", \"b\"] !== [\"a\", \"c\"]", + "check if [\"a\", \"b\"] == [\"a\", \"b\"]", + "check if [\"a\", \"b\"] === [\"a\", \"b\"]", + "check if [1, 2, \"a\"].get(2) == \"a\"", + "check if [1, 2, 1].length() == 3", + "check if [1, 2, 3].all($p -> $p > 0)", + "check if [1, 2, 3].any($p -> $p > 2)", + "check if [1, 2, 3].starts_with([1, 2])", + "check if [1, 2].get(3) == null", + "check if [4, 5, 6].ends_with([6])", + "check if {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}.contains(\"d\")", + "check if {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}.length() == 4", + "check if {\"a\": 1, \"b\": 2}.all($kv -> $kv.get(0) != \"c\" && $kv.get(1) < 3)", + "check if {\"user\": {\"id\": 1, \"roles\": [\"admin\"]}}.get(\"user\").get(\"roles\").contains(\"admin\")", + "check if {1: \"A\", \"a\": 1, \"b\": 2}.any($kv -> $kv.get(0) == 1 && $kv.get(1) == \"A\")", + "check if {1: \"A\", \"a\": 1, \"b\": 2}.get(\"a\") == 1", + "check if {1: \"A\", \"a\": 1, \"b\": 2}.get(\"c\") == null", + "check if {1: \"A\", \"a\": 1, \"b\": 2}.get(1) == \"A\"", + "check if {1: \"A\", \"a\": 1, \"b\": 2}.get(2) == null", + "check if {1: \"a\", 2: \"b\"} != true", + "check if {1: \"a\", 2: \"b\"} != {\"a\": 1, \"b\": 2}", + "check if {1: \"a\", 2: \"b\"} !== {\"a\": 1, \"b\": 2}", + "check if {1: \"a\", 2: \"b\"} == {1: \"a\", 2: \"b\"}", + "check if {1: \"a\", 2: \"b\"} === {1: \"a\", 2: \"b\"}" ] } ], @@ -2769,7 +2820,7 @@ }, "authorizer_code": "allow if true;\n", "revocation_ids": [ - "be401996253dce45ac3d8b2f4b289af1f2cc2a4447a8265a1a2ca879c43377978ffc5ac6633053cd7c30e7c33cf258a37767226834bc80b005c48eb0229c4502" + "8041144f92616477f1cd00b81e8be79581202a3853b08b3d477797b0d91f30c02fd7c01ca91a00f8a222d6be4794cc287baa361a1a00d5941518c1917967ec03" ] } } diff --git a/samples/current/test031_heterogeneous_equal.bc b/samples/current/test031_heterogeneous_equal.bc index feb38732a79185bad7ddf3f375abfa33d4795d5e..8ca4ff20e3684c29cf2d6117eba3d745751c1f10 100644 GIT binary patch literal 748 zcmWeS%F1<%g^MjQDcQx)h>IOUS4glKNpVSVF>y#s330J-F&QwzNGT=`Q8YOQupE#C z%88-M2_WmkDhE=5X(mLU05cJ0%5X`6-6_Jw%Ec_vzyYHmrlQI=qR5IFNpnep^$LSE z0cD|H1$#t^O93n?#l^wJrqFnE;~X|57Q}d*YPwhaV}&|ij!On?ju^6TNRWc5*H5_ zmlX#W6EJw01enlx5WBFeWx=9W%n0FoWOG@NLs3YDgF#3^AoO^^#)Scq=IcexkE!i4 zN}d^Gyv#jf)%uO<(ab`RTBIDjKDjOm@H@c4xtHh0C7xHS4#)Q$UA5x)<-ch`8`UoD zSIJHJcjCjd7>C)Cxn2n;i)^p_-fYy_QOP&`j~~a&pe7C_pj&3XsOFm(5iIv^EAxL* YwLER*LyH2cg?r{o%WG|kxUZWC07XD~kpKVy delta 205 zcmaFE`j@d@=o%we4i`&WVsZ%=YguAWX(|^hh+`zdW~9lb&c(zbEyTmoz#+sWz$nDb z(a0es%*Db5 zWe7P=`1-oNqAPBPOy}Z1%>^eHzcN!dJQ|j;Y4e0rNd?cke(mH)+N-_0p=;UJ@SN#U S&x==1TIB3AnRoIDCKUi^s5!3y diff --git a/samples/current/test033_typeof.bc b/samples/current/test033_typeof.bc index 5b0b4c6250b82f0b05dda663d7144c21d2284d82..649e2544ed9f588cce8f9cefd18d6fb7b0f59fd8 100644 GIT binary patch delta 371 zcmeyw*2Tdl^q8IN2irt8Gd|YDqN2n~F6P|C0xrhHiPj0aN}^oC9331&d|o_UOahER z%ml>DN+MiB9Gx6Oyg}StoLtNTT^vG828LYm zWkiv^&ghOTtHI=t%xz?HuSXcn!NnrP#K8=*MWP+Zkz(QyHPYeI;$q^E7UBT87HB)% z8OW+TFjWIRflGBKRJD)_2ZPY$*G$R|C%*p|)pl6?;`3_BC8lRC<~VA!C$%{!bwYaj|kSb977=Ve~-erZEO0a}T1*3NyJQ z%cd~-b0du6m^^_=WU>Ym@8tVTswm|TF>5&NbC8^-YJ1LgjcvESx5liGpU!Bx zxUW!)lG0gGdBnJUdjFrOW61`=XKM_eAGY}vvA8^4DZ^w>!v@wPeH)bKxH3(C#;gJW D$E-a0 diff --git a/samples/current/test034_array_map.bc b/samples/current/test034_array_map.bc new file mode 100644 index 0000000000000000000000000000000000000000..2fb439447caa4f08f750f19699f6349ff85e4de0 GIT binary patch literal 1951 zcmb_dPe>GD6yKTI-M${Wt)I>|&Wf(1ZL)19Uy%}28s^3zDJzmu7t@F+Dh#rc!2b!> z!7#!@hdcy%QK29@gmtJ(9V)FV1>=O8yfcuSmdAs?Xs~=p#pDR5hee9D^1L)CfDEDp{G9W{i=f*_uo5R6A3v zVn-;E^Nu7tRynI7!IYbflri*wkI!nEHh4P8X=QNHPS4>@xK3s2OZQ_gjgLF6Y+Oww z-efE_kzqNcxRz+dLcG$cps7t^GS@N!z01Yx9y9M+E3QcoAqy^FGSDG>AjB=U32q`J5L$>>!{s0*i_PX zue-PZ*L%L~yD%=m3aFYT&&J=;D|eCJ`fBKEZF%kJ(!Fm=@i literal 0 HcmV?d00001 From d815877795f6026631ff30c770b751fd4e0f8fc5 Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Mon, 4 Nov 2024 14:09:51 +0100 Subject: [PATCH 09/11] fix: reword supported operations on `null` --- SPECIFICATIONS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPECIFICATIONS.md b/SPECIFICATIONS.md index 2197233..91db0dc 100644 --- a/SPECIFICATIONS.md +++ b/SPECIFICATIONS.md @@ -160,7 +160,7 @@ strict not equal, set inclusion, lenient equal, lenient not equal, typeof. A _boolean_ is `true` or `false`. It supports the following operations: `===` (strict equal), `!==` (strict not equal), eager or, eager and, set inclusion, `==` (lenient equal), `!=` (lenient not equal), typeof, short-circuiting or, short-circuiting and. -A _null_ is a default type indicating the absence of value. It supports `===` (strict equal), `!==` (strict not equal), `==` (lenient equal) and `!=` (lenient not equal). `null` is always equal to itself, typeof. +A _null_ is a default type indicating the absence of value. It supports `===` (strict equal), `!==` (strict not equal), `==` (lenient equal) and `!=` (lenient not equal), typeof. `null` is always equal to itself. A _set_ is a deduplicated list of terms of the same type. It cannot contain variables or other sets. It supports strict equal, strict not equal, intersection, union, From 05a49da9e6aead9ae91250c58e0c60b9f04c2fd1 Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Fri, 8 Nov 2024 15:30:21 +0100 Subject: [PATCH 10/11] Update schema.proto with maps and arrays Also explictly document the `Get` binary operation --- SPECIFICATIONS.md | 3 +++ schema.proto | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/SPECIFICATIONS.md b/SPECIFICATIONS.md index 91db0dc..bce683f 100644 --- a/SPECIFICATIONS.md +++ b/SPECIFICATIONS.md @@ -510,6 +510,9 @@ Here are the currently defined binary operations: - _all_, defined on sets, takes a closure term -> boolean, returns a boolean (v6 only) - _short circuiting and_, defined on booleans, takes a closure () -> boolean, returns a boolean (v6 only) - _short circuiting or_, defined on booleans, takes a closure () -> boolean, returns a boolean (v6 only) +- _get_, defined on arrays and maps (v6 only) + on arrays, takes an integer and returns the corresponding element (or `null`, if out of bounds) + on maps, takes either an integer or a string and returns the corresponding element (or `null`, if out of bounds) Integer operations must have overflow checks. If it overflows, the expression fails. diff --git a/schema.proto b/schema.proto index e2dfda2..8e716f6 100644 --- a/schema.proto +++ b/schema.proto @@ -99,6 +99,8 @@ message TermV2 { bool bool = 6; TermSet set = 7; Empty null = 8; + Array array = 9; + Map map = 10; } } @@ -106,6 +108,26 @@ message TermSet { repeated TermV2 set = 1; } +message Array { + repeated TermV2 array = 1; +} + +message Map { + repeated MapEntry entries = 1; +} + +message MapEntry { + required MapKey key = 1; + required TermV2 value = 2; +} + +message MapKey { + oneof Content { + int64 integer = 1; + uint64 string = 2; + } +} + message ExpressionV2 { repeated Op ops = 1; } @@ -159,6 +181,7 @@ message OpBinary { LazyOr = 24; All = 25; Any = 26; + Get = 27; } required Kind kind = 1; From 90fbea9b811cbc22bffe3a013b9a4ef8c1d0f5e5 Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Fri, 8 Nov 2024 15:44:21 +0100 Subject: [PATCH 11/11] specifcy FFI operations --- SPECIFICATIONS.md | 6 +++++- schema.proto | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/SPECIFICATIONS.md b/SPECIFICATIONS.md index bce683f..821ac76 100644 --- a/SPECIFICATIONS.md +++ b/SPECIFICATIONS.md @@ -214,7 +214,7 @@ The logic language is described by the following EBNF grammar: ::= | ( ? ) ::= "!" ? ::= "." "(" ? ( ( ? "," ? )* )? ? ")" - ::= ([a-z] | [A-Z] ) ([a-z] | [A-Z] | [0-9] | "_" )* + ::= (extern::)?([a-z] | [A-Z] ) ([a-z] | [A-Z] | [0-9] | "_" )* ::= | ("(" ? ? ")") ::= "<" | ">" | "<=" | ">=" | "===" | "!==" | "&&" | "||" | "+" | "-" | "*" | "/" | "&" | "|" | "^" | "==" | "!==" @@ -479,6 +479,7 @@ Here are the currently defined unary operations: - `bool` - `set` - `null` +- *external* call: implementation-defined, allows the datalog engine to call out to a function provided by the host language Here are the currently defined binary operations: @@ -513,6 +514,7 @@ Here are the currently defined binary operations: - _get_, defined on arrays and maps (v6 only) on arrays, takes an integer and returns the corresponding element (or `null`, if out of bounds) on maps, takes either an integer or a string and returns the corresponding element (or `null`, if out of bounds) +- *external* call: implementation-defined, allows the datalog engine to call out to a function provided by the host language Integer operations must have overflow checks. If it overflows, the expression fails. @@ -521,6 +523,8 @@ Strict equality fails with a type error when trying to compare different types. Lenient equality returns false when trying to compare different types. +External calls are implementation defined. External calls carry a function name, which can be used to call a user-defined function provided to the biscuit library. + #### Example The expression `$a + 2 < 4` will translate to the following opcodes: $a, 2, +, 4, < diff --git a/schema.proto b/schema.proto index 8e716f6..5524582 100644 --- a/schema.proto +++ b/schema.proto @@ -147,9 +147,11 @@ message OpUnary { Parens = 1; Length = 2; TypeOf = 3; + Ffi = 4; } required Kind kind = 1; + optional string ffiName = 2; } message OpBinary { @@ -182,9 +184,11 @@ message OpBinary { All = 25; Any = 26; Get = 27; + Ffi = 28; } required Kind kind = 1; + optional string ffiName = 2; } message OpClosure {