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