cedar_policy/api/
err.rs

1/*
2 * Copyright Cedar Contributors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//! This module defines the publicly exported error types.
18
19use crate::{EntityUid, PolicyId};
20pub use cedar_policy_core::ast::{
21    expression_construction_errors, restricted_expr_errors, ContainsUnknown,
22    ExpressionConstructionError, PartialValueToValueError, RestrictedExpressionError,
23};
24#[cfg(feature = "tpe")]
25use cedar_policy_core::entities::conformance::err::EntitySchemaConformanceError;
26#[cfg(feature = "entity-manifest")]
27use cedar_policy_core::entities::err::EntitiesError;
28pub use cedar_policy_core::evaluator::{evaluation_errors, EvaluationError};
29pub use cedar_policy_core::extensions::{
30    extension_function_lookup_errors, ExtensionFunctionLookupError,
31};
32pub use cedar_policy_core::validator::cedar_schema::{schema_warnings, SchemaWarning};
33#[cfg(feature = "entity-manifest")]
34pub use cedar_policy_core::validator::entity_manifest::slicing::EntitySliceError;
35#[cfg(feature = "entity-manifest")]
36use cedar_policy_core::validator::entity_manifest::{
37    self, PartialExpressionError, PartialRequestError, UnsupportedCedarFeatureError,
38};
39pub use cedar_policy_core::validator::{schema_errors, SchemaError};
40use cedar_policy_core::{ast, authorizer, est};
41use miette::Diagnostic;
42use ref_cast::RefCast;
43use smol_str::SmolStr;
44use thiserror::Error;
45use to_cedar_syntax_errors::NameCollisionsError;
46
47#[cfg(feature = "entity-manifest")]
48use super::ValidationResult;
49
50#[cfg(feature = "tpe")]
51pub use cedar_policy_core::tpe::err as tpe_err;
52
53/// Errors related to [`crate::Entities`]
54pub mod entities_errors {
55    pub use cedar_policy_core::entities::err::{Duplicate, EntitiesError, TransitiveClosureError};
56}
57
58/// Errors related to serializing/deserializing entities or contexts to/from JSON
59pub mod entities_json_errors {
60    pub use cedar_policy_core::entities::json::err::{
61        ActionParentIsNotAction, DuplicateKey, ExpectedExtnValue, ExpectedLiteralEntityRef,
62        ExtnCall0Arguments, JsonDeserializationError, JsonError, JsonSerializationError,
63        MissingImpliedConstructor, MissingRequiredRecordAttr, ParseEscape, ReservedKey, Residual,
64        TypeMismatch, UnexpectedRecordAttr, UnexpectedRestrictedExprKind,
65    };
66}
67
68/// Errors related to schema conformance checking for entities
69pub mod conformance_errors {
70    pub use cedar_policy_core::entities::conformance::err::{
71        ActionDeclarationMismatch, EntitySchemaConformanceError, ExtensionFunctionLookup,
72        InvalidAncestorType, MissingRequiredEntityAttr, TypeMismatch, UndeclaredAction,
73        UnexpectedEntityAttr, UnexpectedEntityTag, UnexpectedEntityTypeError,
74    };
75}
76
77/// Errors that can occur during authorization
78#[derive(Debug, Diagnostic, PartialEq, Eq, Error, Clone)]
79pub enum AuthorizationError {
80    /// An error occurred when evaluating a policy.
81    #[error(transparent)]
82    #[diagnostic(transparent)]
83    PolicyEvaluationError(#[from] authorization_errors::PolicyEvaluationError),
84}
85
86/// Error subtypes for [`AuthorizationError`]
87pub mod authorization_errors {
88    use crate::{EvaluationError, PolicyId};
89    use cedar_policy_core::{ast, authorizer};
90    use miette::Diagnostic;
91    use ref_cast::RefCast;
92    use thiserror::Error;
93
94    /// An error occurred when evaluating a policy
95    #[derive(Debug, Diagnostic, PartialEq, Eq, Error, Clone)]
96    #[error("error while evaluating policy `{id}`: {error}")]
97    pub struct PolicyEvaluationError {
98        /// Id of the policy with an error
99        id: ast::PolicyID,
100        /// Underlying evaluation error
101        #[diagnostic(transparent)]
102        error: EvaluationError,
103    }
104
105    impl PolicyEvaluationError {
106        /// Get the [`PolicyId`] of the erroring policy
107        pub fn policy_id(&self) -> &PolicyId {
108            PolicyId::ref_cast(&self.id)
109        }
110
111        /// Get the underlying [`EvaluationError`]
112        pub fn inner(&self) -> &EvaluationError {
113            &self.error
114        }
115
116        /// Consume this error, producing the underlying [`EvaluationError`]
117        pub fn into_inner(self) -> EvaluationError {
118            self.error
119        }
120    }
121
122    #[doc(hidden)]
123    impl From<authorizer::AuthorizationError> for PolicyEvaluationError {
124        fn from(e: authorizer::AuthorizationError) -> Self {
125            match e {
126                authorizer::AuthorizationError::PolicyEvaluationError { id, error } => {
127                    Self { id, error }
128                }
129            }
130        }
131    }
132}
133
134#[doc(hidden)]
135impl From<authorizer::AuthorizationError> for AuthorizationError {
136    fn from(value: authorizer::AuthorizationError) -> Self {
137        Self::PolicyEvaluationError(value.into())
138    }
139}
140
141/// Errors that occur during concretizing a partial request
142#[derive(Debug, Diagnostic, Error)]
143#[error(transparent)]
144#[diagnostic(transparent)]
145pub struct ConcretizationError(pub(crate) cedar_policy_core::authorizer::ConcretizationError);
146
147/// Errors that can be encountered when re-evaluating a partial response
148#[derive(Debug, Diagnostic, Error)]
149pub enum ReauthorizationError {
150    /// An evaluation error was encountered
151    #[error(transparent)]
152    #[diagnostic(transparent)]
153    Evaluation(#[from] EvaluationError),
154    /// A policy set error was encountered
155    #[error(transparent)]
156    #[diagnostic(transparent)]
157    PolicySet(#[from] PolicySetError),
158    /// A request concretization error was encountered
159    #[error(transparent)]
160    #[diagnostic(transparent)]
161    Concretization(#[from] ConcretizationError),
162}
163
164#[doc(hidden)]
165impl From<cedar_policy_core::authorizer::ReauthorizationError> for ReauthorizationError {
166    fn from(e: cedar_policy_core::authorizer::ReauthorizationError) -> Self {
167        match e {
168            cedar_policy_core::authorizer::ReauthorizationError::PolicySetError(err) => {
169                Self::PolicySet(err.into())
170            }
171            cedar_policy_core::authorizer::ReauthorizationError::ConcretizationError(err) => {
172                Self::Concretization(ConcretizationError(err))
173            }
174        }
175    }
176}
177
178/// Errors serializing Schemas to the Cedar syntax
179#[derive(Debug, Error, Diagnostic)]
180#[non_exhaustive]
181pub enum ToCedarSchemaError {
182    /// Duplicate names were found in the schema
183    #[error(transparent)]
184    #[diagnostic(transparent)]
185    NameCollisions(#[from] to_cedar_syntax_errors::NameCollisionsError),
186}
187
188/// Error subtypes for [`ToCedarSchemaError`]
189pub mod to_cedar_syntax_errors {
190    use miette::Diagnostic;
191    use thiserror::Error;
192
193    /// Duplicate names were found in the schema
194    #[derive(Debug, Error, Diagnostic)]
195    #[error("{err}")]
196    pub struct NameCollisionsError {
197        #[diagnostic(transparent)]
198        pub(super) err: cedar_policy_core::validator::cedar_schema::fmt::NameCollisionsError,
199        // because `.names()` needs to return borrowed `&str`, we need somewhere to borrow from, hence here
200        pub(super) names_as_strings: Vec<String>,
201    }
202
203    impl NameCollisionsError {
204        /// Get the names that had collisions
205        pub fn names(&self) -> impl Iterator<Item = &str> {
206            self.names_as_strings
207                .iter()
208                .map(std::string::String::as_str)
209        }
210    }
211}
212
213#[doc(hidden)]
214impl From<cedar_policy_core::validator::cedar_schema::fmt::ToCedarSchemaSyntaxError>
215    for ToCedarSchemaError
216{
217    fn from(
218        value: cedar_policy_core::validator::cedar_schema::fmt::ToCedarSchemaSyntaxError,
219    ) -> Self {
220        match value {
221            cedar_policy_core::validator::cedar_schema::fmt::ToCedarSchemaSyntaxError::NameCollisions(
222                name_collision_err,
223            ) => NameCollisionsError {
224                names_as_strings: name_collision_err
225                    .names()
226                    .map(ToString::to_string)
227                    .collect(),
228                err: name_collision_err,
229            }
230            .into(),
231        }
232    }
233}
234
235/// Error subtypes for [`CedarSchemaError`]
236pub mod cedar_schema_errors {
237    use miette::Diagnostic;
238    use thiserror::Error;
239
240    pub use cedar_policy_core::validator::CedarSchemaParseError as ParseError;
241
242    /// IO error while parsing a Cedar schema
243    #[derive(Debug, Error, Diagnostic)]
244    #[error(transparent)]
245    pub struct IoError(#[from] pub(super) std::io::Error);
246}
247
248/// Errors when parsing schemas
249#[derive(Debug, Diagnostic, Error)]
250#[non_exhaustive]
251pub enum CedarSchemaError {
252    /// Error parsing a schema in the Cedar syntax
253    #[error(transparent)]
254    #[diagnostic(transparent)]
255    Parse(#[from] cedar_schema_errors::ParseError),
256    /// IO error while parsing a Cedar schema
257    #[error(transparent)]
258    #[diagnostic(transparent)]
259    Io(#[from] cedar_schema_errors::IoError),
260    /// Encountered a `SchemaError` while parsing a Cedar schema
261    #[error(transparent)]
262    #[diagnostic(transparent)]
263    Schema(#[from] SchemaError),
264}
265
266#[doc(hidden)]
267impl From<cedar_policy_core::validator::CedarSchemaError> for CedarSchemaError {
268    fn from(value: cedar_policy_core::validator::CedarSchemaError) -> Self {
269        match value {
270            cedar_policy_core::validator::CedarSchemaError::Schema(e) => e.into(),
271            cedar_policy_core::validator::CedarSchemaError::IO(e) => {
272                cedar_schema_errors::IoError(e).into()
273            }
274            cedar_policy_core::validator::CedarSchemaError::Parsing(e) => e.into(),
275        }
276    }
277}
278
279/// Error when evaluating an entity attribute or tag
280#[derive(Debug, Diagnostic, Error)]
281#[error("in {} `{attr_or_tag}` of `{uid}`: {err}", if *.was_attr { "attribute" } else { "tag" })]
282pub struct EntityAttrEvaluationError {
283    /// Action that had the attribute or tag with the error
284    uid: EntityUid,
285    /// Attribute or tag that had the error
286    attr_or_tag: SmolStr,
287    /// Is `attr_or_tag` an attribute (`true`) or a tag (`false`)
288    was_attr: bool,
289    /// Underlying evaluation error
290    #[diagnostic(transparent)]
291    err: EvaluationError,
292}
293
294impl EntityAttrEvaluationError {
295    /// Get the [`EntityUid`] of the action that had the attribute with the error
296    pub fn action(&self) -> &EntityUid {
297        &self.uid
298    }
299
300    /// Get the name of the attribute or tag that had the error
301    //
302    // Method is named `.attr()` and not `.attr_or_tag()` for historical / backwards-compatibility reasons
303    pub fn attr(&self) -> &SmolStr {
304        &self.attr_or_tag
305    }
306
307    /// Get the underlying evaluation error
308    pub fn inner(&self) -> &EvaluationError {
309        &self.err
310    }
311}
312
313#[doc(hidden)]
314impl From<ast::EntityAttrEvaluationError> for EntityAttrEvaluationError {
315    fn from(err: ast::EntityAttrEvaluationError) -> Self {
316        Self {
317            uid: err.uid.into(),
318            attr_or_tag: err.attr_or_tag,
319            was_attr: err.was_attr,
320            err: err.err,
321        }
322    }
323}
324
325/// Errors while trying to create a `Context`
326#[derive(Debug, Diagnostic, Error)]
327pub enum ContextCreationError {
328    /// Tried to create a `Context` out of something other than a record
329    #[error(transparent)]
330    #[diagnostic(transparent)]
331    NotARecord(context_creation_errors::NotARecord),
332    /// Error evaluating the expression given for the `Context`
333    #[error(transparent)]
334    #[diagnostic(transparent)]
335    Evaluation(#[from] EvaluationError),
336    /// Error constructing the expression given for the `Context`.
337    /// Only returned by `Context::from_pairs()`
338    #[error(transparent)]
339    #[diagnostic(transparent)]
340    ExpressionConstruction(#[from] ExpressionConstructionError),
341}
342
343#[doc(hidden)]
344impl From<ast::ContextCreationError> for ContextCreationError {
345    fn from(e: ast::ContextCreationError) -> Self {
346        match e {
347            ast::ContextCreationError::NotARecord(nre) => Self::NotARecord(nre),
348            ast::ContextCreationError::Evaluation(e) => Self::Evaluation(e),
349            ast::ContextCreationError::ExpressionConstruction(ece) => {
350                Self::ExpressionConstruction(ece)
351            }
352        }
353    }
354}
355
356/// Error subtypes for [`ContextCreationError`]
357mod context_creation_errors {
358    pub use cedar_policy_core::ast::context_creation_errors::NotARecord;
359}
360
361/// Error subtypes for [`ValidationError`].
362///
363/// Errors are primarily documented on their variants in [`ValidationError`].
364pub mod validation_errors;
365
366/// An error generated by the validator when it finds a potential problem in a
367/// policy.
368#[derive(Debug, Clone, Error, Diagnostic)]
369#[non_exhaustive]
370pub enum ValidationError {
371    /// A policy contains an entity type that is not declared in the schema.
372    #[error(transparent)]
373    #[diagnostic(transparent)]
374    UnrecognizedEntityType(#[from] validation_errors::UnrecognizedEntityType),
375    /// A policy contains an action that is not declared in the schema.
376    #[error(transparent)]
377    #[diagnostic(transparent)]
378    UnrecognizedActionId(#[from] validation_errors::UnrecognizedActionId),
379    /// There is no action satisfying the action scope constraint that can be
380    /// applied to a principal and resources that both satisfy their respective
381    /// scope conditions.
382    #[error(transparent)]
383    #[diagnostic(transparent)]
384    InvalidActionApplication(#[from] validation_errors::InvalidActionApplication),
385    /// The typechecker expected to see a subtype of one of the types in
386    /// `expected`, but saw `actual`.
387    #[error(transparent)]
388    #[diagnostic(transparent)]
389    UnexpectedType(#[from] validation_errors::UnexpectedType),
390    /// The typechecker could not compute a least upper bound for `types`.
391    #[error(transparent)]
392    #[diagnostic(transparent)]
393    IncompatibleTypes(#[from] validation_errors::IncompatibleTypes),
394    /// The typechecker detected an access to a record or entity attribute
395    /// that it could not statically guarantee would be present.
396    #[error(transparent)]
397    #[diagnostic(transparent)]
398    UnsafeAttributeAccess(#[from] validation_errors::UnsafeAttributeAccess),
399    /// The typechecker could not conclude that an access to an optional
400    /// attribute was safe.
401    #[error(transparent)]
402    #[diagnostic(transparent)]
403    UnsafeOptionalAttributeAccess(#[from] validation_errors::UnsafeOptionalAttributeAccess),
404    /// The typechecker could not conclude that an access to a tag was safe.
405    #[error(transparent)]
406    #[diagnostic(transparent)]
407    UnsafeTagAccess(#[from] validation_errors::UnsafeTagAccess),
408    /// `.getTag()` on an entity type which cannot have tags according to the schema.
409    #[error(transparent)]
410    #[diagnostic(transparent)]
411    NoTagsAllowed(#[from] validation_errors::NoTagsAllowed),
412    /// Undefined extension function.
413    #[error(transparent)]
414    #[diagnostic(transparent)]
415    UndefinedFunction(#[from] validation_errors::UndefinedFunction),
416    /// Incorrect number of arguments in an extension function application.
417    #[error(transparent)]
418    #[diagnostic(transparent)]
419    WrongNumberArguments(#[from] validation_errors::WrongNumberArguments),
420    /// Error returned by custom extension function argument validation
421    #[diagnostic(transparent)]
422    #[error(transparent)]
423    FunctionArgumentValidation(#[from] validation_errors::FunctionArgumentValidation),
424    /// Error returned when an empty set literal is found in a policy.
425    #[diagnostic(transparent)]
426    #[error(transparent)]
427    EmptySetForbidden(#[from] validation_errors::EmptySetForbidden),
428    /// Error returned when an extension constructor is applied to an non-literal expression.
429    #[diagnostic(transparent)]
430    #[error(transparent)]
431    NonLitExtConstructor(#[from] validation_errors::NonLitExtConstructor),
432    /// This error type is no longer ever returned, but remains here for
433    /// backwards-compatibility (removing the variant entirely would be a
434    /// breaking change).
435    #[error(transparent)]
436    #[diagnostic(transparent)]
437    HierarchyNotRespected(#[from] validation_errors::HierarchyNotRespected),
438    /// Returned when an internal invariant is violated (should not happen; if
439    /// this is ever returned, please file an issue)
440    #[error(transparent)]
441    #[diagnostic(transparent)]
442    InternalInvariantViolation(#[from] validation_errors::InternalInvariantViolation),
443    /// Entity level violation
444    #[error(transparent)]
445    #[diagnostic(transparent)]
446    EntityDerefLevelViolation(#[from] validation_errors::EntityDerefLevelViolation),
447    /// Returned when an entity is of an enumerated entity type but has invalid EID
448    #[error(transparent)]
449    #[diagnostic(transparent)]
450    InvalidEnumEntity(#[from] validation_errors::InvalidEnumEntity),
451}
452
453impl ValidationError {
454    /// Extract the policy id of the policy where the validator found the issue.
455    pub fn policy_id(&self) -> &crate::PolicyId {
456        match self {
457            Self::UnrecognizedEntityType(e) => e.policy_id(),
458            Self::UnrecognizedActionId(e) => e.policy_id(),
459            Self::InvalidActionApplication(e) => e.policy_id(),
460            Self::UnexpectedType(e) => e.policy_id(),
461            Self::IncompatibleTypes(e) => e.policy_id(),
462            Self::UnsafeAttributeAccess(e) => e.policy_id(),
463            Self::UnsafeOptionalAttributeAccess(e) => e.policy_id(),
464            Self::UnsafeTagAccess(e) => e.policy_id(),
465            Self::NoTagsAllowed(e) => e.policy_id(),
466            Self::UndefinedFunction(e) => e.policy_id(),
467            Self::WrongNumberArguments(e) => e.policy_id(),
468            Self::FunctionArgumentValidation(e) => e.policy_id(),
469            Self::EmptySetForbidden(e) => e.policy_id(),
470            Self::NonLitExtConstructor(e) => e.policy_id(),
471            Self::HierarchyNotRespected(e) => e.policy_id(),
472            Self::InternalInvariantViolation(e) => e.policy_id(),
473            Self::EntityDerefLevelViolation(e) => e.policy_id(),
474            Self::InvalidEnumEntity(e) => e.policy_id(),
475        }
476    }
477}
478
479#[doc(hidden)]
480impl From<cedar_policy_core::validator::ValidationError> for ValidationError {
481    fn from(error: cedar_policy_core::validator::ValidationError) -> Self {
482        match error {
483            cedar_policy_core::validator::ValidationError::UnrecognizedEntityType(e) => {
484                Self::UnrecognizedEntityType(e.into())
485            }
486            cedar_policy_core::validator::ValidationError::UnrecognizedActionId(e) => {
487                Self::UnrecognizedActionId(e.into())
488            }
489            cedar_policy_core::validator::ValidationError::InvalidActionApplication(e) => {
490                Self::InvalidActionApplication(e.into())
491            }
492            cedar_policy_core::validator::ValidationError::UnexpectedType(e) => {
493                Self::UnexpectedType(e.into())
494            }
495            cedar_policy_core::validator::ValidationError::IncompatibleTypes(e) => {
496                Self::IncompatibleTypes(e.into())
497            }
498            cedar_policy_core::validator::ValidationError::UnsafeAttributeAccess(e) => {
499                Self::UnsafeAttributeAccess(e.into())
500            }
501            cedar_policy_core::validator::ValidationError::UnsafeOptionalAttributeAccess(e) => {
502                Self::UnsafeOptionalAttributeAccess(e.into())
503            }
504            cedar_policy_core::validator::ValidationError::UnsafeTagAccess(e) => {
505                Self::UnsafeTagAccess(e.into())
506            }
507            cedar_policy_core::validator::ValidationError::NoTagsAllowed(e) => {
508                Self::NoTagsAllowed(e.into())
509            }
510            cedar_policy_core::validator::ValidationError::UndefinedFunction(e) => {
511                Self::UndefinedFunction(e.into())
512            }
513            cedar_policy_core::validator::ValidationError::WrongNumberArguments(e) => {
514                Self::WrongNumberArguments(e.into())
515            }
516            cedar_policy_core::validator::ValidationError::FunctionArgumentValidation(e) => {
517                Self::FunctionArgumentValidation(e.into())
518            }
519            cedar_policy_core::validator::ValidationError::EmptySetForbidden(e) => {
520                Self::EmptySetForbidden(e.into())
521            }
522            cedar_policy_core::validator::ValidationError::NonLitExtConstructor(e) => {
523                Self::NonLitExtConstructor(e.into())
524            }
525            cedar_policy_core::validator::ValidationError::InternalInvariantViolation(e) => {
526                Self::InternalInvariantViolation(e.into())
527            }
528            cedar_policy_core::validator::ValidationError::InvalidEnumEntity(e) => {
529                Self::InvalidEnumEntity(e.into())
530            }
531            cedar_policy_core::validator::ValidationError::EntityDerefLevelViolation(e) => {
532                Self::EntityDerefLevelViolation(e.into())
533            }
534        }
535    }
536}
537
538/// Error subtypes for [`ValidationWarning`].
539///
540/// Validation warnings are primarily documented on their variants in [`ValidationWarning`].
541pub mod validation_warnings;
542
543/// Represents the different kinds of validation warnings and information
544/// specific to that warning.
545///
546/// Marked as `non_exhaustive` to allow adding additional warnings in the future
547/// as a non-breaking change.
548#[derive(Debug, Clone, Error, Diagnostic)]
549#[non_exhaustive]
550pub enum ValidationWarning {
551    /// A string contains a mix of characters for different scripts (e.g., latin
552    /// and cyrillic alphabets). Different scripts can contain visually similar
553    /// characters which may be confused for each other.
554    #[diagnostic(transparent)]
555    #[error(transparent)]
556    MixedScriptString(#[from] validation_warnings::MixedScriptString),
557    /// A string contains bidirectional text control characters. These can be used to create crafted pieces of code that obfuscate true control flow.
558    #[diagnostic(transparent)]
559    #[error(transparent)]
560    BidiCharsInString(#[from] validation_warnings::BidiCharsInString),
561    /// An id contains bidirectional text control characters. These can be used to create crafted pieces of code that obfuscate true control flow.
562    #[diagnostic(transparent)]
563    #[error(transparent)]
564    BidiCharsInIdentifier(#[from] validation_warnings::BidiCharsInIdentifier),
565    /// An id contains a mix of characters for different scripts (e.g., latin and
566    /// cyrillic alphabets). Different scripts can contain visually similar
567    /// characters which may be confused for each other.
568    #[diagnostic(transparent)]
569    #[error(transparent)]
570    MixedScriptIdentifier(#[from] validation_warnings::MixedScriptIdentifier),
571    /// An id contains characters that is not a [graphical ASCII character](https://doc.rust-lang.org/std/primitive.char.html#method.is_ascii_graphic),
572    /// not the space character (`U+0020`), and falls outside of the General
573    /// Security Profile for Identifiers. We recommend adhering to this if
574    /// possible. See [Unicode® Technical Standard #39](https://unicode.org/reports/tr39/#General_Security_Profile) for more information.
575    #[diagnostic(transparent)]
576    #[error(transparent)]
577    ConfusableIdentifier(#[from] validation_warnings::ConfusableIdentifier),
578    /// The typechecker found that a policy condition will always evaluate to false.
579    #[diagnostic(transparent)]
580    #[error(transparent)]
581    ImpossiblePolicy(#[from] validation_warnings::ImpossiblePolicy),
582}
583
584impl ValidationWarning {
585    /// Extract the policy id of the policy where the validator found the issue.
586    pub fn policy_id(&self) -> &PolicyId {
587        match self {
588            Self::MixedScriptString(w) => w.policy_id(),
589            Self::BidiCharsInString(w) => w.policy_id(),
590            Self::BidiCharsInIdentifier(w) => w.policy_id(),
591            Self::MixedScriptIdentifier(w) => w.policy_id(),
592            Self::ConfusableIdentifier(w) => w.policy_id(),
593            Self::ImpossiblePolicy(w) => w.policy_id(),
594        }
595    }
596}
597
598#[doc(hidden)]
599impl From<cedar_policy_core::validator::ValidationWarning> for ValidationWarning {
600    fn from(warning: cedar_policy_core::validator::ValidationWarning) -> Self {
601        match warning {
602            cedar_policy_core::validator::ValidationWarning::MixedScriptString(w) => {
603                Self::MixedScriptString(w.into())
604            }
605            cedar_policy_core::validator::ValidationWarning::BidiCharsInString(w) => {
606                Self::BidiCharsInString(w.into())
607            }
608            cedar_policy_core::validator::ValidationWarning::BidiCharsInIdentifier(w) => {
609                Self::BidiCharsInIdentifier(w.into())
610            }
611            cedar_policy_core::validator::ValidationWarning::MixedScriptIdentifier(w) => {
612                Self::MixedScriptIdentifier(w.into())
613            }
614            cedar_policy_core::validator::ValidationWarning::ConfusableIdentifier(w) => {
615                Self::ConfusableIdentifier(w.into())
616            }
617            cedar_policy_core::validator::ValidationWarning::ImpossiblePolicy(w) => {
618                Self::ImpossiblePolicy(w.into())
619            }
620        }
621    }
622}
623
624/// Error subtypes for [`PolicySetError`]
625pub mod policy_set_errors {
626    use super::Error;
627    use crate::PolicyId;
628    use cedar_policy_core::ast;
629    use miette::Diagnostic;
630
631    /// There was a duplicate [`PolicyId`] encountered in either the set of
632    /// templates or the set of policies.
633    #[derive(Debug, Diagnostic, Error)]
634    #[error("duplicate template or policy id `{id}`")]
635    pub struct AlreadyDefined {
636        pub(crate) id: PolicyId,
637    }
638
639    impl AlreadyDefined {
640        /// Get the [`PolicyId`] for which there was a duplicate
641        pub fn duplicate_id(&self) -> &PolicyId {
642            &self.id
643        }
644    }
645
646    /// Error when linking a template
647    #[derive(Debug, Diagnostic, Error)]
648    #[error("unable to link template")]
649    pub struct LinkingError {
650        #[from]
651        #[diagnostic(transparent)]
652        pub(crate) inner: ast::LinkingError,
653    }
654
655    /// Expected a static policy, but a template-linked policy was provided
656    #[derive(Debug, Diagnostic, Error)]
657    #[error("expected a static policy, but a template-linked policy was provided")]
658    pub struct ExpectedStatic {
659        /// A private field, just so the public interface notes this as a
660        /// private-fields struct and not a empty-fields struct for semver
661        /// purposes (e.g., consumers cannot construct this type with
662        /// `ExpectedStatic {}`)
663        _dummy: (),
664    }
665
666    impl ExpectedStatic {
667        pub(crate) fn new() -> Self {
668            Self { _dummy: () }
669        }
670    }
671
672    /// Expected a template, but a static policy was provided.
673    #[derive(Debug, Diagnostic, Error)]
674    #[error("expected a template, but a static policy was provided")]
675    pub struct ExpectedTemplate {
676        /// A private field, just so the public interface notes this as a
677        /// private-fields struct and not a empty-fields struct for semver
678        /// purposes (e.g., consumers cannot construct this type with
679        /// `ExpectedTemplate {}`)
680        _dummy: (),
681    }
682
683    impl ExpectedTemplate {
684        pub(crate) fn new() -> Self {
685            Self { _dummy: () }
686        }
687    }
688
689    /// Error when removing a static policy that doesn't exist
690    #[derive(Debug, Diagnostic, Error)]
691    #[error("unable to remove static policy `{policy_id}` because it does not exist")]
692    pub struct PolicyNonexistentError {
693        pub(crate) policy_id: PolicyId,
694    }
695
696    impl PolicyNonexistentError {
697        /// Get the [`PolicyId`] of the policy which didn't exist
698        pub fn policy_id(&self) -> &PolicyId {
699            &self.policy_id
700        }
701    }
702
703    /// Error when removing a template that doesn't exist
704    #[derive(Debug, Diagnostic, Error)]
705    #[error("unable to remove template `{template_id}` because it does not exist")]
706    pub struct TemplateNonexistentError {
707        pub(crate) template_id: PolicyId,
708    }
709
710    impl TemplateNonexistentError {
711        /// Get the [`PolicyId`] of the template which didn't exist
712        pub fn template_id(&self) -> &PolicyId {
713            &self.template_id
714        }
715    }
716
717    /// Error when removing a template with active links
718    #[derive(Debug, Diagnostic, Error)]
719    #[error("unable to remove policy template `{template_id}` because it has active links")]
720    pub struct RemoveTemplateWithActiveLinksError {
721        pub(crate) template_id: PolicyId,
722    }
723
724    impl RemoveTemplateWithActiveLinksError {
725        /// Get the [`PolicyId`] of the template which had active links
726        pub fn template_id(&self) -> &PolicyId {
727            &self.template_id
728        }
729    }
730
731    /// Error when removing a template that is not a template
732    #[derive(Debug, Diagnostic, Error)]
733    #[error("unable to remove policy template `{template_id}` because it is not a template")]
734    pub struct RemoveTemplateNotTemplateError {
735        pub(crate) template_id: PolicyId,
736    }
737
738    impl RemoveTemplateNotTemplateError {
739        /// Get the [`PolicyId`] of the template which is not a template
740        pub fn template_id(&self) -> &PolicyId {
741            &self.template_id
742        }
743    }
744
745    /// Error when unlinking a template-linked policy
746    #[derive(Debug, Diagnostic, Error)]
747    #[error("unable to unlink policy `{policy_id}` because it does not exist")]
748    pub struct LinkNonexistentError {
749        pub(crate) policy_id: PolicyId,
750    }
751
752    impl LinkNonexistentError {
753        /// Get the [`PolicyId`] of the link which does not exist
754        pub fn policy_id(&self) -> &PolicyId {
755            &self.policy_id
756        }
757    }
758
759    /// Error when removing a link that is not a link
760    #[derive(Debug, Diagnostic, Error)]
761    #[error("unable to unlink `{policy_id}` because it is not a link")]
762    pub struct UnlinkLinkNotLinkError {
763        pub(crate) policy_id: PolicyId,
764    }
765
766    impl UnlinkLinkNotLinkError {
767        /// Get the [`PolicyId`] of the link which is not a link
768        pub fn policy_id(&self) -> &PolicyId {
769            &self.policy_id
770        }
771    }
772
773    /// Error during JSON ser/de of the policy set (as opposed to individual policies)
774    #[derive(Debug, Diagnostic, Error)]
775    #[error("error serializing/deserializing policy set to/from JSON")]
776    pub struct JsonPolicySetError {
777        #[from]
778        pub(crate) inner: serde_json::Error,
779    }
780}
781
782/// Potential errors when adding to a `PolicySet`.
783#[derive(Debug, Diagnostic, Error)]
784#[non_exhaustive]
785pub enum PolicySetError {
786    /// There was a duplicate [`PolicyId`] encountered in either the set of
787    /// templates or the set of policies.
788    #[error(transparent)]
789    #[diagnostic(transparent)]
790    AlreadyDefined(#[from] policy_set_errors::AlreadyDefined),
791    /// Error when linking a template
792    #[error(transparent)]
793    #[diagnostic(transparent)]
794    Linking(#[from] policy_set_errors::LinkingError),
795    /// Expected a static policy, but a template-linked policy was provided
796    #[error(transparent)]
797    #[diagnostic(transparent)]
798    ExpectedStatic(#[from] policy_set_errors::ExpectedStatic),
799    /// Expected a template, but a static policy was provided.
800    #[error(transparent)]
801    #[diagnostic(transparent)]
802    ExpectedTemplate(#[from] policy_set_errors::ExpectedTemplate),
803    /// Error when removing a static policy that doesn't exist
804    #[error(transparent)]
805    #[diagnostic(transparent)]
806    PolicyNonexistent(#[from] policy_set_errors::PolicyNonexistentError),
807    /// Error when removing a template that doesn't exist
808    #[error(transparent)]
809    #[diagnostic(transparent)]
810    TemplateNonexistent(#[from] policy_set_errors::TemplateNonexistentError),
811    /// Error when removing a template with active links
812    #[error(transparent)]
813    #[diagnostic(transparent)]
814    RemoveTemplateWithActiveLinks(#[from] policy_set_errors::RemoveTemplateWithActiveLinksError),
815    /// Error when removing a template that is not a template
816    #[error(transparent)]
817    #[diagnostic(transparent)]
818    RemoveTemplateNotTemplate(#[from] policy_set_errors::RemoveTemplateNotTemplateError),
819    /// Error when unlinking a linked policy
820    #[error(transparent)]
821    #[diagnostic(transparent)]
822    LinkNonexistent(#[from] policy_set_errors::LinkNonexistentError),
823    /// Error when removing a link that is not a link
824    #[error(transparent)]
825    #[diagnostic(transparent)]
826    UnlinkLinkNotLink(#[from] policy_set_errors::UnlinkLinkNotLinkError),
827    /// Error when converting a policy/template from JSON format
828    #[error(transparent)]
829    #[diagnostic(transparent)]
830    FromJson(#[from] PolicyFromJsonError),
831    /// Error when converting a policy/template to JSON format
832    #[error("Error serializing a policy/template to JSON")]
833    #[diagnostic(transparent)]
834    ToJson(#[from] PolicyToJsonError),
835    /// Error during JSON ser/de of the policy set (as opposed to individual policies)
836    #[error(transparent)]
837    #[diagnostic(transparent)]
838    JsonPolicySet(#[from] policy_set_errors::JsonPolicySetError),
839}
840
841#[doc(hidden)]
842impl From<ast::PolicySetError> for PolicySetError {
843    fn from(e: ast::PolicySetError) -> Self {
844        match e {
845            ast::PolicySetError::Occupied { id } => {
846                Self::AlreadyDefined(policy_set_errors::AlreadyDefined {
847                    id: PolicyId::new(id),
848                })
849            }
850        }
851    }
852}
853
854#[doc(hidden)]
855impl From<ast::LinkingError> for PolicySetError {
856    fn from(e: ast::LinkingError) -> Self {
857        Self::Linking(e.into())
858    }
859}
860
861#[doc(hidden)]
862impl From<ast::UnexpectedSlotError> for PolicySetError {
863    fn from(_: ast::UnexpectedSlotError) -> Self {
864        Self::ExpectedStatic(policy_set_errors::ExpectedStatic::new())
865    }
866}
867
868#[doc(hidden)]
869impl From<est::PolicySetFromJsonError> for PolicySetError {
870    fn from(e: est::PolicySetFromJsonError) -> Self {
871        match e {
872            est::PolicySetFromJsonError::PolicySet(e) => e.into(),
873            est::PolicySetFromJsonError::Linking(e) => e.into(),
874            est::PolicySetFromJsonError::FromJsonError(e) => Self::FromJson(e.into()),
875        }
876    }
877}
878
879/// Represents one or more [`ParseError`]s encountered when parsing a policy or
880/// expression.
881///
882/// By default, the `Diagnostic` and `Error` implementations will only print the
883/// first error. If you want to see all errors, use `.iter()` or `.into_iter()`.
884#[derive(Debug, Diagnostic, Error)]
885#[error(transparent)]
886#[diagnostic(transparent)]
887pub struct ParseErrors(#[from] cedar_policy_core::parser::err::ParseErrors);
888
889impl ParseErrors {
890    /// Get every [`ParseError`] associated with this [`ParseErrors`] object.
891    /// The returned iterator is guaranteed to be nonempty.
892    pub fn iter(&self) -> impl Iterator<Item = &ParseError> {
893        self.0.iter().map(ParseError::ref_cast)
894    }
895}
896
897/// Errors that can occur when parsing policies or expressions.
898///
899/// Marked as `non_exhaustive` to support adding additional error information
900/// in the future without a major version bump.
901#[derive(Debug, Diagnostic, Error, RefCast)]
902#[repr(transparent)]
903#[error(transparent)]
904#[diagnostic(transparent)]
905#[non_exhaustive]
906pub struct ParseError {
907    #[from]
908    inner: cedar_policy_core::parser::err::ParseError,
909}
910
911/// Errors that can happen when getting the JSON representation of a policy
912#[derive(Debug, Diagnostic, Error)]
913pub enum PolicyToJsonError {
914    /// Parse error in the policy text
915    #[error(transparent)]
916    #[diagnostic(transparent)]
917    Parse(#[from] ParseErrors),
918    /// For linked policies, error linking the JSON representation
919    #[error(transparent)]
920    #[diagnostic(transparent)]
921    Link(#[from] policy_to_json_errors::JsonLinkError),
922    /// Error in the JSON serialization
923    #[error(transparent)]
924    JsonSerialization(#[from] policy_to_json_errors::PolicyJsonSerializationError),
925}
926
927#[doc(hidden)]
928impl From<est::LinkingError> for PolicyToJsonError {
929    fn from(e: est::LinkingError) -> Self {
930        policy_to_json_errors::JsonLinkError::from(e).into()
931    }
932}
933
934impl From<serde_json::Error> for PolicyToJsonError {
935    fn from(e: serde_json::Error) -> Self {
936        policy_to_json_errors::PolicyJsonSerializationError::from(e).into()
937    }
938}
939
940/// Error subtypes for [`PolicyToJsonError`]
941pub mod policy_to_json_errors {
942    use cedar_policy_core::est;
943    use miette::Diagnostic;
944    use thiserror::Error;
945
946    /// Error linking the JSON representation of a linked policy
947    #[derive(Debug, Diagnostic, Error)]
948    #[error(transparent)]
949    #[diagnostic(transparent)]
950    pub struct JsonLinkError {
951        /// Underlying error
952        #[from]
953        err: est::LinkingError,
954    }
955
956    /// Error serializing a policy as JSON
957    #[derive(Debug, Diagnostic, Error)]
958    #[error(transparent)]
959    pub struct PolicyJsonSerializationError {
960        /// Underlying error
961        #[from]
962        err: serde_json::Error,
963    }
964}
965
966/// Error when converting a policy or template from JSON format
967#[derive(Debug, Diagnostic, Error)]
968#[error("error deserializing a policy/template from JSON")]
969#[diagnostic(transparent)]
970pub struct PolicyFromJsonError {
971    #[from]
972    pub(crate) inner: cedar_policy_core::est::FromJsonError,
973}
974
975/// Error type for parsing `Context` from JSON
976#[derive(Debug, Diagnostic, Error)]
977pub enum ContextJsonError {
978    /// Error deserializing the JSON into a [`crate::Context`]
979    #[error(transparent)]
980    #[diagnostic(transparent)]
981    JsonDeserialization(#[from] entities_json_errors::JsonDeserializationError),
982    /// Error constructing the [`crate::Context`] itself
983    #[error(transparent)]
984    #[diagnostic(transparent)]
985    ContextCreation(#[from] ContextCreationError),
986    /// The supplied action doesn't exist in the supplied schema
987    #[error(transparent)]
988    #[diagnostic(transparent)]
989    MissingAction(#[from] context_json_errors::MissingActionError),
990}
991
992impl ContextJsonError {
993    /// Construct a `ContextJsonError::MissingAction`
994    pub(crate) fn missing_action(action: EntityUid) -> Self {
995        Self::MissingAction(context_json_errors::MissingActionError { action })
996    }
997}
998
999#[doc(hidden)]
1000impl From<cedar_policy_core::entities::json::ContextJsonDeserializationError> for ContextJsonError {
1001    fn from(e: cedar_policy_core::entities::json::ContextJsonDeserializationError) -> Self {
1002        match e {
1003            cedar_policy_core::entities::json::ContextJsonDeserializationError::JsonDeserialization(e) => Self::JsonDeserialization(e),
1004            cedar_policy_core::entities::json::ContextJsonDeserializationError::ContextCreation(e) => Self::ContextCreation(e.into())
1005        }
1006    }
1007}
1008
1009/// Error subtypes for [`ContextJsonError`]
1010pub mod context_json_errors {
1011    use super::EntityUid;
1012    use miette::Diagnostic;
1013    use thiserror::Error;
1014
1015    /// The supplied action doesn't exist in the supplied schema
1016    #[derive(Debug, Diagnostic, Error)]
1017    #[error("action `{action}` does not exist in the supplied schema")]
1018    pub struct MissingActionError {
1019        /// UID of the action which doesn't exist
1020        pub(super) action: EntityUid,
1021    }
1022
1023    impl MissingActionError {
1024        /// Get the [`EntityUid`] of the action which doesn't exist
1025        pub fn action(&self) -> &EntityUid {
1026            &self.action
1027        }
1028    }
1029}
1030
1031/// Error type for parsing a `RestrictedExpression`
1032#[derive(Debug, Diagnostic, Error)]
1033#[non_exhaustive]
1034pub enum RestrictedExpressionParseError {
1035    /// Failed to parse the expression
1036    #[error(transparent)]
1037    #[diagnostic(transparent)]
1038    Parse(#[from] ParseErrors),
1039    /// Parsed successfully as an expression, but failed to construct a
1040    /// restricted expression, for the reason indicated in the underlying error
1041    #[error(transparent)]
1042    #[diagnostic(transparent)]
1043    InvalidRestrictedExpression(#[from] RestrictedExpressionError),
1044}
1045
1046#[doc(hidden)]
1047impl From<cedar_policy_core::ast::RestrictedExpressionParseError>
1048    for RestrictedExpressionParseError
1049{
1050    fn from(e: cedar_policy_core::ast::RestrictedExpressionParseError) -> Self {
1051        match e {
1052            cedar_policy_core::ast::RestrictedExpressionParseError::Parse(e) => {
1053                Self::Parse(e.into())
1054            }
1055            cedar_policy_core::ast::RestrictedExpressionParseError::InvalidRestrictedExpression(
1056                e,
1057            ) => e.into(),
1058        }
1059    }
1060}
1061
1062/// The request does not conform to the schema
1063#[derive(Debug, Diagnostic, Error)]
1064#[non_exhaustive]
1065pub enum RequestValidationError {
1066    /// Request action is not declared in the schema
1067    #[error(transparent)]
1068    #[diagnostic(transparent)]
1069    UndeclaredAction(#[from] request_validation_errors::UndeclaredActionError),
1070    /// Request principal is of a type not declared in the schema
1071    #[error(transparent)]
1072    #[diagnostic(transparent)]
1073    UndeclaredPrincipalType(#[from] request_validation_errors::UndeclaredPrincipalTypeError),
1074    /// Request resource is of a type not declared in the schema
1075    #[error(transparent)]
1076    #[diagnostic(transparent)]
1077    UndeclaredResourceType(#[from] request_validation_errors::UndeclaredResourceTypeError),
1078    /// Request principal is of a type that is declared in the schema, but is
1079    /// not valid for the request action
1080    #[error(transparent)]
1081    #[diagnostic(transparent)]
1082    InvalidPrincipalType(#[from] request_validation_errors::InvalidPrincipalTypeError),
1083    /// Request resource is of a type that is declared in the schema, but is
1084    /// not valid for the request action
1085    #[error(transparent)]
1086    #[diagnostic(transparent)]
1087    InvalidResourceType(#[from] request_validation_errors::InvalidResourceTypeError),
1088    /// Context does not comply with the shape specified for the request action
1089    #[error(transparent)]
1090    #[diagnostic(transparent)]
1091    InvalidContext(#[from] request_validation_errors::InvalidContextError),
1092    /// Error computing the type of the `Context`
1093    #[error(transparent)]
1094    #[diagnostic(transparent)]
1095    TypeOfContext(#[from] request_validation_errors::TypeOfContextError),
1096    /// Error when a principal or resource entity is of an enumerated entity
1097    /// type but has an invalid EID
1098    #[error(transparent)]
1099    #[diagnostic(transparent)]
1100    InvalidEnumEntity(#[from] request_validation_errors::InvalidEnumEntityError),
1101}
1102
1103#[doc(hidden)]
1104impl From<cedar_policy_core::validator::RequestValidationError> for RequestValidationError {
1105    fn from(e: cedar_policy_core::validator::RequestValidationError) -> Self {
1106        match e {
1107            cedar_policy_core::validator::RequestValidationError::UndeclaredAction(e) => {
1108                Self::UndeclaredAction(e.into())
1109            }
1110            cedar_policy_core::validator::RequestValidationError::UndeclaredPrincipalType(e) => {
1111                Self::UndeclaredPrincipalType(e.into())
1112            }
1113            cedar_policy_core::validator::RequestValidationError::UndeclaredResourceType(e) => {
1114                Self::UndeclaredResourceType(e.into())
1115            }
1116            cedar_policy_core::validator::RequestValidationError::InvalidPrincipalType(e) => {
1117                Self::InvalidPrincipalType(e.into())
1118            }
1119            cedar_policy_core::validator::RequestValidationError::InvalidResourceType(e) => {
1120                Self::InvalidResourceType(e.into())
1121            }
1122            cedar_policy_core::validator::RequestValidationError::InvalidContext(e) => {
1123                Self::InvalidContext(e.into())
1124            }
1125            cedar_policy_core::validator::RequestValidationError::TypeOfContext(e) => {
1126                Self::TypeOfContext(e.into())
1127            }
1128            cedar_policy_core::validator::RequestValidationError::InvalidEnumEntity(e) => {
1129                Self::InvalidEnumEntity(e.into())
1130            }
1131        }
1132    }
1133}
1134
1135/// Error subtypes for [`RequestValidationError`]
1136pub mod request_validation_errors {
1137    use cedar_policy_core::extensions::ExtensionFunctionLookupError;
1138    use miette::Diagnostic;
1139    use ref_cast::RefCast;
1140    use thiserror::Error;
1141
1142    use crate::{Context, EntityTypeName, EntityUid};
1143
1144    /// Request action is not declared in the schema
1145    #[derive(Debug, Diagnostic, Error)]
1146    #[error(transparent)]
1147    #[diagnostic(transparent)]
1148    pub struct UndeclaredActionError(
1149        #[from] cedar_policy_core::validator::request_validation_errors::UndeclaredActionError,
1150    );
1151
1152    impl UndeclaredActionError {
1153        /// The action which was not declared in the schema
1154        pub fn action(&self) -> &EntityUid {
1155            RefCast::ref_cast(self.0.action())
1156        }
1157    }
1158
1159    /// Request principal is of a type not declared in the schema
1160    #[derive(Debug, Diagnostic, Error)]
1161    #[error(transparent)]
1162    #[diagnostic(transparent)]
1163    pub struct UndeclaredPrincipalTypeError(
1164        #[from]
1165        cedar_policy_core::validator::request_validation_errors::UndeclaredPrincipalTypeError,
1166    );
1167
1168    impl UndeclaredPrincipalTypeError {
1169        /// The principal type which was not declared in the schema
1170        pub fn principal_ty(&self) -> &EntityTypeName {
1171            RefCast::ref_cast(self.0.principal_ty())
1172        }
1173    }
1174
1175    /// Request resource is of a type not declared in the schema
1176    #[derive(Debug, Diagnostic, Error)]
1177    #[error(transparent)]
1178    #[diagnostic(transparent)]
1179    pub struct UndeclaredResourceTypeError(
1180        #[from]
1181        cedar_policy_core::validator::request_validation_errors::UndeclaredResourceTypeError,
1182    );
1183
1184    impl UndeclaredResourceTypeError {
1185        /// The resource type which was not declared in the schema
1186        pub fn resource_ty(&self) -> &EntityTypeName {
1187            RefCast::ref_cast(self.0.resource_ty())
1188        }
1189    }
1190
1191    /// Request principal is of a type that is declared in the schema, but is
1192    /// not valid for the request action
1193    #[derive(Debug, Diagnostic, Error)]
1194    #[error(transparent)]
1195    #[diagnostic(transparent)]
1196    pub struct InvalidPrincipalTypeError(
1197        #[from] cedar_policy_core::validator::request_validation_errors::InvalidPrincipalTypeError,
1198    );
1199
1200    impl InvalidPrincipalTypeError {
1201        /// The principal type which is not valid
1202        pub fn principal_ty(&self) -> &EntityTypeName {
1203            RefCast::ref_cast(self.0.principal_ty())
1204        }
1205
1206        /// The action which it is not valid for
1207        pub fn action(&self) -> &EntityUid {
1208            RefCast::ref_cast(self.0.action())
1209        }
1210    }
1211
1212    /// Request resource is of a type that is declared in the schema, but is
1213    /// not valid for the request action
1214    #[derive(Debug, Diagnostic, Error)]
1215    #[error(transparent)]
1216    #[diagnostic(transparent)]
1217    pub struct InvalidResourceTypeError(
1218        #[from] cedar_policy_core::validator::request_validation_errors::InvalidResourceTypeError,
1219    );
1220
1221    impl InvalidResourceTypeError {
1222        /// The resource type which is not valid
1223        pub fn resource_ty(&self) -> &EntityTypeName {
1224            RefCast::ref_cast(self.0.resource_ty())
1225        }
1226
1227        /// The action which it is not valid for
1228        pub fn action(&self) -> &EntityUid {
1229            RefCast::ref_cast(self.0.action())
1230        }
1231    }
1232
1233    /// Context does not comply with the shape specified for the request action
1234    #[derive(Debug, Diagnostic, Error)]
1235    #[error(transparent)]
1236    #[diagnostic(transparent)]
1237    pub struct InvalidContextError(
1238        #[from] cedar_policy_core::validator::request_validation_errors::InvalidContextError,
1239    );
1240
1241    impl InvalidContextError {
1242        /// The context which is not valid
1243        pub fn context(&self) -> &Context {
1244            RefCast::ref_cast(self.0.context())
1245        }
1246
1247        /// The action which it is not valid for
1248        pub fn action(&self) -> &EntityUid {
1249            RefCast::ref_cast(self.0.action())
1250        }
1251    }
1252
1253    /// Error computing the type of the `Context`
1254    #[derive(Debug, Diagnostic, Error)]
1255    #[error(transparent)]
1256    #[diagnostic(transparent)]
1257    pub struct TypeOfContextError(#[from] ExtensionFunctionLookupError);
1258
1259    /// Error when a principal or resource entity is of an enumerated entity
1260    /// type but has an invalid EID
1261    #[derive(Debug, Diagnostic, Error)]
1262    #[error(transparent)]
1263    #[diagnostic(transparent)]
1264    pub struct InvalidEnumEntityError(
1265        #[from] cedar_policy_core::entities::conformance::err::InvalidEnumEntityError,
1266    );
1267}
1268
1269/// An error generated by entity slicing.
1270#[derive(Debug, Error, Diagnostic)]
1271#[non_exhaustive]
1272#[cfg(feature = "entity-manifest")]
1273pub enum EntityManifestError {
1274    /// A validation error was encountered
1275    #[error(transparent)]
1276    #[diagnostic(transparent)]
1277    Validation(#[from] ValidationResult),
1278    /// A entities error was encountered
1279    #[error(transparent)]
1280    #[diagnostic(transparent)]
1281    Entities(#[from] EntitiesError),
1282
1283    /// The request was partial
1284    #[error(transparent)]
1285    #[diagnostic(transparent)]
1286    PartialRequest(#[from] PartialRequestError),
1287    /// A policy was partial
1288    #[error(transparent)]
1289    #[diagnostic(transparent)]
1290    PartialExpression(#[from] PartialExpressionError),
1291    /// Encounters unsupported Cedar feature
1292    #[error(transparent)]
1293    #[diagnostic(transparent)]
1294    UnsupportedCedarFeature(#[from] UnsupportedCedarFeatureError),
1295}
1296
1297#[cfg(feature = "entity-manifest")]
1298impl From<entity_manifest::EntityManifestError> for EntityManifestError {
1299    fn from(e: entity_manifest::EntityManifestError) -> Self {
1300        match e {
1301            entity_manifest::EntityManifestError::Validation(e) => Self::Validation(e.into()),
1302            entity_manifest::EntityManifestError::Entities(e) => Self::Entities(e),
1303            entity_manifest::EntityManifestError::PartialRequest(e) => Self::PartialRequest(e),
1304            entity_manifest::EntityManifestError::PartialExpression(e) => {
1305                Self::PartialExpression(e)
1306            }
1307            entity_manifest::EntityManifestError::UnsupportedCedarFeature(e) => {
1308                Self::UnsupportedCedarFeature(e)
1309            }
1310        }
1311    }
1312}
1313
1314#[cfg(feature = "tpe")]
1315/// Error thrown when creating a `PartialRequest`
1316#[derive(Debug, Error, Diagnostic)]
1317pub enum PartialRequestCreationError {
1318    /// When the context contains unknowns
1319    #[error("Context contains unknowns")]
1320    ContextContainsUnknowns,
1321    /// When the request does not pass validation
1322    #[error(transparent)]
1323    #[diagnostic(transparent)]
1324    Validation(#[from] RequestValidationError),
1325}
1326
1327#[cfg(feature = "tpe")]
1328/// Errors that can be encountered when re-evaluating a partial response
1329#[derive(Debug, Error)]
1330pub enum TPEReauthorizationError {
1331    /// `Request` cannot be validated
1332    #[error(transparent)]
1333    RequestValidation(#[from] RequestValidationError),
1334    /// `Entities` cannot be validated
1335    #[error(transparent)]
1336    EntityValidation(#[from] EntitySchemaConformanceError),
1337    /// Inconsistent entities
1338    #[error(transparent)]
1339    InconsistentEntities(#[from] tpe_err::EntitiesConsistencyError),
1340    /// Inconsistent requests
1341    #[error(transparent)]
1342    InconsistentRequests(#[from] tpe_err::RequestConsistencyError),
1343}
1344
1345#[cfg(feature = "tpe")]
1346impl From<tpe_err::ReauthorizationError> for TPEReauthorizationError {
1347    fn from(value: tpe_err::ReauthorizationError) -> Self {
1348        match value {
1349            tpe_err::ReauthorizationError::EntitiesConsistentcy(e) => Self::InconsistentEntities(e),
1350            tpe_err::ReauthorizationError::EntityValidation(e) => Self::EntityValidation(e),
1351            tpe_err::ReauthorizationError::RequestConsistentcy(e) => Self::InconsistentRequests(e),
1352            tpe_err::ReauthorizationError::RequestValidation(e) => {
1353                Self::RequestValidation(e.into())
1354            }
1355        }
1356    }
1357}
1358
1359#[cfg(feature = "tpe")]
1360/// Errors that can be encountered when performing a permission query
1361#[derive(Debug, Error)]
1362pub enum PermissionQueryError {
1363    /// When entities contain unknowns
1364    #[error(transparent)]
1365    EntitiesContainUnknown(#[from] PartialValueToValueError),
1366    /// When TPE fails
1367    #[error(transparent)]
1368    TPE(#[from] tpe_err::TPEError),
1369    /// When concrete entities fail validation
1370    #[error(transparent)]
1371    EntityValidation(#[from] EntitySchemaConformanceError),
1372}