NAME

Punk::Authorisation - may this user act on this row

SYNOPSIS

# lib/Shop.pm
auth model => 'User', rank => [qw(member admin owner)], roles => sub { ... };
plugin 'Authorisation';                       # rules: Shop::Authorisation

# lib/Shop/Authorisation.pm
package Shop::Authorisation;
use Punk::Plugin::Authorisation;              # installs `rule`

rule 'doc.edit' => sub {
    my ($c, $doc) = @_;
    return 1 if $doc->{owner_id} == $c->auth_id;
    return $c->forbidden if $c->rank_at_least('admin');
    return $c->not_yours;
};
1;

# in a controller
my $doc = $c->model('Doc')->get(id => $c->param('id'));
$c->may('doc.edit', $doc) or return $c->deny;

DESCRIPTION

auth_guard answers may this user reach this route. An API key's scope answers may this credential call this operation. Neither can answer may this user act on this row, and that is where the commonest authorisation bug in a web application lives: the controller that loads a row by an id from the request and forgets to ask whose it is.

This distribution is the asking. The rules are the application's and live in one package it owns; what lives here is the machinery around them - collecting them, refusing to guess at a name nobody defined, and turning a refusal into the right status, which is a 404 rather than a 403 whenever a 403 would confirm that somebody else's row exists.

Two modules and a table:

Punk::Plugin::Authorisation

The plugin. Its options, its helpers, and what each refusal means. This is the one to read.

Punk::Model::Grant

The grants table, for what one user hands another. Off unless plugin 'Authorisation' => { grants => ... } asks for it, and worth reading about before it is: a grant table is a second source of truth wherever a rule already encodes ownership.

The punk_authz Sqitch project

Ships beside the plugin, so Punk::Sqitch deploys the table without the application writing the DDL. The DDL is in Punk::Model::Grant for an application that manages its schema another way.

REQUIREMENTS

Punk 0.32 or newer. The plugin reads the role ladder and the roles hook from the auth keyword through $app->auth_config, which 0.32 is the first release to provide, rather than being told them a second time in its own options.

SEE ALSO

Punk::Plugin::Authorisation for the plugin, Punk::Model::Grant for the table, Punk::Auth for the guard this sits beside, and Punk::DIY for a generated application that uses all of them.

AUTHOR

LNATION <email@lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION <email@lnation.org>.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)