1use miette::Diagnostic;
21use smol_str::SmolStr;
22use thiserror::Error;
23
24use crate::{
25 ast::{Eid, EntityType, EntityUID, PartialValueToValueError},
26 entities::{conformance::err::EntitySchemaConformanceError, err::Duplicate},
27 evaluator::{evaluation_errors::UnlinkedSlotError, EvaluationError},
28 transitive_closure::TcError,
29 validator::{RequestValidationError, ValidationError},
30};
31
32#[derive(Debug, Error, Diagnostic)]
34#[error("Unexpected action: `{}`", .action)]
35pub struct UnexpectedActionError {
36 pub(super) action: EntityUID,
37}
38
39#[derive(Debug, Error, Diagnostic)]
41pub enum JsonDeserializationError {
42 #[error(transparent)]
44 #[diagnostic(transparent)]
45 Concrete(#[from] crate::entities::json::err::JsonDeserializationError),
46 #[error(transparent)]
49 #[diagnostic(transparent)]
50 UnexpectedAction(#[from] UnexpectedActionError),
51 #[error(transparent)]
53 #[diagnostic(transparent)]
54 RestrictedExprEvaluation(#[from] EvaluationError),
55}
56
57#[derive(Debug, Error, Diagnostic)]
59pub enum EntityValidationError {
60 #[error(transparent)]
62 #[diagnostic(transparent)]
63 Concrete(#[from] EntitySchemaConformanceError),
64 #[error(transparent)]
66 #[diagnostic(transparent)]
67 UnknownActionComponent(#[from] UnknownActionComponentError),
68 #[error(transparent)]
70 #[diagnostic(transparent)]
71 MismatchedActionAncestors(#[from] MismatchedActionAncestorsError),
72}
73
74#[derive(Debug, Error, Diagnostic)]
76#[error("action `{}` has unknown ancestors/attrs/tags", .action)]
77pub struct UnknownActionComponentError {
78 pub(super) action: EntityUID,
79}
80
81#[derive(Debug, Error, Diagnostic)]
83#[error("action `{}`'s ancestors do not match the schema", .action)]
84pub struct MismatchedActionAncestorsError {
85 pub(super) action: EntityUID,
86}
87
88#[derive(Debug, Error, Diagnostic)]
90#[error("ancestor `{ancestor}` of `{uid}` has unknown ancestors")]
91#[diagnostic(help(
92 "an entity with known ancestors cannot have an ancestor whose own ancestors are unknown"
93))]
94pub struct AncestorValidationError {
95 pub(crate) uid: EntityUID,
96 pub(crate) ancestor: EntityUID,
97}
98
99#[derive(Debug, Error, Diagnostic)]
101pub enum TpeError {
102 #[error(transparent)]
105 #[diagnostic(transparent)]
106 NoMatchingReqEnv(#[from] NoMatchingReqEnvError),
107 #[error(transparent)]
109 #[diagnostic(transparent)]
110 Validation(#[from] PolicyValidationError),
111 #[error(transparent)]
113 #[diagnostic(transparent)]
114 ExprToResidualError(#[from] ExprToResidualError),
115}
116
117#[derive(Debug, Error, Diagnostic)]
120#[error("policy failed to validate against the schema")]
121pub struct PolicyValidationError {
122 #[related]
123 pub(super) errors: Vec<ValidationError>,
124}
125
126impl PolicyValidationError {
127 pub(crate) fn new(errors: Vec<ValidationError>) -> Self {
128 Self { errors }
129 }
130
131 pub fn errors(&self) -> impl Iterator<Item = &ValidationError> {
133 self.errors.iter()
134 }
135}
136
137#[derive(Debug, Error, Diagnostic)]
140#[non_exhaustive]
141pub enum ExprToResidualError {
142 #[error(transparent)]
144 #[diagnostic(transparent)]
145 MissingTypeAnnotation(#[from] MissingTypeAnnotationError),
146 #[error(transparent)]
148 #[diagnostic(transparent)]
149 UnlinkedSlotError(#[from] UnlinkedSlotError),
150 #[error(transparent)]
152 #[diagnostic(transparent)]
153 UnknownNotSupported(#[from] UnknownNotSupportedError),
154 #[error(transparent)]
156 #[diagnostic(transparent)]
157 ErrorNotSupported(#[from] ErrorNotSupportedError),
158}
159
160#[derive(Debug, Error, Diagnostic)]
162#[error("expression is missing a type annotation")]
163#[diagnostic(help(
164 "expressions must be typechecked by the policy validator before partial evaluation"
165))]
166pub struct MissingTypeAnnotationError;
167
168#[derive(Debug, Error, Diagnostic)]
170#[error("expression contains an unknown, which is not supported in residuals")]
171pub struct UnknownNotSupportedError;
172
173#[derive(Debug, Error, Diagnostic)]
175#[error("expression contains an error node, which is not supported in residuals")]
176pub struct ErrorNotSupportedError;
177
178#[derive(Debug, Error, Diagnostic)]
180#[error("expected a concrete request, but found a partial request")]
181pub struct PartialRequestError {}
182
183#[derive(Debug, Error, Diagnostic)]
186#[error("no request environment in the schema matches the given request")]
187pub struct NoMatchingReqEnvError;
188
189#[derive(Debug, Error, Diagnostic)]
191pub enum RequestBuilderError {
192 #[error(transparent)]
194 #[diagnostic(transparent)]
195 Validation(#[from] RequestValidationError),
196 #[error(transparent)]
198 #[diagnostic(transparent)]
199 ExistingPrincipal(#[from] ExistingPrincipalError),
200 #[error(transparent)]
202 #[diagnostic(transparent)]
203 ExistingResource(#[from] ExistingResourceError),
204 #[error("a context has already been set on this request")]
206 ExistingContext,
207 #[error(transparent)]
210 #[diagnostic(transparent)]
211 IncorrectPrincipalEntityType(#[from] IncorrectPrincipalEntityTypeError),
212 #[error(transparent)]
215 #[diagnostic(transparent)]
216 IncorrectResourceEntityType(#[from] IncorrectResourceEntityTypeError),
217 #[error("context candidate contains unknowns")]
219 UnknownContextCandidate,
220}
221
222#[derive(Debug, Error, Diagnostic)]
224#[error("a principal (`{principal}`) has already been set on this request")]
225pub struct ExistingPrincipalError {
226 pub(super) principal: EntityUID,
227}
228
229#[derive(Debug, Error, Diagnostic)]
231#[error("a resource (`{resource}`) has already been set on this request")]
232pub struct ExistingResourceError {
233 pub(super) resource: EntityUID,
234}
235
236#[derive(Debug, Error, Diagnostic)]
239#[error("principal type `{ty}` does not match the partial request's principal type `{expected}`")]
240pub struct IncorrectPrincipalEntityTypeError {
241 pub(super) ty: EntityType,
242 pub(super) expected: EntityType,
243}
244
245#[derive(Debug, Error, Diagnostic)]
248#[error("resource type `{ty}` does not match the partial request's resource type `{expected}`")]
249pub struct IncorrectResourceEntityTypeError {
250 pub(super) ty: EntityType,
251 pub(super) expected: EntityType,
252}
253
254#[derive(Debug, Error, Diagnostic)]
256pub enum EntitiesError {
257 #[error(transparent)]
259 #[diagnostic(transparent)]
260 Deserialization(#[from] JsonDeserializationError),
261 #[error(transparent)]
263 #[diagnostic(transparent)]
264 Validation(#[from] EntityValidationError),
265 #[error(transparent)]
267 #[diagnostic(transparent)]
268 AncestorValidation(#[from] AncestorValidationError),
269 #[error(transparent)]
271 #[diagnostic(transparent)]
272 TCComputation(#[from] TcError<EntityUID>),
273 #[error(transparent)]
276 #[diagnostic(transparent)]
277 Duplicate(#[from] Duplicate),
278 #[error(transparent)]
280 #[diagnostic(transparent)]
281 PartialValueToValue(#[from] PartialValueToValueError),
282}
283
284#[derive(Debug, Error, Diagnostic)]
287pub enum EntitiesConsistencyError {
288 #[error(transparent)]
290 #[diagnostic(transparent)]
291 MissingEntity(#[from] MissingEntityError),
292 #[error(transparent)]
294 #[diagnostic(transparent)]
295 UnknownEntity(#[from] UnknownEntityError),
296 #[error(transparent)]
299 #[diagnostic(transparent)]
300 InconsistentEntity(#[from] EntityConsistencyError),
301}
302
303#[derive(Debug, Error, Diagnostic)]
306pub enum EntityConsistencyError {
307 #[error(transparent)]
309 #[diagnostic(transparent)]
310 UnknownAttribute(#[from] UnknownAttributeError),
311 #[error(transparent)]
313 #[diagnostic(transparent)]
314 MismatchedAttribute(#[from] MismatchedAttributeError),
315 #[error(transparent)]
317 #[diagnostic(transparent)]
318 MismatchedAncestor(#[from] MismatchedAncestorError),
319 #[error(transparent)]
321 #[diagnostic(transparent)]
322 UnknownTag(#[from] UnknownTagError),
323 #[error(transparent)]
325 #[diagnostic(transparent)]
326 MismatchedTag(#[from] MismatchedTagError),
327}
328
329#[derive(Debug, Error, Diagnostic)]
331#[error("concrete entity `{uid}` has attribute `{attr}` not present in the partial entity")]
332pub struct UnknownAttributeError {
333 pub(super) uid: EntityUID,
334 pub(super) attr: SmolStr,
335}
336
337#[derive(Debug, Error, Diagnostic)]
339#[error("concrete entity `{uid}` has attribute values that do not match the partial entity")]
340pub struct MismatchedAttributeError {
341 pub(super) uid: EntityUID,
342}
343
344#[derive(Debug, Error, Diagnostic)]
346#[error("concrete entity `{uid}` has tag `{tag}` not present in the partial entity")]
347pub struct UnknownTagError {
348 pub(super) uid: EntityUID,
349 pub(super) tag: SmolStr,
350}
351
352#[derive(Debug, Error, Diagnostic)]
354#[error("concrete entity `{uid}` has tag values that do not match the partial entity")]
355pub struct MismatchedTagError {
356 pub(super) uid: EntityUID,
357}
358
359#[derive(Debug, Error, Diagnostic)]
361#[error("concrete entity `{uid}` has ancestors that do not match the partial entity")]
362pub struct MismatchedAncestorError {
363 pub(super) uid: EntityUID,
364}
365
366#[derive(Debug, Error, Diagnostic)]
368#[error("entity `{uid}` is present in the partial entities but missing from the concrete entities")]
369pub struct MissingEntityError {
370 pub(super) uid: EntityUID,
371}
372
373#[derive(Debug, Error, Diagnostic)]
375#[error("concrete entities contain unknown entity `{uid}`")]
376pub struct UnknownEntityError {
377 pub(super) uid: EntityUID,
378}
379
380#[derive(Debug, Error, Diagnostic)]
382#[error("failed to load entities: {}", .missing_entities.iter().map(|uid| uid.to_string()).collect::<Vec<_>>().join(", "))]
383pub struct MissingEntitiesError {
384 pub(super) missing_entities: Vec<EntityUID>,
385}
386
387impl MissingEntitiesError {
388 pub fn new(missing_entities: Vec<EntityUID>) -> Self {
390 Self { missing_entities }
391 }
392}
393
394#[derive(Debug, Error, Diagnostic)]
396pub enum RequestConsistencyError {
397 #[error("the concrete request's principal is unknown")]
399 UnknownPrincipal,
400 #[error("the concrete request's resource is unknown")]
402 UnknownResource,
403 #[error("the concrete request's action is unknown")]
405 UnknownAction,
406 #[error("the concrete request's context is unknown")]
408 UnknownContext,
409 #[error(transparent)]
411 #[diagnostic(transparent)]
412 InconsistentPrincipalType(#[from] InconsistentPrincipalTypeError),
413 #[error(transparent)]
415 #[diagnostic(transparent)]
416 InconsistentPrincipalEid(#[from] InconsistentPrincipalEidError),
417 #[error(transparent)]
419 #[diagnostic(transparent)]
420 InconsistentResourceType(#[from] InconsistentResourceTypeError),
421 #[error(transparent)]
423 #[diagnostic(transparent)]
424 InconsistentResourceEid(#[from] InconsistentResourceEidError),
425 #[error(transparent)]
427 #[diagnostic(transparent)]
428 InconsistentAction(#[from] InconsistentActionError),
429 #[error("the partial and concrete request contexts do not match")]
431 InconsistentContext,
432 #[error("the concrete request's context contains unknowns")]
434 ConcreteContextContainsUnknowns,
435}
436
437#[derive(Debug, Error, Diagnostic)]
439#[error("partial request principal type `{partial}` does not match concrete request principal type `{concrete}`")]
440pub struct InconsistentPrincipalTypeError {
441 pub(super) partial: EntityType,
442 pub(super) concrete: EntityType,
443}
444
445#[derive(Debug, Error, Diagnostic)]
447#[error("partial request principal id `{}` does not match concrete request principal id `{}`", .partial.escaped(), .concrete.escaped())]
448pub struct InconsistentPrincipalEidError {
449 pub(super) partial: Eid,
450 pub(super) concrete: Eid,
451}
452
453#[derive(Debug, Error, Diagnostic)]
455#[error("partial request resource type `{partial}` does not match concrete request resource type `{concrete}`")]
456pub struct InconsistentResourceTypeError {
457 pub(super) partial: EntityType,
458 pub(super) concrete: EntityType,
459}
460
461#[derive(Debug, Error, Diagnostic)]
463#[error("partial request resource id `{}` does not match concrete request resource id `{}`", .partial.escaped(), .concrete.escaped())]
464pub struct InconsistentResourceEidError {
465 pub(super) partial: Eid,
466 pub(super) concrete: Eid,
467}
468
469#[derive(Debug, Error, Diagnostic)]
471#[error("partial request action `{partial}` does not match concrete request action `{concrete}`")]
472pub struct InconsistentActionError {
473 pub(super) partial: EntityUID,
474 pub(super) concrete: EntityUID,
475}
476
477#[derive(Debug, Error, Diagnostic)]
479pub enum ReauthorizationError {
480 #[error(transparent)]
482 #[diagnostic(transparent)]
483 RequestValidation(#[from] RequestValidationError),
484 #[error(transparent)]
486 #[diagnostic(transparent)]
487 EntityValidation(#[from] EntitySchemaConformanceError),
488 #[error(transparent)]
490 #[diagnostic(transparent)]
491 EntitiesConsistency(#[from] EntitiesConsistencyError),
492 #[error(transparent)]
494 #[diagnostic(transparent)]
495 RequestConsistency(#[from] RequestConsistencyError),
496}