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.
| Exception | When |
|---|---|
InvalidSealDefinitionException | A seal definition does not compile — problems() lists every problem. |
SealingMisconfiguredException | Wiring errors, fail closed: notSealable, unknownSeal (lists the declared seals), unknownRing, saveOverridden, writeOutsideSealedPath, middlewareParameter, bindingsNotSubstituted, queryModelMismatch, missingColumn, unknownModel, invalidColumn, middlewareOption, whereNeedsOneModel. |
CanonicalizationException | A value cannot be canonicalized — field() and reason() name the field and rule, never the value. |
NoSigningKeyException | No 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(). |
UnknownKeyException | A kid unknown in that ring (also a kid of another ring). |
KeyIntegrityException | A database key row disagrees with its envelope. |
InvalidKeyMaterialException | Key material refused (encoding, length, weak secret, curve mismatch, private material on a verify-only import, …). |
AlgorithmNotAllowedException | An algorithm outside an allow-list. |
KeyDriverException | Key lifecycle refusals: readOnly, notStoredInDatabase, keyIdTaken, reasonRequired, invalidKeyId, invalidLabel. |
ConcurrentSealException | A lost race (the write rolls back). |
SealingFailedException | Sealing an unsaved model / a row gone during sealing. |
TamperedModelException | verifyOrFail(), a refused write, a refused mass update — result() / results(). |
SealingSuspensionNotAllowedException | withoutSealing() with allow_suspension off. |
AcknowledgementDeniedException | Acknowledgement / unseal / baseline refused: reason, reasonTooLong, actorRequired, unauthorized. |
LedgerIsAppendOnlyException | An Eloquent update or delete of a ledger entry or checkpoint. |
LedgerIntegrityException | LedgerReport::throwIfViolated() — findings() returns the violations. |
InvalidSentinelConfigurationException | Invalid configuration, thrown at first use and never replaced by a default — the message names the key (for a boolean, also the value given). |
InvalidPurposeException | A nonce purpose outside the alphabet. |
IdempotentResultException | idempotency()->run() returned something not storable as JSON — the callback ran, its key is completed as unreplayable. |
HTTP exceptions
| Exception | Status | code |
|---|---|---|
Http\Exceptions\SealVerificationFailedHttpException | middleware.verified_status (409) | — (generic message) |
IdempotencyKeyMissingException | 400 | idempotency_key_missing |
InvalidIdempotencyKeyException | 400 | invalid_idempotency_key |
IdempotencyKeyReusedException | 422 | idempotency_key_reused |
IdempotencyRequestInProgressException | 409 + Retry-After | idempotency_request_in_progress |
IdempotentResponseUnavailableException | 409 | idempotent_response_unavailable |
NonceRejectedException | 403 | nonce_rejected |
HttpSignatureException | 401 (+ 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:
| Case | Value | Intact? |
|---|---|---|
Intact | intact | yes |
Outdated | outdated | yes, unless verification.outdated_is_intact is off |
Unsealed | unsealed | yes (lenient seals) |
Tampered | tampered | no |
Missing | missing | no |
Stale | stale | no |
UnknownKey | unknown_key | no |
RevokedKey | revoked_key | no |
RetiredKey | retired_key | no |
AlgorithmNotAllowed | algorithm_not_allowed | no |
AlgorithmMismatch | algorithm_mismatch | no |
Malformed | malformed | no |
Unverifiable | unverifiable | no |
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:
| Enum | Cases | Helpers |
|---|---|---|
Algorithm | HmacSha256, HmacSha384, HmacSha512, Ed25519, EcdsaP256Sha256, EcdsaP384Sha384 | isHmac(), isAsymmetric(), isHttpRegistered(), hashName(), hashLength(), hashAlgorithm(), cryptoAlgorithm() |
KeyStatus | Pending, Active, VerifyOnly, Retired, Revoked | canSign(), canVerify() |
KeyDestination | Config, Database | — |
SealEvent | Sealed, Resealed, Acknowledged, Baseline, Rotated, Deleted, Unsealed | isTombstone() |
VerificationContext | Api, Middleware, Retrieve, Command, Rule, Collection, Write | — |
Reaction | Throw, Report | — |
TamperedWritePolicy | Refuse, Reseal, Skip | — |
LedgerFindingKind | CheckpointGap, CheckpointInvalid, CheckpointMismatch, ChainBroken, AnchorAhead, AnchorMismatch, AnchorInvalid, AnchorUnreachable, EntryInvalid, OrphanEntry, EntityDeleted, SealRolledBack, SealMissing, Backlog | isViolation() |
IdempotencyRejection | Missing, Invalid, Reused, InProgress, Unavailable | status() |
IdempotencyOutcome | Proceed, Replay, InProgress, Reused, Unavailable | — |
SignatureRejection | Missing, Malformed, Ambiguous, MissingParameter, MissingComponent, UnsupportedComponent, UnsupportedAlgorithm, UnknownKey, RevokedKey, AlgorithmMismatch, AlgorithmNotAllowed, TagMismatch, NotYetValid, TooOld, Expired, DigestMismatch, UnsupportedDigest, InvalidSignature, Replayed | — |
DigestAlgorithm | Sha256, Sha512 | hashAlgorithm() |
HealthStatus | Ok, Warning, Failure | — |
NonceKind | Issued, Seen | — |
PersistOperation | Save, Delete, Increment | — |
TypeKind | Auto, String, Integer, Decimal, Float, Boolean, DateTime, Date, Json, Binary, Null, Plaintext | hasScale(), 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 cryptoBy 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.