adachsoft / task-access-control
Adapter connecting adachsoft/task-contracts authorization to adachsoft/access-control-contracts.
Requires
- php: ^8.3
- adachsoft/access-control-contracts: ^0.1
- adachsoft/task-contracts: ^3.0@rc
Requires (Dev)
- adachsoft/php-code-style: ^0.7.2
- adachsoft/rule-evaluator-expression-language: ^0.1
- friendsofphp/php-cs-fixer: ^3.95
- phpstan/phpstan: ^2.3
- phpunit/phpunit: ^13.4
- rector/rector: ^2.8
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-13 08:54:33 UTC
README
adachsoft/task-access-control adapts adachsoft/task-contracts authorization to the services in adachsoft/access-control-contracts. It supplies task resources to permission conditions and exposes provisioned account roles to workflow transition conditions. Authentication remains the host application's responsibility.
Installation
composer require adachsoft/task-access-control
Applications must provide implementations of the access-control and task-definition repositories, plus a RuleEvaluatorInterface. For the ExpressionLanguage evaluator used in the example below, install:
composer require adachsoft/rule-evaluator-expression-language
Create the task authorization adapter
Pass the repositories and rule evaluator to TaskAccessControlFactory. The returned adapter can be injected into TaskServiceFactory::createTaskService() and TaskServiceFactory::createCommentService().
<?php
declare(strict_types=1);
use AdachSoft\TaskAccessControl\TaskAccessControlFactory;
use AdachSoft\TaskContracts\UseCase\TaskServiceFactory;
use AdachSoft\RuleEvaluatorExpressionLanguage\ExpressionLanguageRuleEvaluatorFactory;
$ruleEvaluator = (new ExpressionLanguageRuleEvaluatorFactory())->createDefault();
$taskAuthorization = TaskAccessControlFactory::create(
accountRepository: $accountRepository,
roleDefinitionRepository: $roleDefinitionRepository,
roleAssignmentRuleRepository: $roleAssignmentRuleRepository,
taskTypeDefinitionRepository: $taskTypeDefinitionRepository,
workflowDefinitionRepository: $workflowDefinitionRepository,
ruleEvaluator: $ruleEvaluator,
);
$taskService = TaskServiceFactory::createTaskService(
taskRepository: $taskRepository,
commentRepository: $commentRepository,
attachmentRepository: $attachmentRepository,
taskTypeDefinitionRepository: $taskTypeDefinitionRepository,
workflowDefinitionRepository: $workflowDefinitionRepository,
ruleEvaluator: $ruleEvaluator,
taskAuthorization: $taskAuthorization,
);
The adapter maps a task to a resource containing its ID, author, status ID, workflow category, type, parent ID, and attributes. The category is resolved through the task's workflow definition. Actor data contains the account ID, account type, and role IDs, so workflow expressions can use conditions such as 'supervisor' in actor.roles.
Example role definitions
The following JSON illustrates role grants and ordered account assignment rules. Store and load definitions through the repositories supplied to the factory; the adapter does not parse definition files.
{
"roles": [
{
"id": "admin",
"name": "Administrator",
"grants": [
{"permission": "*"}
]
},
{
"id": "supervisor",
"name": "Supervisor",
"grants": [
{"permission": "*"},
{"permission": "access.impersonate"}
]
},
{
"id": "developer",
"name": "Developer",
"grants": [
{"permission": "task.create"},
{
"permission": "task.edit",
"condition": "resource.author == actor.id and resource.category == 'TODO'"
},
{
"permission": "task.change_status",
"condition": "resource.author == actor.id"
},
{"permission": "comment.*"}
]
},
{
"id": "agent",
"name": "Agent",
"grants": [
{"permission": "comment.add"}
]
}
],
"assignment_rules": [
{"account": "aa", "type": "HUMAN", "roles": ["admin"]},
{"account": "claude", "type": "SERVICE", "roles": ["supervisor"]},
{"account": "dev_*", "type": "AGENT", "roles": ["developer"]},
{"account": "*", "type": "AGENT", "roles": ["agent"]}
]
}
Assignment rules are checked in file order; the first matching rule supplies the type and roles for an account created on first use. Access is denied by default when no grant matches. The global * grant does not authorize reserved access.* permissions unless they are granted explicitly.