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///
356/// Errors are primarily documented on their variants in [`ValidationError`].
357pub mod validation_errors;
358
359/// An error generated by the validator when it finds a potential problem in a
360/// policy.
361#[derive(Debug, Clone, Error, Diagnostic)]
362#[non_exhaustive]
363pub enum ValidationError {
364    /// A policy contains an entity type that is not declared in the schema.
365    #[error(transparent)]
366    #[diagnostic(transparent)]
367    UnrecognizedEntityType(#[from] validation_errors::UnrecognizedEntityType),
368    /// A policy contains an action that is not declared in the schema.
369    #[error(transparent)]
370    #[diagnostic(transparent)]
371    UnrecognizedActionId(#[from] validation_errors::UnrecognizedActionId),
372    /// There is no action satisfying the action scope constraint that can be
373    /// applied to a principal and resources that both satisfy their respective
374    /// scope conditions.
375    #[error(transparent)]
376    #[diagnostic(transparent)]
377    InvalidActionApplication(#[from] validation_errors::InvalidActionApplication),
378    /// The typechecker expected to see a subtype of one of the types in
379    /// `expected`, but saw `actual`.
380    #[error(transparent)]
381    #[diagnostic(transparent)]
382    UnexpectedType(#[from] validation_errors::UnexpectedType),
383    /// The typechecker could not compute a least upper bound for `types`.
384    #[error(transparent)]
385    #[diagnostic(transparent)]
386    IncompatibleTypes(#[from] validation_errors::IncompatibleTypes),
387    /// The typechecker detected an access to a record or entity attribute
388    /// that it could not statically guarantee would be present.
389    #[error(transparent)]
390    #[diagnostic(transparent)]
391    UnsafeAttributeAccess(#[from] validation_errors::UnsafeAttributeAccess),
392    /// The typechecker could not conclude that an access to an optional
393    /// attribute was safe.
394    #[error(transparent)]
395    #[diagnostic(transparent)]
396    UnsafeOptionalAttributeAccess(#[from] validation_errors::UnsafeOptionalAttributeAccess),
397    /// The typechecker could not conclude that an access to a tag was safe.
398    #[error(transparent)]
399    #[diagnostic(transparent)]
400    UnsafeTagAccess(#[from] validation_errors::UnsafeTagAccess),
401    /// `.getTag()` on an entity type which cannot have tags according to the schema.
402    #[error(transparent)]
403    #[diagnostic(transparent)]
404    NoTagsAllowed(#[from] validation_errors::NoTagsAllowed),
405    /// Undefined extension function.
406    #[error(transparent)]
407    #[diagnostic(transparent)]
408    UndefinedFunction(#[from] validation_errors::UndefinedFunction),
409    /// Incorrect number of arguments in an extension function application.
410    #[error(transparent)]
411    #[diagnostic(transparent)]
412    WrongNumberArguments(#[from] validation_errors::WrongNumberArguments),
413    /// Error returned by custom extension function argument validation
414    #[diagnostic(transparent)]
415    #[error(transparent)]
416    FunctionArgumentValidation(#[from] validation_errors::FunctionArgumentValidation),
417    /// Error returned when an empty set literal is found in a policy.
418    #[diagnostic(transparent)]
419    #[error(transparent)]
420    EmptySetForbidden(#[from] validation_errors::EmptySetForbidden),
421    /// Error returned when an extension constructor is applied to an non-literal expression.
422    #[diagnostic(transparent)]
423    #[error(transparent)]
424    NonLitExtConstructor(#[from] validation_errors::NonLitExtConstructor),
425    /// This error type is no longer ever returned, but remains here for
426    /// backwards-compatibility (removing the variant entirely would be a
427    /// breaking change).
428    #[error(transparent)]
429    #[diagnostic(transparent)]
430    HierarchyNotRespected(#[from] validation_errors::HierarchyNotRespected),
431    /// Returned when an internal invariant is violated (should not happen; if
432    /// this is ever returned, please file an issue)
433    #[error(transparent)]
434    #[diagnostic(transparent)]
435    InternalInvariantViolation(#[from] validation_errors::InternalInvariantViolation),
436    /// Entity level violation
437    #[error(transparent)]
438    #[diagnostic(transparent)]
439    EntityDerefLevelViolation(#[from] validation_errors::EntityDerefLevelViolation),
440    /// Returned when an entity is of an enumerated entity type but has invalid EID
441    #[error(transparent)]
442    #[diagnostic(transparent)]
443    InvalidEnumEntity(#[from] validation_errors::InvalidEnumEntity),
444}
445
446impl ValidationError {
447    /// Extract the policy id of the policy where the validator found the issue.
448    pub fn policy_id(&self) -> &crate::PolicyId {
449        match self {
450            Self::UnrecognizedEntityType(e) => e.policy_id(),
451            Self::UnrecognizedActionId(e) => e.policy_id(),
452            Self::InvalidActionApplication(e) => e.policy_id(),
453            Self::UnexpectedType(e) => e.policy_id(),
454            Self::IncompatibleTypes(e) => e.policy_id(),
455            Self::UnsafeAttributeAccess(e) => e.policy_id(),
456            Self::UnsafeOptionalAttributeAccess(e) => e.policy_id(),
457            Self::UnsafeTagAccess(e) => e.policy_id(),
458            Self::NoTagsAllowed(e) => e.policy_id(),
459            Self::UndefinedFunction(e) => e.policy_id(),
460            Self::WrongNumberArguments(e) => e.policy_id(),
461            Self::FunctionArgumentValidation(e) => e.policy_id(),
462            Self::EmptySetForbidden(e) => e.policy_id(),
463            Self::NonLitExtConstructor(e) => e.policy_id(),
464            Self::HierarchyNotRespected(e) => e.policy_id(),
465            Self::InternalInvariantViolation(e) => e.policy_id(),
466            Self::EntityDerefLevelViolation(e) => e.policy_id(),
467            Self::InvalidEnumEntity(e) => e.policy_id(),
468        }
469    }
470}
471
472#[doc(hidden)]
473impl From<cedar_policy_validator::ValidationError> for ValidationError {
474    fn from(error: cedar_policy_validator::ValidationError) -> Self {
475        match error {
476            cedar_policy_validator::ValidationError::UnrecognizedEntityType(e) => {
477                Self::UnrecognizedEntityType(e.into())
478            }
479            cedar_policy_validator::ValidationError::UnrecognizedActionId(e) => {
480                Self::UnrecognizedActionId(e.into())
481            }
482            cedar_policy_validator::ValidationError::InvalidActionApplication(e) => {
483                Self::InvalidActionApplication(e.into())
484            }
485            cedar_policy_validator::ValidationError::UnexpectedType(e) => {
486                Self::UnexpectedType(e.into())
487            }
488            cedar_policy_validator::ValidationError::IncompatibleTypes(e) => {
489                Self::IncompatibleTypes(e.into())
490            }
491            cedar_policy_validator::ValidationError::UnsafeAttributeAccess(e) => {
492                Self::UnsafeAttributeAccess(e.into())
493            }
494            cedar_policy_validator::ValidationError::UnsafeOptionalAttributeAccess(e) => {
495                Self::UnsafeOptionalAttributeAccess(e.into())
496            }
497            cedar_policy_validator::ValidationError::UnsafeTagAccess(e) => {
498                Self::UnsafeTagAccess(e.into())
499            }
500            cedar_policy_validator::ValidationError::NoTagsAllowed(e) => {
501                Self::NoTagsAllowed(e.into())
502            }
503            cedar_policy_validator::ValidationError::UndefinedFunction(e) => {
504                Self::UndefinedFunction(e.into())
505            }
506            cedar_policy_validator::ValidationError::WrongNumberArguments(e) => {
507                Self::WrongNumberArguments(e.into())
508            }
509            cedar_policy_validator::ValidationError::FunctionArgumentValidation(e) => {
510                Self::FunctionArgumentValidation(e.into())
511            }
512            cedar_policy_validator::ValidationError::EmptySetForbidden(e) => {
513                Self::EmptySetForbidden(e.into())
514            }
515            cedar_policy_validator::ValidationError::NonLitExtConstructor(e) => {
516                Self::NonLitExtConstructor(e.into())
517            }
518            cedar_policy_validator::ValidationError::InternalInvariantViolation(e) => {
519                Self::InternalInvariantViolation(e.into())
520            }
521            cedar_policy_validator::ValidationError::InvalidEnumEntity(e) => {
522                Self::InvalidEnumEntity(e.into())
523            }
524            cedar_policy_validator::ValidationError::EntityDerefLevelViolation(e) => {
525                Self::EntityDerefLevelViolation(e.into())
526            }
527        }
528    }
529}
530
531/// Error subtypes for [`ValidationWarning`].
532///
533/// Validation warnings are primarily documented on their variants in [`ValidationWarning`].
534pub mod validation_warnings;
535
536/// Represents the different kinds of validation warnings and information
537/// specific to that warning.
538///
539/// Marked as `non_exhaustive` to allow adding additional warnings in the future
540/// as a non-breaking change.
541#[derive(Debug, Clone, Error, Diagnostic)]
542#[non_exhaustive]
543pub enum ValidationWarning {
544    /// A string contains a mix of characters for different scripts (e.g., latin
545    /// and cyrillic alphabets). Different scripts can contain visually similar
546    /// characters which may be confused for each other.
547    #[diagnostic(transparent)]
548    #[error(transparent)]
549    MixedScriptString(#[from] validation_warnings::MixedScriptString),
550    /// A string contains bidirectional text control characters. These can be used to create crafted pieces of code that obfuscate true control flow.
551    #[diagnostic(transparent)]
552    #[error(transparent)]
553    BidiCharsInString(#[from] validation_warnings::BidiCharsInString),
554    /// An id contains bidirectional text control characters. These can be used to create crafted pieces of code that obfuscate true control flow.
555    #[diagnostic(transparent)]
556    #[error(transparent)]
557    BidiCharsInIdentifier(#[from] validation_warnings::BidiCharsInIdentifier),
558    /// An id contains a mix of characters for different scripts (e.g., latin and
559    /// cyrillic alphabets). Different scripts can contain visually similar
560    /// characters which may be confused for each other.
561    #[diagnostic(transparent)]
562    #[error(transparent)]
563    MixedScriptIdentifier(#[from] validation_warnings::MixedScriptIdentifier),
564    /// An id contains characters that is not a [graphical ASCII character](https://doc.rust-lang.org/std/primitive.char.html#method.is_ascii_graphic),
565    /// not the space character (`U+0020`), and falls outside of the General
566    /// Security Profile for Identifiers. We recommend adhering to this if
567    /// possible. See [Unicode® Technical Standard #39](https://unicode.org/reports/tr39/#General_Security_Profile) for more information.
568    #[diagnostic(transparent)]
569    #[error(transparent)]
570    ConfusableIdentifier(#[from] validation_warnings::ConfusableIdentifier),
571    /// The typechecker found that a policy condition will always evaluate to false.
572    #[diagnostic(transparent)]
573    #[error(transparent)]
574    ImpossiblePolicy(#[from] validation_warnings::ImpossiblePolicy),
575}
576
577impl ValidationWarning {
578    /// Extract the policy id of the policy where the validator found the issue.
579    pub fn policy_id(&self) -> &PolicyId {
580        match self {
581            Self::MixedScriptString(w) => w.policy_id(),
582            Self::BidiCharsInString(w) => w.policy_id(),
583            Self::BidiCharsInIdentifier(w) => w.policy_id(),
584            Self::MixedScriptIdentifier(w) => w.policy_id(),
585            Self::ConfusableIdentifier(w) => w.policy_id(),
586            Self::ImpossiblePolicy(w) => w.policy_id(),
587        }
588    }
589}
590
591#[doc(hidden)]
592impl From<cedar_policy_validator::ValidationWarning> for ValidationWarning {
593    fn from(warning: cedar_policy_validator::ValidationWarning) -> Self {
594        match warning {
595            cedar_policy_validator::ValidationWarning::MixedScriptString(w) => {
596                Self::MixedScriptString(w.into())
597            }
598            cedar_policy_validator::ValidationWarning::BidiCharsInString(w) => {
599                Self::BidiCharsInString(w.into())
600            }
601            cedar_policy_validator::ValidationWarning::BidiCharsInIdentifier(w) => {
602                Self::BidiCharsInIdentifier(w.into())
603            }
604            cedar_policy_validator::ValidationWarning::MixedScriptIdentifier(w) => {
605                Self::MixedScriptIdentifier(w.into())
606            }
607            cedar_policy_validator::ValidationWarning::ConfusableIdentifier(w) => {
608                Self::ConfusableIdentifier(w.into())
609            }
610            cedar_policy_validator::ValidationWarning::ImpossiblePolicy(w) => {
611                Self::ImpossiblePolicy(w.into())
612            }
613        }
614    }
615}
616
617/// Error subtypes for [`PolicySetError`]
618pub mod policy_set_errors {
619    use super::Error;
620    use crate::PolicyId;
621    use cedar_policy_core::ast;
622    use miette::Diagnostic;
623
624    /// There was a duplicate [`PolicyId`] encountered in either the set of
625    /// templates or the set of policies.
626    #[derive(Debug, Diagnostic, Error)]
627    #[error("duplicate template or policy id `{id}`")]
628    pub struct AlreadyDefined {
629        pub(crate) id: PolicyId,
630    }
631
632    impl AlreadyDefined {
633        /// Get the [`PolicyId`] for which there was a duplicate
634        pub fn duplicate_id(&self) -> &PolicyId {
635            &self.id
636        }
637    }
638
639    /// Error when linking a template
640    #[derive(Debug, Diagnostic, Error)]
641    #[error("unable to link template")]
642    pub struct LinkingError {
643        #[from]
644        #[diagnostic(transparent)]
645        pub(crate) inner: ast::LinkingError,
646    }
647
648    /// Expected a static policy, but a template-linked policy was provided
649    #[derive(Debug, Diagnostic, Error)]
650    #[error("expected a static policy, but a template-linked policy was provided")]
651    pub struct ExpectedStatic {
652        /// A private field, just so the public interface notes this as a
653        /// private-fields struct and not a empty-fields struct for semver
654        /// purposes (e.g., consumers cannot construct this type with
655        /// `ExpectedStatic {}`)
656        _dummy: (),
657    }
658
659    impl ExpectedStatic {
660        pub(crate) fn new() -> Self {
661            Self { _dummy: () }
662        }
663    }
664
665    /// Expected a template, but a static policy was provided.
666    #[derive(Debug, Diagnostic, Error)]
667    #[error("expected a template, but a static policy was provided")]
668    pub struct ExpectedTemplate {
669        /// A private field, just so the public interface notes this as a
670        /// private-fields struct and not a empty-fields struct for semver
671        /// purposes (e.g., consumers cannot construct this type with
672        /// `ExpectedTemplate {}`)
673        _dummy: (),
674    }
675
676    impl ExpectedTemplate {
677        pub(crate) fn new() -> Self {
678            Self { _dummy: () }
679        }
680    }
681
682    /// Error when removing a static policy that doesn't exist
683    #[derive(Debug, Diagnostic, Error)]
684    #[error("unable to remove static policy `{policy_id}` because it does not exist")]
685    pub struct PolicyNonexistentError {
686        pub(crate) policy_id: PolicyId,
687    }
688
689    impl PolicyNonexistentError {
690        /// Get the [`PolicyId`] of the policy which didn't exist
691        pub fn policy_id(&self) -> &PolicyId {
692            &self.policy_id
693        }
694    }
695
696    /// Error when removing a template that doesn't exist
697    #[derive(Debug, Diagnostic, Error)]
698    #[error("unable to remove template `{template_id}` because it does not exist")]
699    pub struct TemplateNonexistentError {
700        pub(crate) template_id: PolicyId,
701    }
702
703    impl TemplateNonexistentError {
704        /// Get the [`PolicyId`] of the template which didn't exist
705        pub fn template_id(&self) -> &PolicyId {
706            &self.template_id
707        }
708    }
709
710    /// Error when removing a template with active links
711    #[derive(Debug, Diagnostic, Error)]
712    #[error("unable to remove policy template `{template_id}` because it has active links")]
713    pub struct RemoveTemplateWithActiveLinksError {
714        pub(crate) template_id: PolicyId,
715    }
716
717    impl RemoveTemplateWithActiveLinksError {
718        /// Get the [`PolicyId`] of the template which had active links
719        pub fn template_id(&self) -> &PolicyId {
720            &self.template_id
721        }
722    }
723
724    /// Error when removing a template that is not a template
725    #[derive(Debug, Diagnostic, Error)]
726    #[error("unable to remove policy template `{template_id}` because it is not a template")]
727    pub struct RemoveTemplateNotTemplateError {
728        pub(crate) template_id: PolicyId,
729    }
730
731    impl RemoveTemplateNotTemplateError {
732        /// Get the [`PolicyId`] of the template which is not a template
733        pub fn template_id(&self) -> &PolicyId {
734            &self.template_id
735        }
736    }
737
738    /// Error when unlinking a template-linked policy
739    #[derive(Debug, Diagnostic, Error)]
740    #[error("unable to unlink policy `{policy_id}` because it does not exist")]
741    pub struct LinkNonexistentError {
742        pub(crate) policy_id: PolicyId,
743    }
744
745    impl LinkNonexistentError {
746        /// Get the [`PolicyId`] of the link which does not exist
747        pub fn policy_id(&self) -> &PolicyId {
748            &self.policy_id
749        }
750    }
751
752    /// Error when removing a link that is not a link
753    #[derive(Debug, Diagnostic, Error)]
754    #[error("unable to unlink `{policy_id}` because it is not a link")]
755    pub struct UnlinkLinkNotLinkError {
756        pub(crate) policy_id: PolicyId,
757    }
758
759    impl UnlinkLinkNotLinkError {
760        /// Get the [`PolicyId`] of the link which is not a link
761        pub fn policy_id(&self) -> &PolicyId {
762            &self.policy_id
763        }
764    }
765
766    /// Error during JSON ser/de of the policy set (as opposed to individual policies)
767    #[derive(Debug, Diagnostic, Error)]
768    #[error("error serializing/deserializing policy set to/from JSON")]
769    pub struct JsonPolicySetError {
770        #[from]
771        pub(crate) inner: serde_json::Error,
772    }
773}
774
775/// Potential errors when adding to a `PolicySet`.
776#[derive(Debug, Diagnostic, Error)]
777#[non_exhaustive]
778pub enum PolicySetError {
779    /// There was a duplicate [`PolicyId`] encountered in either the set of
780    /// templates or the set of policies.
781    #[error(transparent)]
782    #[diagnostic(transparent)]
783    AlreadyDefined(#[from] policy_set_errors::AlreadyDefined),
784    /// Error when linking a template
785    #[error(transparent)]
786    #[diagnostic(transparent)]
787    Linking(#[from] policy_set_errors::LinkingError),
788    /// Expected a static policy, but a template-linked policy was provided
789    #[error(transparent)]
790    #[diagnostic(transparent)]
791    ExpectedStatic(#[from] policy_set_errors::ExpectedStatic),
792    /// Expected a template, but a static policy was provided.
793    #[error(transparent)]
794    #[diagnostic(transparent)]
795    ExpectedTemplate(#[from] policy_set_errors::ExpectedTemplate),
796    /// Error when removing a static policy that doesn't exist
797    #[error(transparent)]
798    #[diagnostic(transparent)]
799    PolicyNonexistent(#[from] policy_set_errors::PolicyNonexistentError),
800    /// Error when removing a template that doesn't exist
801    #[error(transparent)]
802    #[diagnostic(transparent)]
803    TemplateNonexistent(#[from] policy_set_errors::TemplateNonexistentError),
804    /// Error when removing a template with active links
805    #[error(transparent)]
806    #[diagnostic(transparent)]
807    RemoveTemplateWithActiveLinks(#[from] policy_set_errors::RemoveTemplateWithActiveLinksError),
808    /// Error when removing a template that is not a template
809    #[error(transparent)]
810    #[diagnostic(transparent)]
811    RemoveTemplateNotTemplate(#[from] policy_set_errors::RemoveTemplateNotTemplateError),
812    /// Error when unlinking a linked policy
813    #[error(transparent)]
814    #[diagnostic(transparent)]
815    LinkNonexistent(#[from] policy_set_errors::LinkNonexistentError),
816    /// Error when removing a link that is not a link
817    #[error(transparent)]
818    #[diagnostic(transparent)]
819    UnlinkLinkNotLink(#[from] policy_set_errors::UnlinkLinkNotLinkError),
820    /// Error when converting a policy/template from JSON format
821    #[error(transparent)]
822    #[diagnostic(transparent)]
823    FromJson(#[from] PolicyFromJsonError),
824    /// Error when converting a policy/template to JSON format
825    #[error("Error serializing a policy/template to JSON")]
826    #[diagnostic(transparent)]
827    ToJson(#[from] PolicyToJsonError),
828    /// Error during JSON ser/de of the policy set (as opposed to individual policies)
829    #[error(transparent)]
830    #[diagnostic(transparent)]
831    JsonPolicySet(#[from] policy_set_errors::JsonPolicySetError),
832}
833
834#[doc(hidden)]
835impl From<ast::PolicySetError> for PolicySetError {
836    fn from(e: ast::PolicySetError) -> Self {
837        match e {
838            ast::PolicySetError::Occupied { id } => {
839                Self::AlreadyDefined(policy_set_errors::AlreadyDefined {
840                    id: PolicyId::new(id),
841                })
842            }
843        }
844    }
845}
846
847#[doc(hidden)]
848impl From<ast::LinkingError> for PolicySetError {
849    fn from(e: ast::LinkingError) -> Self {
850        Self::Linking(e.into())
851    }
852}
853
854#[doc(hidden)]
855impl From<ast::UnexpectedSlotError> for PolicySetError {
856    fn from(_: ast::UnexpectedSlotError) -> Self {
857        Self::ExpectedStatic(policy_set_errors::ExpectedStatic::new())
858    }
859}
860
861#[doc(hidden)]
862impl From<est::PolicySetFromJsonError> for PolicySetError {
863    fn from(e: est::PolicySetFromJsonError) -> Self {
864        match e {
865            est::PolicySetFromJsonError::PolicySet(e) => e.into(),
866            est::PolicySetFromJsonError::Linking(e) => e.into(),
867            est::PolicySetFromJsonError::FromJsonError(e) => Self::FromJson(e.into()),
868        }
869    }
870}
871
872/// Represents one or more [`ParseError`]s encountered when parsing a policy or
873/// expression.
874///
875/// By default, the `Diagnostic` and `Error` implementations will only print the
876/// first error. If you want to see all errors, use `.iter()` or `.into_iter()`.
877#[derive(Debug, Diagnostic, Error)]
878#[error(transparent)]
879#[diagnostic(transparent)]
880pub struct ParseErrors(#[from] cedar_policy_core::parser::err::ParseErrors);
881
882impl ParseErrors {
883    /// Get every [`ParseError`] associated with this [`ParseErrors`] object.
884    /// The returned iterator is guaranteed to be nonempty.
885    pub fn iter(&self) -> impl Iterator<Item = &ParseError> {
886        self.0.iter().map(ParseError::ref_cast)
887    }
888}
889
890/// Errors that can occur when parsing policies or expressions.
891///
892/// Marked as `non_exhaustive` to support adding additional error information
893/// in the future without a major version bump.
894#[derive(Debug, Diagnostic, Error, RefCast)]
895#[repr(transparent)]
896#[error(transparent)]
897#[diagnostic(transparent)]
898#[non_exhaustive]
899pub struct ParseError {
900    #[from]
901    inner: cedar_policy_core::parser::err::ParseError,
902}
903
904/// Errors that can happen when getting the JSON representation of a policy
905#[derive(Debug, Diagnostic, Error)]
906pub enum PolicyToJsonError {
907    /// Parse error in the policy text
908    #[error(transparent)]
909    #[diagnostic(transparent)]
910    Parse(#[from] ParseErrors),
911    /// For linked policies, error linking the JSON representation
912    #[error(transparent)]
913    #[diagnostic(transparent)]
914    Link(#[from] policy_to_json_errors::JsonLinkError),
915    /// Error in the JSON serialization
916    #[error(transparent)]
917    JsonSerialization(#[from] policy_to_json_errors::PolicyJsonSerializationError),
918}
919
920#[doc(hidden)]
921impl From<est::LinkingError> for PolicyToJsonError {
922    fn from(e: est::LinkingError) -> Self {
923        policy_to_json_errors::JsonLinkError::from(e).into()
924    }
925}
926
927impl From<serde_json::Error> for PolicyToJsonError {
928    fn from(e: serde_json::Error) -> Self {
929        policy_to_json_errors::PolicyJsonSerializationError::from(e).into()
930    }
931}
932
933/// Error subtypes for [`PolicyToJsonError`]
934pub mod policy_to_json_errors {
935    use cedar_policy_core::est;
936    use miette::Diagnostic;
937    use thiserror::Error;
938
939    /// Error linking the JSON representation of a linked policy
940    #[derive(Debug, Diagnostic, Error)]
941    #[error(transparent)]
942    #[diagnostic(transparent)]
943    pub struct JsonLinkError {
944        /// Underlying error
945        #[from]
946        err: est::LinkingError,
947    }
948
949    /// Error serializing a policy as JSON
950    #[derive(Debug, Diagnostic, Error)]
951    #[error(transparent)]
952    pub struct PolicyJsonSerializationError {
953        /// Underlying error
954        #[from]
955        err: serde_json::Error,
956    }
957}
958
959/// Error when converting a policy or template from JSON format
960#[derive(Debug, Diagnostic, Error)]
961#[error("error deserializing a policy/template from JSON")]
962#[diagnostic(transparent)]
963pub struct PolicyFromJsonError {
964    #[from]
965    pub(crate) inner: cedar_policy_core::est::FromJsonError,
966}
967
968/// Error type for parsing `Context` from JSON
969#[derive(Debug, Diagnostic, Error)]
970pub enum ContextJsonError {
971    /// Error deserializing the JSON into a [`crate::Context`]
972    #[error(transparent)]
973    #[diagnostic(transparent)]
974    JsonDeserialization(#[from] entities_json_errors::JsonDeserializationError),
975    /// Error constructing the [`crate::Context`] itself
976    #[error(transparent)]
977    #[diagnostic(transparent)]
978    ContextCreation(#[from] ContextCreationError),
979    /// The supplied action doesn't exist in the supplied schema
980    #[error(transparent)]
981    #[diagnostic(transparent)]
982    MissingAction(#[from] context_json_errors::MissingActionError),
983}
984
985impl ContextJsonError {
986    /// Construct a `ContextJsonError::MissingAction`
987    pub(crate) fn missing_action(action: EntityUid) -> Self {
988        Self::MissingAction(context_json_errors::MissingActionError { action })
989    }
990}
991
992#[doc(hidden)]
993impl From<cedar_policy_core::entities::json::ContextJsonDeserializationError> for ContextJsonError {
994    fn from(e: cedar_policy_core::entities::json::ContextJsonDeserializationError) -> Self {
995        match e {
996            cedar_policy_core::entities::json::ContextJsonDeserializationError::JsonDeserialization(e) => Self::JsonDeserialization(e),
997            cedar_policy_core::entities::json::ContextJsonDeserializationError::ContextCreation(e) => Self::ContextCreation(e.into())
998        }
999    }
1000}
1001
1002/// Error subtypes for [`ContextJsonError`]
1003pub mod context_json_errors {
1004    use super::EntityUid;
1005    use miette::Diagnostic;
1006    use thiserror::Error;
1007
1008    /// The supplied action doesn't exist in the supplied schema
1009    #[derive(Debug, Diagnostic, Error)]
1010    #[error("action `{action}` does not exist in the supplied schema")]
1011    pub struct MissingActionError {
1012        /// UID of the action which doesn't exist
1013        pub(super) action: EntityUid,
1014    }
1015
1016    impl MissingActionError {
1017        /// Get the [`EntityUid`] of the action which doesn't exist
1018        pub fn action(&self) -> &EntityUid {
1019            &self.action
1020        }
1021    }
1022}
1023
1024/// Error type for parsing a `RestrictedExpression`
1025#[derive(Debug, Diagnostic, Error)]
1026#[non_exhaustive]
1027pub enum RestrictedExpressionParseError {
1028    /// Failed to parse the expression
1029    #[error(transparent)]
1030    #[diagnostic(transparent)]
1031    Parse(#[from] ParseErrors),
1032    /// Parsed successfully as an expression, but failed to construct a
1033    /// restricted expression, for the reason indicated in the underlying error
1034    #[error(transparent)]
1035    #[diagnostic(transparent)]
1036    InvalidRestrictedExpression(#[from] RestrictedExpressionError),
1037}
1038
1039#[doc(hidden)]
1040impl From<cedar_policy_core::ast::RestrictedExpressionParseError>
1041    for RestrictedExpressionParseError
1042{
1043    fn from(e: cedar_policy_core::ast::RestrictedExpressionParseError) -> Self {
1044        match e {
1045            cedar_policy_core::ast::RestrictedExpressionParseError::Parse(e) => {
1046                Self::Parse(e.into())
1047            }
1048            cedar_policy_core::ast::RestrictedExpressionParseError::InvalidRestrictedExpression(
1049                e,
1050            ) => e.into(),
1051        }
1052    }
1053}
1054
1055/// The request does not conform to the schema
1056#[derive(Debug, Diagnostic, Error)]
1057#[non_exhaustive]
1058pub enum RequestValidationError {
1059    /// Request action is not declared in the schema
1060    #[error(transparent)]
1061    #[diagnostic(transparent)]
1062    UndeclaredAction(#[from] request_validation_errors::UndeclaredActionError),
1063    /// Request principal is of a type not declared in the schema
1064    #[error(transparent)]
1065    #[diagnostic(transparent)]
1066    UndeclaredPrincipalType(#[from] request_validation_errors::UndeclaredPrincipalTypeError),
1067    /// Request resource is of a type not declared in the schema
1068    #[error(transparent)]
1069    #[diagnostic(transparent)]
1070    UndeclaredResourceType(#[from] request_validation_errors::UndeclaredResourceTypeError),
1071    /// Request principal is of a type that is declared in the schema, but is
1072    /// not valid for the request action
1073    #[error(transparent)]
1074    #[diagnostic(transparent)]
1075    InvalidPrincipalType(#[from] request_validation_errors::InvalidPrincipalTypeError),
1076    /// Request resource is of a type that is declared in the schema, but is
1077    /// not valid for the request action
1078    #[error(transparent)]
1079    #[diagnostic(transparent)]
1080    InvalidResourceType(#[from] request_validation_errors::InvalidResourceTypeError),
1081    /// Context does not comply with the shape specified for the request action
1082    #[error(transparent)]
1083    #[diagnostic(transparent)]
1084    InvalidContext(#[from] request_validation_errors::InvalidContextError),
1085    /// Error computing the type of the `Context`
1086    #[error(transparent)]
1087    #[diagnostic(transparent)]
1088    TypeOfContext(#[from] request_validation_errors::TypeOfContextError),
1089    /// Error when a principal or resource entity is of an enumerated entity
1090    /// type but has an invalid EID
1091    #[error(transparent)]
1092    #[diagnostic(transparent)]
1093    InvalidEnumEntity(#[from] request_validation_errors::InvalidEnumEntityError),
1094}
1095
1096#[doc(hidden)]
1097impl From<cedar_policy_validator::RequestValidationError> for RequestValidationError {
1098    fn from(e: cedar_policy_validator::RequestValidationError) -> Self {
1099        match e {
1100            cedar_policy_validator::RequestValidationError::UndeclaredAction(e) => {
1101                Self::UndeclaredAction(e.into())
1102            }
1103            cedar_policy_validator::RequestValidationError::UndeclaredPrincipalType(e) => {
1104                Self::UndeclaredPrincipalType(e.into())
1105            }
1106            cedar_policy_validator::RequestValidationError::UndeclaredResourceType(e) => {
1107                Self::UndeclaredResourceType(e.into())
1108            }
1109            cedar_policy_validator::RequestValidationError::InvalidPrincipalType(e) => {
1110                Self::InvalidPrincipalType(e.into())
1111            }
1112            cedar_policy_validator::RequestValidationError::InvalidResourceType(e) => {
1113                Self::InvalidResourceType(e.into())
1114            }
1115            cedar_policy_validator::RequestValidationError::InvalidContext(e) => {
1116                Self::InvalidContext(e.into())
1117            }
1118            cedar_policy_validator::RequestValidationError::TypeOfContext(e) => {
1119                Self::TypeOfContext(e.into())
1120            }
1121            cedar_policy_validator::RequestValidationError::InvalidEnumEntity(e) => {
1122                Self::InvalidEnumEntity(e.into())
1123            }
1124        }
1125    }
1126}
1127
1128/// Error subtypes for [`RequestValidationError`]
1129pub mod request_validation_errors {
1130    use cedar_policy_core::extensions::ExtensionFunctionLookupError;
1131    use miette::Diagnostic;
1132    use ref_cast::RefCast;
1133    use thiserror::Error;
1134
1135    use crate::{Context, EntityTypeName, EntityUid};
1136
1137    /// Request action is not declared in the schema
1138    #[derive(Debug, Diagnostic, Error)]
1139    #[error(transparent)]
1140    #[diagnostic(transparent)]
1141    pub struct UndeclaredActionError(
1142        #[from] cedar_policy_validator::request_validation_errors::UndeclaredActionError,
1143    );
1144
1145    impl UndeclaredActionError {
1146        /// The action which was not declared in the schema
1147        pub fn action(&self) -> &EntityUid {
1148            RefCast::ref_cast(self.0.action())
1149        }
1150    }
1151
1152    /// Request principal is of a type not declared in the schema
1153    #[derive(Debug, Diagnostic, Error)]
1154    #[error(transparent)]
1155    #[diagnostic(transparent)]
1156    pub struct UndeclaredPrincipalTypeError(
1157        #[from] cedar_policy_validator::request_validation_errors::UndeclaredPrincipalTypeError,
1158    );
1159
1160    impl UndeclaredPrincipalTypeError {
1161        /// The principal type which was not declared in the schema
1162        pub fn principal_ty(&self) -> &EntityTypeName {
1163            RefCast::ref_cast(self.0.principal_ty())
1164        }
1165    }
1166
1167    /// Request resource is of a type not declared in the schema
1168    #[derive(Debug, Diagnostic, Error)]
1169    #[error(transparent)]
1170    #[diagnostic(transparent)]
1171    pub struct UndeclaredResourceTypeError(
1172        #[from] cedar_policy_validator::request_validation_errors::UndeclaredResourceTypeError,
1173    );
1174
1175    impl UndeclaredResourceTypeError {
1176        /// The resource type which was not declared in the schema
1177        pub fn resource_ty(&self) -> &EntityTypeName {
1178            RefCast::ref_cast(self.0.resource_ty())
1179        }
1180    }
1181
1182    /// Request principal is of a type that is declared in the schema, but is
1183    /// not valid for the request action
1184    #[derive(Debug, Diagnostic, Error)]
1185    #[error(transparent)]
1186    #[diagnostic(transparent)]
1187    pub struct InvalidPrincipalTypeError(
1188        #[from] cedar_policy_validator::request_validation_errors::InvalidPrincipalTypeError,
1189    );
1190
1191    impl InvalidPrincipalTypeError {
1192        /// The principal type which is not valid
1193        pub fn principal_ty(&self) -> &EntityTypeName {
1194            RefCast::ref_cast(self.0.principal_ty())
1195        }
1196
1197        /// The action which it is not valid for
1198        pub fn action(&self) -> &EntityUid {
1199            RefCast::ref_cast(self.0.action())
1200        }
1201    }
1202
1203    /// Request resource is of a type that is declared in the schema, but is
1204    /// not valid for the request action
1205    #[derive(Debug, Diagnostic, Error)]
1206    #[error(transparent)]
1207    #[diagnostic(transparent)]
1208    pub struct InvalidResourceTypeError(
1209        #[from] cedar_policy_validator::request_validation_errors::InvalidResourceTypeError,
1210    );
1211
1212    impl InvalidResourceTypeError {
1213        /// The resource type which is not valid
1214        pub fn resource_ty(&self) -> &EntityTypeName {
1215            RefCast::ref_cast(self.0.resource_ty())
1216        }
1217
1218        /// The action which it is not valid for
1219        pub fn action(&self) -> &EntityUid {
1220            RefCast::ref_cast(self.0.action())
1221        }
1222    }
1223
1224    /// Context does not comply with the shape specified for the request action
1225    #[derive(Debug, Diagnostic, Error)]
1226    #[error(transparent)]
1227    #[diagnostic(transparent)]
1228    pub struct InvalidContextError(
1229        #[from] cedar_policy_validator::request_validation_errors::InvalidContextError,
1230    );
1231
1232    impl InvalidContextError {
1233        /// The context which is not valid
1234        pub fn context(&self) -> &Context {
1235            RefCast::ref_cast(self.0.context())
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    /// Error computing the type of the `Context`
1245    #[derive(Debug, Diagnostic, Error)]
1246    #[error(transparent)]
1247    #[diagnostic(transparent)]
1248    pub struct TypeOfContextError(#[from] ExtensionFunctionLookupError);
1249
1250    /// Error when a principal or resource entity is of an enumerated entity
1251    /// type but has an invalid EID
1252    #[derive(Debug, Diagnostic, Error)]
1253    #[error(transparent)]
1254    #[diagnostic(transparent)]
1255    pub struct InvalidEnumEntityError(
1256        #[from] cedar_policy_core::entities::conformance::err::InvalidEnumEntityError,
1257    );
1258}
1259
1260/// An error generated by entity slicing.
1261#[derive(Debug, Error, Diagnostic)]
1262#[non_exhaustive]
1263#[cfg(feature = "entity-manifest")]
1264pub enum EntityManifestError {
1265    /// A validation error was encountered
1266    #[error(transparent)]
1267    #[diagnostic(transparent)]
1268    Validation(#[from] ValidationResult),
1269    /// A entities error was encountered
1270    #[error(transparent)]
1271    #[diagnostic(transparent)]
1272    Entities(#[from] EntitiesError),
1273
1274    /// The request was partial
1275    #[error(transparent)]
1276    #[diagnostic(transparent)]
1277    PartialRequest(#[from] PartialRequestError),
1278    /// A policy was partial
1279    #[error(transparent)]
1280    #[diagnostic(transparent)]
1281    PartialExpression(#[from] PartialExpressionError),
1282    /// Encounters unsupported Cedar feature
1283    #[error(transparent)]
1284    #[diagnostic(transparent)]
1285    UnsupportedCedarFeature(#[from] UnsupportedCedarFeatureError),
1286}
1287
1288#[cfg(feature = "entity-manifest")]
1289impl From<entity_manifest::EntityManifestError> for EntityManifestError {
1290    fn from(e: entity_manifest::EntityManifestError) -> Self {
1291        match e {
1292            entity_manifest::EntityManifestError::Validation(e) => Self::Validation(e.into()),
1293            entity_manifest::EntityManifestError::Entities(e) => Self::Entities(e),
1294            entity_manifest::EntityManifestError::PartialRequest(e) => Self::PartialRequest(e),
1295            entity_manifest::EntityManifestError::PartialExpression(e) => {
1296                Self::PartialExpression(e)
1297            }
1298            entity_manifest::EntityManifestError::UnsupportedCedarFeature(e) => {
1299                Self::UnsupportedCedarFeature(e)
1300            }
1301        }
1302    }
1303}