Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# file generated with AI assistance: Claude Code - 2026-10-28 21:10:00 UTC
name: Tests

on:
push:
branches: [main, master, "feature/**"]
pull_request:

jobs:
phpunit:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ["8.5"]
name: PHPUnit (PHP ${{ matrix.php }})
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: pdo_sqlite, zip
coverage: none
- run: composer install --no-interaction --no-progress
- run: vendor/bin/phpunit
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@

All notable changes to this bundle. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow [SemVer](https://semver.org/) and come from the Git tags. Releases before 0.9.0 are described in the [GitHub releases](https://github.com/dmstr/flowable-bundle/releases).

## [0.11.0] - Unreleased

The bundle no longer checks role names: every HTTP operation and every MCP tool checks its own permission.

### Breaking changes

- **Every operation and every MCP tool needs a permission voter in the application.** Each of the 13 permissions (`flowable:read`, `flowable:read_stacktrace`, `flowable:mcp_read`, `flowable:deploy`, `flowable:deploy_delete`, `flowable:decision_evaluate`, `flowable:process_start`, `flowable:process_delete`, `flowable:task_complete`, `flowable:event_send`, `flowable:execution_trigger`, `flowable:worker`, `flowable:job_execute`) is checked with `is_granted()` and subject `null`. Without a voter that maps them, everything answers `403`, so provide the mapping before upgrading. Before: the read operations required the base user role, all write operations and all 14 MCP tools required `ROLE_FLOWABLE_ADMIN`; the job stacktrace declared the same role but did not enforce it (see Security). To reproduce that, map the former user role to `flowable:read` and the former administrator role to all 13 permissions (the map has no hierarchy, so the administrator needs `flowable:read` explicitly). The README has a migration section with an example voter.
- **Requires PHP >= 8.5.**
- **Requires `dmstr/api-configuration-bundle` `^0.6`** (and `doctrine/orm` `^3`). Applications on api-configuration-bundle 0.5 stay on 0.10.0.
- **Requires `symfony/expression-language` and `symfony/object-mapper`** (`^7.0`). The first evaluates the operations' `security` expressions; the second because API Platform enables its MCP integration only when it is installed.

### Added

- `Dmstr\Flowable\Security\FlowablePermissions` with the 13 permission constants and `all()`. They are registered as 13 `za7_core.permission` container tags (tag attribute `permission`) in `config/services.yaml`, so applications that collect such tags can offer them for assignment. The bundle has no permission map, no config node and no za7-core dependency. The MCP switches `dmstr_flowable.mcp.read` / `mcp.write` / `mcp.deploy` are unchanged and independent: a tool needs its switch and its permission.
- Kernel-based HTTP and MCP test suite (`tests/Kernel`, `tests/Http`) with its own test authentication (`X-Test-Roles` header, only under `tests/`), a GitHub Action (`.github/workflows/tests.yml`, PHP 8.5) and a `docker-compose.yml` CLI runner (`docker compose run --rm php`). Partially addresses Issue #14 (bundle test suite).

### Security

- `GET /jobs/{id}/stacktrace`, `GET /tasks/{id}/input_schema` and `GET /process_definitions/{id}/input_schema` did not evaluate their `security` expression: API Platform skips it for a custom controller with `read: false`, so every request that passed the firewall got them, with or without the declared role (the expression only filtered the hydra:operation list). The three controllers now check `flowable:read_stacktrace` and `flowable:read` themselves before calling the engine: `403` without the permission, `401` without authentication. This was already the case in 0.10.0 and earlier.

## [0.10.0] - 2026-10-21

### Breaking changes
Expand Down
7 changes: 6 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ packages are public and English-only.

## Requirements

PHP >= 8.4 (see `composer.json`). There is a PHPUnit 12 suite in `tests/` (configuration `phpunit.dist.xml`) that needs no Flowable engine, database or kernel: the client is a `FlowableClientInterface` double, and the MCP tool metadata is built from the resource attributes. Run it with `composer install && vendor/bin/phpunit`, or in any PHP 8.4 image with the repository mounted, e.g. `docker run --rm -v "$PWD:/app" -w /app <php-8.4-image> vendor/bin/phpunit`. There is no CI in this repository yet; the bundle is also exercised through its consuming applications (e.g. the za7 API stacks).
PHP >= 8.5 (see `composer.json`). The PHPUnit 12 suite in `tests/` (configuration `phpunit.dist.xml`) needs no Flowable engine or database. It has unit tests (the client is a `FlowableClientInterface` double, MCP tool metadata is built from the resource attributes) and kernel-based suites under `tests/Kernel` and `tests/Http` that boot a test kernel and send HTTP and MCP requests; their test authentication (`X-Test-Roles` header) lives only under `tests/`. Run it with the compose CLI runner: `docker compose run --rm php composer install && docker compose run --rm php vendor/bin/phpunit`. CI is the GitHub Action `.github/workflows/tests.yml` (PHP 8.5); the bundle is also exercised through its consuming applications (e.g. the za7 API stacks).

## Permissions

The bundle checks only `flowable:*` permissions (`Dmstr\Flowable\Security\FlowablePermissions`, registered as `za7_core.permission` tags in `config/services.yaml`) with `is_granted('<permission>')` and subject `null`. No `ROLE_*` name appears in `src/`, `config/` or the docs: the application maps permissions to roles through its own voter. A new operation or tool gets a permission constant, a tag and a test, and the README permission table is updated in the same change.

<!-- - revised 2026-10-08 (PHPUnit suite) -->
<!-- - revised 2026-10-28 (PHP 8.5, CI, kernel tests, permissions) -->
Loading
Loading