Skip to content

Schema API

Reference for Warrant\Schema\WarrantSchema and the attributes and context objects that go with it. Conceptual coverage is in Schemas and Conditions.

public const model = ''; // class-string of the managed Model; '' = capability schema
public const schemaKey = null; // explicit key override; null = derive from model table
public static function userHasAbilities(
string|array $abilities,
Model|string|null $target = null,
?Authenticatable $user = null,
AbilityMatchMode $matchMode = AbilityMatchMode::ALL,
array $context = [],
): bool;
public static function getUserAbilities(
Model|string|null $target = null,
?Authenticatable $user = null,
array $context = [],
): array;
public static function authorize(
string|array $abilities,
Model|string|null $target = null,
?Authenticatable $user = null,
AbilityMatchMode $matchMode = AbilityMatchMode::ALL,
array $context = [],
): void;
public static function getNoTargetAbilitiesBag(?Authenticatable $user = null): array;
  • $user defaults to auth()->user(); both throw InvalidArgumentException if no user is available.
  • $target may be a Model (its getKey() is used) or a scalar id. null uses the no-target path.
  • authorize() mirrors userHasAbilities() but returns void and throws WarrantAuthorizationException (HTTP 403) on denial. See Denial messages.
public static function schemaKey(): string; // const or (new model)->getTable()
public static function declaredAbilities(): array; // declaration order (NOT sorted)
public static function conditionKeys(): array; // sorted
public static function targetedConditionKeys(): array; // sorted
public static function noTargetConditionKeys(): array; // sorted
public static function declaredContextKeys(): array; // declaration order
public static function requiredContextKeys(): array;
protected function implicitRules(): array; // default []; merged into every rule set
protected function defaultContext(): array; // default []; merged UNDER explicit context

Schema-level fallbacks that supply a message when authorize() denies and the responsible rule carried no withDenialMessage(). Override in your schema; each returns string|Throwable|null (return null to fall through). See Denial messages.

protected function forbiddenDenialMessage(WarrantDenialContext $c): string|Throwable|null; // a matching `cannot` denied, but carried no message
protected function ungrantedDenialMessage(WarrantUngrantedContext $c): string|Throwable|null; // nothing granted the ability

Message-source precedence (first non-null wins): (1) the matching cannot rule’s withDenialMessage(); (2) forbiddenDenialMessage(); (3) ungrantedDenialMessage(); (4) a generic 403.

Structural analysis of the resolved rule set — evaluates no conditions, runs no SQL, takes no context:. See Checking API for full signatures and Reachability for concepts.

public static function abilityReachability(string $ability, ?Authenticatable $user = null): Reachability;
public static function userCouldEverHave(string|array $abilities, ?Authenticatable $user = null, AbilityMatchMode $matchMode = AbilityMatchMode::ALL): bool;
public static function userAlwaysHas(string|array $abilities, ?Authenticatable $user = null, AbilityMatchMode $matchMode = AbilityMatchMode::ALL): bool;
public static function userNeverHas(string|array $abilities, ?Authenticatable $user = null, AbilityMatchMode $matchMode = AbilityMatchMode::ALL): bool;
public static function getUserPossibleAbilities(?Authenticatable $user = null): array;
public static function getUserGuaranteedAbilities(?Authenticatable $user = null): array;
public static function getUserImpossibleAbilities(?Authenticatable $user = null): array;

Marks a class constant as an ability. No arguments. The constant’s value is the ability name; its name is ignored (discovery is by attribute).

#[Ability] public const VIEW = 'view';

Mark a public method as a condition. Optional key overrides the snake-cased method name; passing '' throws.

#[TargetedCondition] // key = snake_case(method)
#[TargetedCondition('is_owner')] // explicit key
#[GlobalCondition]

The method must accept exactly one parameter, typed to match: TargetedConditionContext or GlobalConditionContext.

Marks a class constant as a check-time context key. required defaults to true. The constant’s value is the key string.

#[ContextKey] public const WORKSPACE = 'workspace_id';
#[ContextKey(required: false)] public const AS_OF = 'as_of_date';
public function __construct(
public Authenticatable $user,
public Builder $query, // Illuminate query builder
public array $arguments = [],
public array $context = [],
);

Same as above, plus targetSqlId (always present for a targeted condition):

public function __construct(
public Authenticatable $user,
public Builder $query,
public string $targetSqlId, // e.g. "documents.id"
public array $arguments = [],
public array $context = [],
);
AbilityMatchMode::ANY; // 'any' — any one ability is enough
AbilityMatchMode::ALL; // 'all' — every listed ability required

Pure enum (not backed) returned by the reachability API.

Reachability::NEVER; // no rule shape can ever grant it
Reachability::MAYBE; // grantable, but subject to conditions at check time
Reachability::ALWAYS; // granted by the rules' shape (NOT a per-row guarantee)

Decision per ability, top to bottom: (1) an unconditional cannotNEVER; (2) no can rule lists it → NEVER; (3) an unconditional can and no conditional cannotALWAYS; (4) otherwise → MAYBE. A conditional cannot is intentionally ignored — ALWAYS means “granted by the rules’ shape”, not a guarantee for every row.

StandardAbilities::VIEW; // 'view'
StandardAbilities::CREATE; // 'create'
StandardAbilities::UPDATE; // 'update'
StandardAbilities::DELETE; // 'delete'
StandardAbilities::ARCHIVE; // 'archive'
StandardAbilities::CREATE_VIEW_UPDATE_DELETE; // ['create','view','update','delete']

manage is intentionally not here — see Middleware.

The Warrant facade exposes the schema registry:

Warrant::getSchemaForModelClass(string $modelClass): string;
Warrant::getSchemaForKey(string $schemaKey): string;
Warrant::resolveSchemaKey(Model|WarrantSchema|string $schema): string;
Warrant::getNoTargetAbilitiesBag(?Authenticatable $user = null, string ...$schemaClassesOrKeys): array;
Warrant::registeredSchemas(): array;

It also proxies the reachability statics; the first argument is a schema key or a schema/model class:

Warrant::abilityReachability(string $schema, string $ability, ?Authenticatable $user = null): Reachability;
Warrant::userCouldEverHave(string $schema, string|array $abilities, ?Authenticatable $user = null, AbilityMatchMode $matchMode = AbilityMatchMode::ALL): bool;
Warrant::userAlwaysHas(string $schema, string|array $abilities, ?Authenticatable $user = null, AbilityMatchMode $matchMode = AbilityMatchMode::ALL): bool;
Warrant::userNeverHas(string $schema, string|array $abilities, ?Authenticatable $user = null, AbilityMatchMode $matchMode = AbilityMatchMode::ALL): bool;
// e.g. Warrant::userCouldEverHave('documents', 'update', $user)

Unknown model/key lookups throw OutOfBoundsException.