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