BE group permission checks
Every Model enum value is registered as a native
TYPO3 customPermOptions entry under the nrllm namespace.
Administrators see a checkbox per capability (chat, completion,
embeddings, vision, streaming, tools, json_mode, audio) on the
Backend Users > Access Options tab when editing a BE
group. Consumer code asks the
Netresearch
whether the capability is allowed for the current user.
Running a check
Inject the service and call is before dispatching.
The method accepts an optional Backend for
tests; when omitted it reads $GLOBALS:
use Netresearch\NrLlm\Domain\Enum\ModelCapability;
use Netresearch\NrLlm\Exception\AccessDeniedException;
use Netresearch\NrLlm\Service\CapabilityPermissionService;
final class Caption
{
public function __construct(
private readonly CapabilityPermissionService $permissions,
) {}
public function describe(string $imageUrl): string
{
if (!$this->permissions->isAllowed(ModelCapability::VISION)) {
throw new AccessDeniedException(
'Vision capability not permitted for this user',
1745712100,
);
}
// ... dispatch to VisionService ...
}
}
Resolution order
The check resolves in this order:
- No BE user in context (CLI, scheduler, frontend) → allowed. Capability gating is a backend-editor concern; background jobs and frontend rendering are not subject to it.
- User is admin → allowed. Admins bypass the native TYPO3 permission machinery by convention.
- Delegates to
$backend— the native TYPO3 permission check. Returns what it returns.User->check ('custom_ options', 'nrllm: capability_ X')
Complementary to configuration ACL
The allowed_groups MM relation on
tx_ gates access to a specific preset
(API keys, system prompt, etc.). Capability permissions gate which
operations a user may invoke against any preset they can already
reach. The two are orthogonal and both checks must pass.
- Configuration ACL: "Can this editor use the 'creative-writing' configuration at all?"
- Capability permission: "Can this editor invoke vision against any configuration?"
Stable keys
Capability returns the
TYPO3 permission string (e.g. nrllm:capability_vision) for any
enum case. Use it when you need to check directly without going
through the service, for example in a Fluid ViewHelper or a TCA
display condition:
use Netresearch\NrLlm\Domain\Enum\ModelCapability;
use Netresearch\NrLlm\Service\CapabilityPermissionService;
$permString = CapabilityPermissionService::permissionString(
ModelCapability::TOOLS,
);
// => "nrllm:capability_tools"
See ADR-023: Native Backend Capability Permissions for the full design rationale and the alternatives (per-configuration flags, bespoke MM table, inline enforcement) we ruled out.