NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Sentinel for Laravel

Exceptions, statuses and enums

Every exception extends RoundlyConsulting\Sentinel\Exceptions\SentinelException (a RuntimeException), except the HTTP-facing ones, which extend Symfony’s HttpException and render RFC 9457 problem details. Messages are developer-facing English (HTTP messages are translated) and never contain key material or sealed values.

ExceptionWhen
InvalidSealDefinitionExceptionA seal definition does not compile — problems() lists every problem.
SealingMisconfiguredExceptionWiring errors, fail closed: notSealable, unknownSeal (lists the declared seals), unknownRing, saveOverridden, writeOutsideSealedPath, middlewareParameter, bindingsNotSubstituted, queryModelMismatch, missingColumn, unknownModel, invalidColumn, middlewareOption, whereNeedsOneModel.
CanonicalizationExceptionA value cannot be canonicalized — field() and reason() name the field and rule, never the value.
NoSigningKeyExceptionNo active key with private material in the ring; the message names the ring’s key variables and, in testing, points at WithSentinelKeys or Sentinel::fake().
UnknownKeyExceptionA kid unknown in that ring (also a kid of another ring).
KeyIntegrityExceptionA database key row disagrees with its envelope.
InvalidKeyMaterialExceptionKey material refused (encoding, length, weak secret, curve mismatch, private material on a verify-only import, …).
AlgorithmNotAllowedExceptionAn algorithm outside an allow-list.
KeyDriverExceptionKey lifecycle refusals: readOnly, notStoredInDatabase, keyIdTaken, reasonRequired, invalidKeyId, invalidLabel.
ConcurrentSealExceptionA lost race (the write rolls back).
SealingFailedExceptionSealing an unsaved model / a row gone during sealing.
TamperedModelExceptionverifyOrFail(), a refused write, a refused mass update — result() / results().
SealingSuspensionNotAllowedExceptionwithoutSealing() with allow_suspension off.
AcknowledgementDeniedExceptionAcknowledgement / unseal / baseline refused: reason, reasonTooLong, actorRequired, unauthorized.
LedgerIsAppendOnlyExceptionAn Eloquent update or delete of a ledger entry or checkpoint.
LedgerIntegrityExceptionLedgerReport::throwIfViolated() — findings() returns the violations.
InvalidSentinelConfigurationExceptionInvalid configuration, thrown at first use and never replaced by a default — the message names the key (for a boolean, also the value given).
InvalidPurposeExceptionA nonce purpose outside the alphabet.
IdempotentResultExceptionidempotency()->run() returned something not storable as JSON — the callback ran, its key is completed as unreplayable.

HTTP exceptions

ExceptionStatuscode
Http\Exceptions\SealVerificationFailedHttpExceptionmiddleware.verified_status (409)— (generic message)
IdempotencyKeyMissingException400idempotency_key_missing
InvalidIdempotencyKeyException400invalid_idempotency_key
IdempotencyKeyReusedException422idempotency_key_reused
IdempotencyRequestInProgressException409 + Retry-Afteridempotency_request_in_progress
IdempotentResponseUnavailableException409idempotent_response_unavailable
NonceRejectedException403nonce_rejected
HttpSignatureException401 (+ Accept-Signature)signature_rejected

Problem bodies carry type (when configured), title, status, detail and code, with Content-Type: application/problem+json; type is problems.type_base#code, and title and detail are translated. The idempotency family shares the abstract IdempotencyException — rejection() returns the IdempotencyRejection, retryAfterSeconds() the Retry-After value — and HttpSignatureException has reason() and keyId().

Verification statuses

VerificationStatus values are frozen; case names are the studly forms of the values. isIntact() and isFailure() apply the same rule as VerificationResult::isIntact(), and translated labels ship in sentinel::statuses:

CaseValueIntact?
Intactintactyes
Outdatedoutdatedyes, unless verification.outdated_is_intact is off
Unsealedunsealedyes (lenient seals)
Tamperedtamperedno
Missingmissingno
Stalestaleno
UnknownKeyunknown_keyno
RevokedKeyrevoked_keyno
RetiredKeyretired_keyno
AlgorithmNotAllowedalgorithm_not_allowedno
AlgorithmMismatchalgorithm_mismatchno
Malformedmalformedno
Unverifiableunverifiableno

Reasons: mac, computed, canonicalization, ledger_entry (tampered); seal_deleted, never_sealed, unsealed (missing); newer_version, not_in_ledger, ledger_mismatch, entity_recreated (stale); ring_not_accepted, not_found, pending, integrity (unknown key); missing_attribute, missing_computed, error (unverifiable).

Enums

All live in RoundlyConsulting\Sentinel\Enums, are frozen, and use the enums-for-laravel helpers (values(), names(), labels(), options(), fromName(), tryFromName(), label(), is(), isIn(), …). Changing a value is a major release:

EnumCasesHelpers
AlgorithmHmacSha256, HmacSha384, HmacSha512, Ed25519, EcdsaP256Sha256, EcdsaP384Sha384isHmac(), isAsymmetric(), isHttpRegistered(), hashName(), hashLength(), hashAlgorithm(), cryptoAlgorithm()
KeyStatusPending, Active, VerifyOnly, Retired, RevokedcanSign(), canVerify()
KeyDestinationConfig, Database—
SealEventSealed, Resealed, Acknowledged, Baseline, Rotated, Deleted, UnsealedisTombstone()
VerificationContextApi, Middleware, Retrieve, Command, Rule, Collection, Write—
ReactionThrow, Report—
TamperedWritePolicyRefuse, Reseal, Skip—
LedgerFindingKindCheckpointGap, CheckpointInvalid, CheckpointMismatch, ChainBroken, AnchorAhead, AnchorMismatch, AnchorInvalid, AnchorUnreachable, EntryInvalid, OrphanEntry, EntityDeleted, SealRolledBack, SealMissing, BacklogisViolation()
IdempotencyRejectionMissing, Invalid, Reused, InProgress, Unavailablestatus()
IdempotencyOutcomeProceed, Replay, InProgress, Reused, Unavailable—
SignatureRejectionMissing, Malformed, Ambiguous, MissingParameter, MissingComponent, UnsupportedComponent, UnsupportedAlgorithm, UnknownKey, RevokedKey, AlgorithmMismatch, AlgorithmNotAllowed, TagMismatch, NotYetValid, TooOld, Expired, DigestMismatch, UnsupportedDigest, InvalidSignature, Replayed—
DigestAlgorithmSha256, Sha512hashAlgorithm()
HealthStatusOk, Warning, Failure—
NonceKindIssued, Seen—
PersistOperationSave, Delete, Increment—
TypeKindAuto, String, Integer, Decimal, Float, Boolean, DateTime, Date, Json, Binary, Null, PlaintexthasScale(), isDeclarable()

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.