@@ -70,7 +70,7 @@ def or : Residual → Residual → CedarType → Residual
70
70
| .val false _, r, _ => r
71
71
| .error _, _, ty => .error ty
72
72
| l, .val false _, _ => l
73
- | l, r, ty => .and l r ty
73
+ | l, r, ty => .or l r ty
74
74
75
75
def apply₁ (op₁ : UnaryOp) (r : Residual) (ty : CedarType) : Residual :=
76
76
match r with
@@ -95,46 +95,52 @@ def getTag (uid : EntityUID) (tag : String) (es : PartialEntities) (ty : CedarTy
95
95
| .none => .binaryApp .getTag uid tag ty
96
96
97
97
def apply₂ (op₂ : BinaryOp) (r₁ r₂ : Residual) (es : PartialEntities) (ty : CedarType) : Residual :=
98
- match op₂, r₁, r₂ with
99
- | .eq, .val v₁ _, .val v₂ _ =>
100
- .val (v₁ == v₂) ty
101
- | .less, .val (.prim (.int i)) _, .val (.prim (.int j)) _ =>
102
- .val (i < j : Bool) ty
103
- | .less, .val (.ext (.datetime d₁)) _, .val (.ext (.datetime d₂)) _ =>
104
- .val (d₁ < d₂: Bool) ty
105
- | .less, .val (.ext (.duration d₁)) _, .val (.ext (.duration d₂)) _ =>
106
- .val (d₁ < d₂: Bool) ty
107
- | .lessEq, .val (.prim (.int i)) _, .val (.prim (.int j)) _ =>
108
- .val (i ≤ j : Bool) ty
109
- | .lessEq, .val (.ext (.datetime d₁)) _, .val (.ext (.datetime d₂)) _ =>
110
- .val (d₁ ≤ d₂: Bool) ty
111
- | .lessEq, .val (.ext (.duration d₁)) _, .val (.ext (.duration d₂)) _ =>
112
- .val (d₁ ≤ d₂: Bool) ty
113
- | .add, .val (.prim (.int i)) _, .val (.prim (.int j)) _ =>
114
- someOrError (i.add? j) ty
115
- | .sub, .val (.prim (.int i)) _, .val (.prim (.int j)) _ =>
116
- someOrError (i.sub? j) ty
117
- | .mul, .val (.prim (.int i)) _, .val (.prim (.int j)) _ =>
118
- someOrError (i.mul? j) ty
119
- | .contains, .val (.set vs₁) _, .val v₂ _ =>
120
- .val (vs₁.contains v₂) ty
121
- | .containsAll, .val (.set vs₁) _, .val (.set vs₂) _ =>
122
- .val (vs₂.subset vs₁) ty
123
- | .containsAny, .val (.set vs₁) _, .val (.set vs₂) _ =>
124
- .val (vs₁.intersects vs₂) ty
125
- | .mem, .val (.prim (.entityUID uid₁)) _, .val (.prim (.entityUID uid₂)) _ =>
126
- someOrSelf (in ₑ uid₁ uid₂ es) ty self
127
- | .mem, .val (.prim (.entityUID uid₁)) _, .val (.set vs) _ =>
128
- someOrSelf (in ₛ uid₁ vs es) ty self
129
- | .hasTag, .val (.prim (.entityUID uid₁)) _, .val (.prim (.string tag)) _ =>
130
- someOrSelf (hasTag uid₁ tag es) ty self
131
- | .getTag, .val (.prim (.entityUID uid₁)) _, .val (.prim (.string tag)) _ =>
132
- getTag uid₁ tag es ty
133
- | _, .error _, _ | _, _, .error _ => .error ty
134
- | _, _, _ => self
135
- where
98
+ match r₁.asValue, r₂.asValue with
99
+ | .some v₁, .some v₂ =>
100
+ match op₂, v₁, v₂ with
101
+ | .eq, _, _ =>
102
+ .val (v₁ == v₂) ty
103
+ | .less, .prim (.int i), .prim (.int j) =>
104
+ .val (i < j : Bool) ty
105
+ | .less, .ext (.datetime d₁), .ext (.datetime d₂) =>
106
+ .val (d₁ < d₂: Bool) ty
107
+ | .less, .ext (.duration d₁), .ext (.duration d₂) =>
108
+ .val (d₁ < d₂: Bool) ty
109
+ | .lessEq, .prim (.int i), .prim (.int j) =>
110
+ .val (i ≤ j : Bool) ty
111
+ | .lessEq, .ext (.datetime d₁), .ext (.datetime d₂) =>
112
+ .val (d₁ ≤ d₂: Bool) ty
113
+ | .lessEq, .ext (.duration d₁), .ext (.duration d₂) =>
114
+ .val (d₁ ≤ d₂: Bool) ty
115
+ | .add, .prim (.int i), .prim (.int j) =>
116
+ someOrError (i.add? j) ty
117
+ | .sub, .prim (.int i), .prim (.int j) =>
118
+ someOrError (i.sub? j) ty
119
+ | .mul, .prim (.int i), .prim (.int j) =>
120
+ someOrError (i.mul? j) ty
121
+ | .contains, .set vs₁, _ =>
122
+ .val (vs₁.contains v₂) ty
123
+ | .containsAll, .set vs₁, .set vs₂ =>
124
+ .val (vs₂.subset vs₁) ty
125
+ | .containsAny, .set vs₁, .set vs₂ =>
126
+ .val (vs₁.intersects vs₂) ty
127
+ | .mem, .prim (.entityUID uid₁), .prim (.entityUID uid₂) =>
128
+ someOrSelf (in ₑ uid₁ uid₂ es) ty self
129
+ | .mem, .prim (.entityUID uid₁), .set vs =>
130
+ someOrSelf (in ₛ uid₁ vs es) ty self
131
+ | .hasTag, .prim (.entityUID uid₁), .prim (.string tag) =>
132
+ someOrSelf (hasTag uid₁ tag es) ty self
133
+ | .getTag, .prim (.entityUID uid₁), .prim (.string tag) =>
134
+ getTag uid₁ tag es ty
135
+ | _, _, _ => .error ty
136
+ | _, _ =>
137
+ match r₁, r₂ with
138
+ | .error _, _ | _, .error _ => .error ty
139
+ | _, _ => self
140
+ where
136
141
self := .binaryApp op₂ r₁ r₂ ty
137
142
143
+
138
144
def attrsOf (r : Residual) (lookup : EntityUID → Option (Map Attr Value)) : Option (Map Attr Value) :=
139
145
match r with
140
146
| .val (.record m) _ => .some m
@@ -210,6 +216,18 @@ decreasing_by
210
216
try simp at h
211
217
omega
212
218
219
+ /-- Partially evaluating a policy.
220
+ Note that this function actually evaluates a type-lifted version of `TypedExpr`
221
+ produced by the type checker, as opposed to evaluating the expression directly.
222
+ This design is to simplify proofs otherwise we need to prove theorems that
223
+ state type-lifting (i.e, `TypedExpr.liftBoolTypes`) do not change the results
224
+ of evaluating residuals. The soundness theorem still holds. That is,
225
+ reauthorizing the residuals produces the same outcome as authorizing the input
226
+ expressions with consistent requests/entities. It is just that the types in the
227
+ residuals are all lifted. We essentially trade efficiency for ease of proofs,
228
+ which I (Shaobo) think is fine because the Lean model is a reference model not
229
+ used in production.
230
+ -/
213
231
def evaluatePolicy (schema : Schema)
214
232
(p : Policy)
215
233
(req : PartialRequest)
@@ -222,7 +240,7 @@ def evaluatePolicy (schema : Schema)
222
240
do
223
241
let expr := substituteAction env.reqty.action p.toExpr
224
242
let (te, _) ← (typeOf expr ∅ env).mapError Error.invalidPolicy
225
- .ok (evaluate te req es)
243
+ .ok (evaluate te.liftBoolTypes req es)
226
244
else .error .invalidRequestOrEntities
227
245
| .none => .error .invalidEnvironment
228
246
0 commit comments