From bd0fc1e4b0dec4d2a71dd7d236c4b09062a0cb05 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Thu, 19 Mar 2026 12:36:48 +0100 Subject: [PATCH 01/16] 6869: Add agents.md and Claude Code configuration Add vendor-neutral agents.md with project context for AI coding agents, and Claude Code settings with permissions, hooks, and plugins. Update README with AI coding agents section describing the setup. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/settings.json | 107 +++++++++++++++++++++++++++++++ README.md | 32 ++++++++++ agents.md | 142 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 281 insertions(+) create mode 100644 .claude/settings.json create mode 100644 agents.md diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..f000cbb --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,107 @@ +{ + "$schema": "https://json.schemastore.org/claude-code-settings.json", + "env": { + "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1" + }, + "permissions": { + "allow": [ + "Bash(cat:*)", + "Bash(diff:*)", + "Bash(echo:*)", + "Bash(find:*)", + "Bash(gh:*)", + "Bash(git:*)", + "Bash(grep:*)", + "Bash(head:*)", + "Bash(ls:*)", + "Bash(pwd)", + "Bash(tail:*)", + "Bash(tree:*)", + "Bash(wc:*)", + "Bash(which:*)", + "Bash(docker compose:*)", + "Bash(docker network:*)" + ], + "deny": [ + "Bash(rm -rf:*)", + "Read(./.env.local)", + "Read(./.env.local.*)", + "Read(./config/secrets/*)" + ], + "ask": [ + "Bash(gh issue create:*)", + "Bash(gh issue close:*)", + "Bash(gh issue delete:*)", + "Bash(gh issue edit:*)", + "Bash(gh issue comment:*)", + "Bash(gh pr create:*)", + "Bash(gh pr close:*)", + "Bash(gh pr merge:*)", + "Bash(gh pr edit:*)", + "Bash(gh pr comment:*)", + "Bash(gh pr review:*)", + "Bash(gh release create:*)", + "Bash(gh release delete:*)", + "Bash(gh release edit:*)", + "Bash(gh repo create:*)", + "Bash(gh repo delete:*)", + "Bash(gh label create:*)", + "Bash(gh label delete:*)", + "Bash(gh label edit:*)", + "Bash(git push:*)", + "Bash(git branch -d:*)", + "Bash(git branch -D:*)", + "Bash(git tag -d:*)", + "Bash(git tag -a:*)", + "Bash(git tag :*)", + "Bash(git reset:*)", + "Bash(git rebase:*)", + "Bash(git merge:*)", + "Bash(git stash drop:*)", + "Bash(git clean:*)", + "Bash(git checkout -- :*)", + "Bash(git restore:*)", + "Bash(git commit:*)" + ] + }, + "hooks": { + "PostToolUse": [ + { + "matcher": "Write|Edit", + "hooks": [ + { + "type": "command", + "command": "case \"$CLAUDE_FILE_PATH\" in *.php) docker compose exec -T phpfpm vendor/bin/php-cs-fixer fix --quiet \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", + "timeout": 30 + }, + { + "type": "command", + "command": "case \"$CLAUDE_FILE_PATH\" in *.yaml|*.yml) docker compose exec -T phpfpm bin/console lint:yaml \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", + "timeout": 15 + }, + { + "type": "command", + "command": "case \"$CLAUDE_FILE_PATH\" in *.twig) docker compose exec -T phpfpm bin/console lint:twig \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", + "timeout": 15 + }, + { + "type": "command", + "command": "case \"$CLAUDE_FILE_PATH\" in *.json) python3 -m json.tool \"$CLAUDE_FILE_PATH\" > /dev/null 2>&1 || true ;; esac", + "timeout": 10 + } + ] + } + ] + }, + "enabledPlugins": { + "php-lsp@claude-plugins-official": true, + "code-simplifier@claude-plugins-official": true, + "context7@claude-plugins-official": true, + "code-review@claude-plugins-official": true, + "security-guidance@claude-plugins-official": true, + "playwright@claude-plugins-official": true, + "feature-dev@claude-plugins-official": true + }, + "alwaysThinkingEnabled": true, + "defaultMode": "acceptEdits" +} diff --git a/README.md b/README.md index a1fc813..11cf35e 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ [![Codecov](https://img.shields.io/codecov/c/github/itk-dev/devops_itksites?style=flat-square&logo=codecov)](https://codecov.io/gh/itk-dev/devops_itksites) [![GitHub last commit](https://img.shields.io/github/last-commit/itk-dev/devops_itksites?style=flat-square)](https://github.com/itk-dev/devops_itksites/commits/develop/) [![GitHub License](https://img.shields.io/github/license/itk-dev/devops_itksites?style=flat-square)](https://github.com/itk-dev/devops_itksites/blob/develop/LICENSE) +[![agents.md](https://img.shields.io/badge/%F0%9F%A4%96_agents.md-AI%20ready-8A2BE2?style=flat-square)](https://github.com/itk-dev/devops_itksites/blob/develop/agents.md) This is our internal server and site registration tool. It works in tandem with our @@ -125,3 +126,34 @@ during development to automatically rebuild assets when source files change. ```sh docker compose run --rm node yarn coding-standards-check ``` + +### 🤖 AI coding agents + +This project includes an [`agents.md`](agents.md) file that provides project +context for AI coding agents. The file describes the project architecture, +technology stack, development commands, CI/CD setup, and coding conventions. + +`agents.md` is a vendor-neutral standard supported by tools such as +[Claude Code](https://claude.ai/claude-code), +[OpenCode](https://opencode.ai/), and others. + +Tool-specific configuration (permissions, hooks, plugins) lives in `.claude/` +and is not portable across tools. + +#### Claude Code plugins + +The following plugins are enabled in `.claude/settings.json`: + +| Plugin | Purpose | Source | +|---|---|---| +| `php-lsp` | PHP language server for type-aware code intelligence | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `context7` | Up-to-date documentation lookup for Symfony, Doctrine, API Platform, etc. | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `code-review` | Pull request code review | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `code-simplifier` | Suggests clarity and maintainability improvements | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `security-guidance` | Flags potential security issues (OWASP, injection, etc.) | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `playwright` | Browser automation for debugging and testing the EasyAdmin UI | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `feature-dev` | Guided feature development with codebase exploration and architecture focus | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | + +> **Note:** The `php-lsp` plugin requires [Intelephense](https://intelephense.com/) +> installed globally: `npm install -g intelephense`. All other plugins work +> without additional dependencies. diff --git a/agents.md b/agents.md new file mode 100644 index 0000000..6624c1a --- /dev/null +++ b/agents.md @@ -0,0 +1,142 @@ +# 🤖 Code Agents - DevOps ITKsites + +## Project Overview + +**DevOps ITKsites** is an internal Symfony application for server and site +registration/monitoring at ITK Dev. It receives `DetectionResults` from the +[ITK sites server harvester](https://github.com/itk-dev/devops_itkServerHarvest) +and processes them asynchronously to track servers, sites, domains, Docker +images, packages, modules, CVEs, and git repositories. + +## Technology Stack + +- **Language**: PHP 8.4+ (Symfony 7.3) +- **API**: API Platform 4.0 (REST) +- **Admin UI**: EasyAdmin 4.x +- **Database**: Doctrine ORM 3.x / DBAL 4.x with MariaDB +- **Messaging**: Symfony Messenger (AMQP/RabbitMQ) +- **Auth**: OpenID Connect (`itk-dev/openid-connect-bundle`) +- **Frontend**: Webpack Encore, Stimulus.js +- **Testing**: PHPUnit 11+ +- **Code Quality**: PHP-CS-Fixer, PHPStan, Rector + +## Architecture + +```mermaid +graph TD + A[Harvester] -->|POST DetectionResult| B[API Platform REST endpoint] + B --> C[Symfony Messenger] + C --> D[Async Message Handlers] + D --> D1[DirectoryHandler] + D --> D2[DockerImageHandler] + D --> D3[DrupalHandler] + D --> D4[GitHandler] + D --> D5[NginxHandler] + D --> D6[SymfonyHandler] + D1 & D2 & D3 & D4 & D5 & D6 --> E[Doctrine ORM] + E --> F[MariaDB] + F --> G[EasyAdmin UI] +``` + +### Key Directories + +| Directory | Purpose | +|---|---| +| `src/Entity/` | ~20 Doctrine entities (Server, Site, Domain, Installation, Package, DockerImage, Advisory, etc.) | +| `src/Handler/` | DetectionResult handlers (Directory, Docker, Drupal, Git, Nginx, Symfony) | +| `src/MessageHandler/` | Async message processing (PersistDetectionResult, ProcessDetectionResult) | +| `src/Admin/` | EasyAdmin CRUD controllers | +| `src/ApiResource/` | API Platform resource definitions | +| `src/Service/` | Factories (PackageVersion, ModuleVersion, Advisory) and export services | +| `src/Repository/` | Doctrine repositories | +| `config/packages/` | Bundle configurations | +| `migrations/` | Doctrine migrations | +| `fixtures/` | Hautelook/Alice test fixtures | +| `tests/` | PHPUnit tests (Api, Controller, MessageHandler) | + +### Data Flow + +All analyzed data (sites, installations, domains, packages, etc.) can be +truncated and rebuilt by replaying DetectionResults. Manually maintained data +(Servers, OIDC setups, Service Certificates) is separate and must be preserved. + +## Development Environment + +```sh +# Start services (MariaDB, PHP-FPM 8.4, Nginx, Mailpit) +docker compose pull && docker compose up --detach + +# Install dependencies +docker compose exec phpfpm composer install + +# Run migrations +docker compose exec phpfpm bin/console doctrine:migrations:migrate --no-interaction + +# Load fixtures +docker compose exec phpfpm composer fixtures + +# Login as admin (after fixtures) +docker compose exec phpfpm bin/console itk-dev:openid-connect:login admin@example.com + +# Process message queues +docker compose exec phpfpm composer queues + +# Build frontend assets +docker compose run --rm node yarn install && docker compose run --rm node yarn build +``` + +## Quality Checks + +All commands run inside Docker containers: + +```sh +# PHP coding standards (PHP-CS-Fixer) +docker compose exec phpfpm composer coding-standards-check +docker compose exec phpfpm composer coding-standards-apply + +# PHPUnit tests (creates test DB, runs migrations, executes tests) +docker compose exec phpfpm composer tests + +# Frontend coding standards +docker compose run --rm node yarn coding-standards-check + +# API spec export (must be committed) +docker compose exec phpfpm composer update-api-spec +``` + +## CI/CD + +### GitHub Actions (`pr.yaml`) + +Pull requests run these checks: + +1. **Composer validation** - validates and installs (prod + dev) +2. **Doctrine schema validation** - migrations + schema check against MariaDB +3. **PHP-CS-Fixer** - coding standards +4. **PHPUnit** - unit/integration tests with MariaDB +5. **API spec validation** - ensures exported OpenAPI spec is up to date +6. **Fixtures** - verifies fixtures load successfully +7. **Asset build** - verifies frontend assets compile +8. **Changelog** - ensures CHANGELOG.md is updated + +### Woodpecker CI (deployment) + +- `stg.yml` - Deploys to staging on push to develop +- `prod.yml` - Deploys to production on release (Ansible playbook, runs migrations + transport setup) + +## PR Guidelines + +- PRs must link to a ticket +- Code must pass all CI checks (tests, coding standards, static analysis) +- CHANGELOG.md must be updated +- UI changes require screenshots +- Base branch: `develop` + +## Important Conventions + +- Entity classes extend `AbstractBaseEntity` (provides `id`, `createdAt`, `updatedAt`) +- Detection handlers implement `DetectionResultHandlerInterface` +- Handlers are auto-tagged and injected via tagged iterator in `services.yaml` +- Async processing uses Symfony Messenger with AMQP transport +- Environment-specific config goes in `.env.local` (not committed) +- API specs (`public/api-spec-v1.yaml` and `.json`) must be regenerated and committed when API changes \ No newline at end of file From 1e7c04c249c7beb360338a1d6377be074848c87a Mon Sep 17 00:00:00 2001 From: turegjorup Date: Thu, 19 Mar 2026 12:44:49 +0100 Subject: [PATCH 02/16] &869: Update Chnagelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf0a0af..6d2fdf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#58](https://github.com/itk-dev/devops_itksites/pull/58) 5002: Added export to everything +- [#62](https://github.com/itk-dev/devops_itksites/pull/62) + 6869: Add agents.md and Claude Code configuration for AI coding agents ## [1.8.10] - 2025-07-02 From 30a9a5340521b6c439a6a91af71b79c25fd5e635 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Thu, 19 Mar 2026 12:44:49 +0100 Subject: [PATCH 03/16] 6869: Update Changelog Co-Authored-By: Claude Opus 4.6 (1M context) --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf0a0af..6d2fdf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#58](https://github.com/itk-dev/devops_itksites/pull/58) 5002: Added export to everything +- [#62](https://github.com/itk-dev/devops_itksites/pull/62) + 6869: Add agents.md and Claude Code configuration for AI coding agents ## [1.8.10] - 2025-07-02 From 3d5ac2dc9939d1a30121239185e92bc9cfa0e633 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Wed, 25 Mar 2026 13:54:27 +0100 Subject: [PATCH 04/16] 6869: Rename agents.md to claude.md and update settings Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/settings.json | 1 + agents.md => claude.md | 0 2 files changed, 1 insertion(+) rename agents.md => claude.md (100%) diff --git a/.claude/settings.json b/.claude/settings.json index f000cbb..263375d 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -16,6 +16,7 @@ "Bash(ls:*)", "Bash(pwd)", "Bash(tail:*)", + "Bash(task:*)", "Bash(tree:*)", "Bash(wc:*)", "Bash(which:*)", diff --git a/agents.md b/claude.md similarity index 100% rename from agents.md rename to claude.md From f07447d608b3c222298c213aef1251dd1def3bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ture=20Gj=C3=B8rup?= Date: Wed, 25 Mar 2026 14:07:12 +0100 Subject: [PATCH 05/16] Update .claude/settings.json Co-authored-by: Jesper Pedersen --- .claude/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.claude/settings.json b/.claude/settings.json index f000cbb..f33ed30 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -100,7 +100,8 @@ "code-review@claude-plugins-official": true, "security-guidance@claude-plugins-official": true, "playwright@claude-plugins-official": true, - "feature-dev@claude-plugins-official": true + "feature-dev@claude-plugins-official": true, + "itkdev-skills@itkdev-marketplace": true }, "alwaysThinkingEnabled": true, "defaultMode": "acceptEdits" From 8c33fafd09eab56bc899c21991d284ba702688ba Mon Sep 17 00:00:00 2001 From: turegjorup Date: Wed, 25 Mar 2026 14:18:59 +0100 Subject: [PATCH 06/16] 6869: Add PHPStan job to PR workflow Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/pr.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 5ddf9eb..5625c95 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -21,6 +21,21 @@ jobs: docker compose exec phpfpm bin/console messenger:setup-transports failed docker compose exec phpfpm bin/console doctrine:schema:validate + phpstan: + runs-on: ubuntu-latest + name: PHPStan + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Create docker network + run: docker network create frontend + + - name: Run PHPStan + run: | + docker compose run --rm phpfpm composer install --no-interaction + docker compose run --rm phpfpm vendor/bin/phpstan analyse + phpunit: runs-on: ubuntu-latest name: PHP Unit tests From 4b47640397d34a5731c5c894b5cdbbb952e8266f Mon Sep 17 00:00:00 2001 From: turegjorup Date: Wed, 25 Mar 2026 14:19:18 +0100 Subject: [PATCH 07/16] 6869: Improve Claude Code hooks and permissions - Add PHPStan, twig-cs-fixer, and composer normalize PostToolUse hooks - Add SessionStart hook to ensure Docker services are running - Add Stop hook for Symfony DI container validation - Scope docker compose permissions (destructive commands require confirmation) - Restore php-lsp plugin - Set COMPOSE_USER env var Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/settings.json | 59 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/.claude/settings.json b/.claude/settings.json index 263375d..5582e45 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-settings.json", "env": { - "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1" + "COMPOSE_USER": "deploy" }, "permissions": { "allow": [ @@ -20,19 +20,34 @@ "Bash(tree:*)", "Bash(wc:*)", "Bash(which:*)", - "Bash(docker compose:*)", + "Bash(docker compose exec:*)", + "Bash(docker compose run:*)", + "Bash(docker compose up:*)", + "Bash(docker compose ps:*)", + "Bash(docker compose logs:*)", + "Bash(docker compose top:*)", + "Bash(docker compose config:*)", + "Bash(docker compose pull:*)", + "Bash(docker compose images:*)", "Bash(docker network:*)" ], "deny": [ "Bash(rm -rf:*)", + "Bash(gh issue delete:*)", + "Bash(gh release delete:*)", + "Bash(gh repo delete:*)", + "Bash(gh label delete:*)", "Read(./.env.local)", "Read(./.env.local.*)", "Read(./config/secrets/*)" ], "ask": [ + "Bash(docker compose down:*)", + "Bash(docker compose stop:*)", + "Bash(docker compose rm:*)", + "Bash(docker compose restart:*)", "Bash(gh issue create:*)", "Bash(gh issue close:*)", - "Bash(gh issue delete:*)", "Bash(gh issue edit:*)", "Bash(gh issue comment:*)", "Bash(gh pr create:*)", @@ -42,12 +57,9 @@ "Bash(gh pr comment:*)", "Bash(gh pr review:*)", "Bash(gh release create:*)", - "Bash(gh release delete:*)", "Bash(gh release edit:*)", "Bash(gh repo create:*)", - "Bash(gh repo delete:*)", "Bash(gh label create:*)", - "Bash(gh label delete:*)", "Bash(gh label edit:*)", "Bash(git push:*)", "Bash(git branch -d:*)", @@ -66,6 +78,19 @@ ] }, "hooks": { + "SessionStart": [ + { + "matcher": "startup", + "hooks": [ + { + "type": "command", + "command": "docker compose up --detach --quiet-pull 2>/dev/null || true", + "timeout": 60, + "statusMessage": "Starting Docker services..." + } + ] + } + ], "PostToolUse": [ { "matcher": "Write|Edit", @@ -77,18 +102,30 @@ }, { "type": "command", - "command": "case \"$CLAUDE_FILE_PATH\" in *.yaml|*.yml) docker compose exec -T phpfpm bin/console lint:yaml \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", - "timeout": 15 + "command": "case \"$CLAUDE_FILE_PATH\" in *.php) docker compose exec -T phpfpm vendor/bin/phpstan analyse --no-progress --error-format=raw \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", + "timeout": 30 }, { "type": "command", - "command": "case \"$CLAUDE_FILE_PATH\" in *.twig) docker compose exec -T phpfpm bin/console lint:twig \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", + "command": "case \"$CLAUDE_FILE_PATH\" in *.twig) docker compose exec -T phpfpm vendor/bin/twig-cs-fixer lint --fix \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", "timeout": 15 }, { "type": "command", - "command": "case \"$CLAUDE_FILE_PATH\" in *.json) python3 -m json.tool \"$CLAUDE_FILE_PATH\" > /dev/null 2>&1 || true ;; esac", - "timeout": 10 + "command": "case \"$CLAUDE_FILE_PATH\" in */composer.json) docker compose exec -T phpfpm composer normalize --quiet 2>/dev/null || true ;; esac", + "timeout": 30 + } + ] + } + ], + "Stop": [ + { + "hooks": [ + { + "type": "command", + "command": "docker compose exec -T phpfpm bin/console lint:container 2>/dev/null || true", + "timeout": 30, + "statusMessage": "Validating Symfony DI container..." } ] } From 560e5e5666e3776ab8dba90aa85d4450456db624 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Wed, 25 Mar 2026 14:19:27 +0100 Subject: [PATCH 08/16] 6869: Clarify local-only dev credentials in docker-compose.override Replace opaque RabbitMQ Erlang cookie with self-documenting value and add comment indicating these are local dev credentials. Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.override.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 77c259d..73f8b43 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -9,7 +9,7 @@ services: environment: - RABBITMQ_DEFAULT_USER=user - RABBITMQ_DEFAULT_PASS=password - - RABBITMQ_ERLANG_COOKIE='d53f219cd9376f8f440aaf9889f315ab' + - RABBITMQ_ERLANG_COOKIE='local-dev-cookie-not-a-secret' healthcheck: test: rabbitmq-diagnostics check_port_connectivity interval: 1s From 2ad001c7eced756385df17838f56d42597c74475 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Wed, 25 Mar 2026 14:25:28 +0100 Subject: [PATCH 09/16] 6869: Update claude.md for Symfony 8.0 and PHP 8.5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PHP 8.4+ → 8.5+, Symfony 7.3 → 8.0 - EasyAdmin 4.x → 5.x, PHPUnit 11+ → 13+ - Expand CI section to reflect all 14 workflow checks Co-Authored-By: Claude Opus 4.6 (1M context) --- README.md | 18 ++++++++--------- claude.md | 58 ++++++++++++++++++++++++++++++------------------------- 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index bcbb48b..2928aa9 100644 --- a/README.md +++ b/README.md @@ -149,15 +149,15 @@ and is not portable across tools. The following plugins are enabled in `.claude/settings.json`: -| Plugin | Purpose | Source | -|---|---|---| -| `php-lsp` | PHP language server for type-aware code intelligence | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | -| `context7` | Up-to-date documentation lookup for Symfony, Doctrine, API Platform, etc. | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | -| `code-review` | Pull request code review | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | -| `code-simplifier` | Suggests clarity and maintainability improvements | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | -| `security-guidance` | Flags potential security issues (OWASP, injection, etc.) | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | -| `playwright` | Browser automation for debugging and testing the EasyAdmin UI | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | -| `feature-dev` | Guided feature development with codebase exploration and architecture focus | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| Plugin | Purpose | Source | +|---------------------|-----------------------------------------------------------------------------|------------------------------------------------------------------------------| +| `php-lsp` | PHP language server for type-aware code intelligence | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `context7` | Up-to-date documentation lookup for Symfony, Doctrine, API Platform, etc. | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `code-review` | Pull request code review | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `code-simplifier` | Suggests clarity and maintainability improvements | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `security-guidance` | Flags potential security issues (OWASP, injection, etc.) | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `playwright` | Browser automation for debugging and testing the EasyAdmin UI | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | +| `feature-dev` | Guided feature development with codebase exploration and architecture focus | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | > **Note:** The `php-lsp` plugin requires [Intelephense](https://intelephense.com/) > installed globally: `npm install -g intelephense`. All other plugins work diff --git a/claude.md b/claude.md index 6624c1a..a83a1af 100644 --- a/claude.md +++ b/claude.md @@ -10,14 +10,14 @@ images, packages, modules, CVEs, and git repositories. ## Technology Stack -- **Language**: PHP 8.4+ (Symfony 7.3) +- **Language**: PHP 8.5+ (Symfony 8.0) - **API**: API Platform 4.0 (REST) -- **Admin UI**: EasyAdmin 4.x +- **Admin UI**: EasyAdmin 5.x - **Database**: Doctrine ORM 3.x / DBAL 4.x with MariaDB - **Messaging**: Symfony Messenger (AMQP/RabbitMQ) - **Auth**: OpenID Connect (`itk-dev/openid-connect-bundle`) - **Frontend**: Webpack Encore, Stimulus.js -- **Testing**: PHPUnit 11+ +- **Testing**: PHPUnit 13+ - **Code Quality**: PHP-CS-Fixer, PHPStan, Rector ## Architecture @@ -40,19 +40,19 @@ graph TD ### Key Directories -| Directory | Purpose | -|---|---| -| `src/Entity/` | ~20 Doctrine entities (Server, Site, Domain, Installation, Package, DockerImage, Advisory, etc.) | -| `src/Handler/` | DetectionResult handlers (Directory, Docker, Drupal, Git, Nginx, Symfony) | -| `src/MessageHandler/` | Async message processing (PersistDetectionResult, ProcessDetectionResult) | -| `src/Admin/` | EasyAdmin CRUD controllers | -| `src/ApiResource/` | API Platform resource definitions | -| `src/Service/` | Factories (PackageVersion, ModuleVersion, Advisory) and export services | -| `src/Repository/` | Doctrine repositories | -| `config/packages/` | Bundle configurations | -| `migrations/` | Doctrine migrations | -| `fixtures/` | Hautelook/Alice test fixtures | -| `tests/` | PHPUnit tests (Api, Controller, MessageHandler) | +| Directory | Purpose | +|-----------------------|--------------------------------------------------------------------------------------------------| +| `src/Entity/` | ~20 Doctrine entities (Server, Site, Domain, Installation, Package, DockerImage, Advisory, etc.) | +| `src/Handler/` | DetectionResult handlers (Directory, Docker, Drupal, Git, Nginx, Symfony) | +| `src/MessageHandler/` | Async message processing (PersistDetectionResult, ProcessDetectionResult) | +| `src/Admin/` | EasyAdmin CRUD controllers | +| `src/ApiResource/` | API Platform resource definitions | +| `src/Service/` | Factories (PackageVersion, ModuleVersion, Advisory) and export services | +| `src/Repository/` | Doctrine repositories | +| `config/packages/` | Bundle configurations | +| `migrations/` | Doctrine migrations | +| `fixtures/` | Hautelook/Alice test fixtures | +| `tests/` | PHPUnit tests (Api, Controller, MessageHandler) | ### Data Flow @@ -63,7 +63,7 @@ truncated and rebuilt by replaying DetectionResults. Manually maintained data ## Development Environment ```sh -# Start services (MariaDB, PHP-FPM 8.4, Nginx, Mailpit) +# Start services (MariaDB, PHP-FPM 8.5, Nginx, Mailpit) docker compose pull && docker compose up --detach # Install dependencies @@ -110,14 +110,20 @@ docker compose exec phpfpm composer update-api-spec Pull requests run these checks: -1. **Composer validation** - validates and installs (prod + dev) -2. **Doctrine schema validation** - migrations + schema check against MariaDB -3. **PHP-CS-Fixer** - coding standards -4. **PHPUnit** - unit/integration tests with MariaDB -5. **API spec validation** - ensures exported OpenAPI spec is up to date -6. **Fixtures** - verifies fixtures load successfully -7. **Asset build** - verifies frontend assets compile -8. **Changelog** - ensures CHANGELOG.md is updated +1. **Composer** (`composer.yaml`) - validates, normalizes, and audits +2. **Doctrine schema validation** (`pr.yaml`) - migrations + schema check against MariaDB +3. **PHP-CS-Fixer** (`php.yaml`) - PHP coding standards +4. **PHPStan** (`pr.yaml`) - static analysis (level 6) +5. **PHPUnit** (`pr.yaml`) - unit/integration tests with MariaDB + coverage +6. **Twig** (`twig.yaml`) - Twig coding standards (twig-cs-fixer) +7. **YAML** (`yaml.yaml`) - YAML formatting (Prettier) +8. **Markdown** (`markdown.yaml`) - Markdown linting (markdownlint) +9. **JavaScript** (`javascript.yaml`) - JS formatting (Prettier) +10. **Styles** (`styles.yaml`) - CSS/SCSS formatting (Prettier) +11. **API spec** (`api-spec.yaml`) - ensures exported OpenAPI spec is up to date +12. **Fixtures** (`pr.yaml`) - verifies fixtures load successfully +13. **Asset build** (`pr.yaml`) - verifies frontend assets compile +14. **Changelog** (`changelog.yaml`) - ensures CHANGELOG.md is updated ### Woodpecker CI (deployment) @@ -139,4 +145,4 @@ Pull requests run these checks: - Handlers are auto-tagged and injected via tagged iterator in `services.yaml` - Async processing uses Symfony Messenger with AMQP transport - Environment-specific config goes in `.env.local` (not committed) -- API specs (`public/api-spec-v1.yaml` and `.json`) must be regenerated and committed when API changes \ No newline at end of file +- API specs (`public/api-spec-v1.yaml` and `.json`) must be regenerated and committed when API changes From 9a88a0033b08cdbe91284c5e785207ee52a70a4a Mon Sep 17 00:00:00 2001 From: turegjorup Date: Wed, 25 Mar 2026 14:26:15 +0100 Subject: [PATCH 10/16] =?UTF-8?q?6869:=20Fix=20typo=20in=20config=20refere?= =?UTF-8?q?nce=20(@var=20=E2=86=92=20@type)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- config/reference.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/reference.php b/config/reference.php index 7c1b9ad..85a036d 100644 --- a/config/reference.php +++ b/config/reference.php @@ -1360,7 +1360,7 @@ * mercure?: bool|array{ * enabled?: bool|Param, // Default: false * hub_url?: scalar|Param|null, // The URL sent in the Link HTTP header. If not set, will default to the URL for MercureBundle's default hub. // Default: null - * include_type?: bool|Param, // Always include @var in updates (including delete ones). // Default: false + * include_type?: bool|Param, // Always include @type in updates (including delete ones). // Default: false * }, * messenger?: bool|array{ * enabled?: bool|Param, // Default: true From 9344dcaac8fdeabdcac31f5c52c3cd6a5776992a Mon Sep 17 00:00:00 2001 From: turegjorup Date: Fri, 27 Mar 2026 10:53:54 +0100 Subject: [PATCH 11/16] 6869: Fix FieldCollection::new() removed in EasyAdmin 5.x Use plain constructor instead of the removed static factory method, fixing PHPStan staticMethod.notFound errors. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/Trait/ExportCrudControllerTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Trait/ExportCrudControllerTrait.php b/src/Trait/ExportCrudControllerTrait.php index 8880d58..d02b687 100644 --- a/src/Trait/ExportCrudControllerTrait.php +++ b/src/Trait/ExportCrudControllerTrait.php @@ -47,7 +47,7 @@ public function export(AdminContext $context): Response assert($this instanceof AbstractCrudController); // Lifted from self::index(). - $fields = FieldCollection::new($this->configureFields(Crud::PAGE_INDEX)); + $fields = new FieldCollection($this->configureFields(Crud::PAGE_INDEX)); $context->getCrud()->setFieldAssets($this->getFieldAssets($fields)); $filters = $this->filterFactory->create($context->getCrud()->getFiltersConfig(), $fields, $context->getEntity()); From 39144a69254aa5f514ad745971fad621ab69b029 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Fri, 27 Mar 2026 11:05:53 +0100 Subject: [PATCH 12/16] 6869: Update task file with "pr.actions" check --- Taskfile.yml | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/Taskfile.yml b/Taskfile.yml index 9c4494a..108d803 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -174,6 +174,76 @@ tasks: COMPOSE_ARGS: run --rm prettier '**/*.{yml,yaml}' --check --no-error-on-unmatched-pattern silent: true + # Composer checks (mirrors composer.yaml CI) + + composer:check: + desc: Validate, normalize, and audit composer + cmds: + - task: compose + vars: + COMPOSE_ARGS: exec phpfpm composer validate --strict + - task: compose + vars: + COMPOSE_ARGS: exec phpfpm composer normalize --dry-run + - task: compose + vars: + COMPOSE_ARGS: exec phpfpm composer audit + + # Analysis + + analysis:php: + aliases: [analyze:php] + desc: Run PHPStan static analysis + cmds: + - task: compose + vars: + COMPOSE_ARGS: exec phpfpm vendor/bin/phpstan + silent: true + + # Test matrix (mirrors pr.yaml CI jobs) + + test:matrix: + desc: Run full test matrix (tests, schema validation, fixtures, assets) + cmds: + - task: tests + - task: test:doctrine-schema + - task: test:fixtures + - task: test:build-assets + + test:doctrine-schema: + desc: Validate Doctrine schema against database + cmds: + - task: console + vars: + CONSOLE_ARGS: doctrine:schema:validate + + test:fixtures: + desc: Verify fixtures load successfully + cmds: + - task: console + vars: + CONSOLE_ARGS: hautelook:fixtures:load --no-interaction + + test:build-assets: + desc: Verify frontend assets compile + cmds: + - task: compose + vars: + COMPOSE_ARGS: run --rm node yarn install + - task: compose + vars: + COMPOSE_ARGS: run --rm node yarn build + + # CI + + pr:actions: + desc: Run all CI checks locally + cmds: + - task: composer:check + - task: coding-standards:check + - task: analyze:php + - task: test:matrix + api:spec:export: desc: Export API specification cmds: From 84caedcf3d3cc92b0f2a4d450098770264fc9c81 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Fri, 27 Mar 2026 11:09:23 +0100 Subject: [PATCH 13/16] 6869: Update defaults in claude.md --- .claude/settings.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.claude/settings.json b/.claude/settings.json index e722d3d..5eb49e1 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -140,7 +140,5 @@ "playwright@claude-plugins-official": true, "feature-dev@claude-plugins-official": true, "itkdev-skills@itkdev-marketplace": true - }, - "alwaysThinkingEnabled": true, - "defaultMode": "acceptEdits" + } } From 506969b1c241ece4d43d6d2e2ae912836615722c Mon Sep 17 00:00:00 2001 From: turegjorup Date: Fri, 27 Mar 2026 11:29:16 +0100 Subject: [PATCH 14/16] 6869: Add automation recommendations (agents, skills, hooks, MCP) Add PR readiness and migration generator agents, update-api-spec skill, PreToolUse lock file guard, Prettier PostToolUse hook, and team-shared .mcp.json with context7. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/agents/create-migration.md | 15 +++++++++++++++ .claude/agents/pr-readiness.md | 24 ++++++++++++++++++++++++ .claude/settings.json | 16 ++++++++++++++++ .claude/skills/update-api-spec/SKILL.md | 12 ++++++++++++ .gitignore | 1 - .mcp.json | 8 ++++++++ 6 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 .claude/agents/create-migration.md create mode 100644 .claude/agents/pr-readiness.md create mode 100644 .claude/skills/update-api-spec/SKILL.md create mode 100644 .mcp.json diff --git a/.claude/agents/create-migration.md b/.claude/agents/create-migration.md new file mode 100644 index 0000000..235de3b --- /dev/null +++ b/.claude/agents/create-migration.md @@ -0,0 +1,15 @@ +--- +name: create-migration +description: Generate and validate a Doctrine migration after entity changes +model: sonnet +--- + +After entity changes, generate and validate a Doctrine migration: + +1. Run `docker compose exec -T phpfpm bin/console doctrine:migrations:diff` to generate a migration +2. Read the generated migration file and verify the SQL looks correct +3. Run `docker compose exec -T phpfpm bin/console doctrine:migrations:migrate --no-interaction` +4. Run `docker compose exec -T phpfpm bin/console doctrine:schema:validate` + +Report the migration file path, the SQL it contains, and whether schema validation passed. +If schema validation fails, investigate and report the discrepancies. diff --git a/.claude/agents/pr-readiness.md b/.claude/agents/pr-readiness.md new file mode 100644 index 0000000..1b57e49 --- /dev/null +++ b/.claude/agents/pr-readiness.md @@ -0,0 +1,24 @@ +--- +name: pr-readiness +description: Run all CI-equivalent checks locally before creating a PR +model: haiku +--- + +Run the following checks in sequence inside Docker and report results for each. +Stop early if a critical check fails. + +## Checks + +1. **Composer validate**: `docker compose exec -T phpfpm composer validate --strict` +2. **Composer normalize**: `docker compose exec -T phpfpm composer normalize --dry-run` +3. **PHP coding standards**: `docker compose exec -T phpfpm composer coding-standards-check` +4. **PHPStan**: `docker compose exec -T phpfpm vendor/bin/phpstan analyse --no-progress` +5. **PHPUnit tests**: `docker compose exec -T phpfpm composer tests` +6. **Twig coding standards**: `docker compose exec -T phpfpm vendor/bin/twig-cs-fixer lint templates/` +7. **JS coding standards**: `docker compose run --rm -T node yarn coding-standards-check` +8. **API spec up to date**: Run `docker compose exec -T phpfpm composer update-api-spec`, then check `git diff --exit-code public/api-spec-v1.*` +9. **CHANGELOG updated**: Verify CHANGELOG.md has changes compared to the base branch (`git diff develop -- CHANGELOG.md`) + +## Output + +Report a summary table with columns: Check Name, Status (pass/fail), and error output for failures. diff --git a/.claude/settings.json b/.claude/settings.json index 5eb49e1..6b3b901 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -91,6 +91,17 @@ ] } ], + "PreToolUse": [ + { + "matcher": "Edit|Write", + "hooks": [ + { + "type": "command", + "command": "case \"$CLAUDE_FILE_PATH\" in */composer.lock|*/yarn.lock|*/.env.local|*/.env.local.*) echo 'BLOCKED: Do not edit lock files or .env.local directly' >&2; exit 1 ;; esac" + } + ] + } + ], "PostToolUse": [ { "matcher": "Write|Edit", @@ -114,6 +125,11 @@ "type": "command", "command": "case \"$CLAUDE_FILE_PATH\" in */composer.json) docker compose exec -T phpfpm composer normalize --quiet 2>/dev/null || true ;; esac", "timeout": 30 + }, + { + "type": "command", + "command": "case \"$CLAUDE_FILE_PATH\" in *.js|*.css|*.scss|*.yaml|*.yml|*.md) docker compose run --rm -T node npx prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", + "timeout": 15 } ] } diff --git a/.claude/skills/update-api-spec/SKILL.md b/.claude/skills/update-api-spec/SKILL.md new file mode 100644 index 0000000..54856bf --- /dev/null +++ b/.claude/skills/update-api-spec/SKILL.md @@ -0,0 +1,12 @@ +--- +name: update-api-spec +description: Regenerate and stage API spec files after API resource changes +user-invocable: true +--- + +When API resources or operations change, regenerate the OpenAPI spec files: + +1. Run `docker compose exec -T phpfpm composer update-api-spec` +2. Check `git diff public/api-spec-v1.*` for changes +3. If changed, stage the spec files with `git add public/api-spec-v1.yaml public/api-spec-v1.json` +4. Report what changed in the API spec diff --git a/.gitignore b/.gitignore index 8fa3dcb..c07e73d 100644 --- a/.gitignore +++ b/.gitignore @@ -30,5 +30,4 @@ yarn-error.log phpstan.neon ###< phpstan/phpstan ### .phpunit.cache -.claude .twig-cs-fixer.cache diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..f0c27d6 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "context7": { + "command": "npx", + "args": ["-y", "@upstreamapi/context7-mcp@latest"] + } + } +} From 5da6d06d80c05e21b019d67765ceb24cf9529d18 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Fri, 27 Mar 2026 11:36:12 +0100 Subject: [PATCH 15/16] 6869: Fix hook file paths for Docker and update README Convert absolute host paths to relative paths in all PostToolUse hooks using ${CLAUDE_FILE_PATH#$CLAUDE_PROJECT_DIR/} so tools inside Docker containers can resolve the files. Document agents, skills, hooks, and MCP servers in README. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/settings.json | 8 +++--- README.md | 64 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/.claude/settings.json b/.claude/settings.json index 6b3b901..f1b6bf0 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -108,17 +108,17 @@ "hooks": [ { "type": "command", - "command": "case \"$CLAUDE_FILE_PATH\" in *.php) docker compose exec -T phpfpm vendor/bin/php-cs-fixer fix --quiet \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", + "command": "case \"$CLAUDE_FILE_PATH\" in *.php) REL_PATH=\"${CLAUDE_FILE_PATH#$CLAUDE_PROJECT_DIR/}\"; docker compose exec -T phpfpm vendor/bin/php-cs-fixer fix --quiet \"$REL_PATH\" 2>/dev/null || true ;; esac", "timeout": 30 }, { "type": "command", - "command": "case \"$CLAUDE_FILE_PATH\" in *.php) docker compose exec -T phpfpm vendor/bin/phpstan analyse --no-progress --error-format=raw \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", + "command": "case \"$CLAUDE_FILE_PATH\" in *.php) REL_PATH=\"${CLAUDE_FILE_PATH#$CLAUDE_PROJECT_DIR/}\"; docker compose exec -T phpfpm vendor/bin/phpstan analyse --no-progress --error-format=raw \"$REL_PATH\" 2>/dev/null || true ;; esac", "timeout": 30 }, { "type": "command", - "command": "case \"$CLAUDE_FILE_PATH\" in *.twig) docker compose exec -T phpfpm vendor/bin/twig-cs-fixer lint --fix \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", + "command": "case \"$CLAUDE_FILE_PATH\" in *.twig) REL_PATH=\"${CLAUDE_FILE_PATH#$CLAUDE_PROJECT_DIR/}\"; docker compose exec -T phpfpm vendor/bin/twig-cs-fixer lint --fix \"$REL_PATH\" 2>/dev/null || true ;; esac", "timeout": 15 }, { @@ -128,7 +128,7 @@ }, { "type": "command", - "command": "case \"$CLAUDE_FILE_PATH\" in *.js|*.css|*.scss|*.yaml|*.yml|*.md) docker compose run --rm -T node npx prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac", + "command": "case \"$CLAUDE_FILE_PATH\" in *.js|*.css|*.scss|*.yaml|*.yml|*.md) REL_PATH=\"${CLAUDE_FILE_PATH#$CLAUDE_PROJECT_DIR/}\"; docker compose run --rm -T node npx prettier --write \"$REL_PATH\" 2>/dev/null || true ;; esac", "timeout": 15 } ] diff --git a/README.md b/README.md index 2928aa9..573f212 100644 --- a/README.md +++ b/README.md @@ -16,17 +16,17 @@ information about sites and installations running on the server. These are sent This allows us to monitor -* What is installed and running -* Which sites/domains we are hosting -* What docker images we are running -* What packages and modules we are running -* If there are known CVE's for the packages/modules -* What git repositories we are hosting +- What is installed and running +- Which sites/domains we are hosting +- What docker images we are running +- What packages and modules we are running +- If there are known CVE's for the packages/modules +- What git repositories we are hosting Additionally we can register and document -* All OpenID Connect setups -* All Services Certificates +- All OpenID Connect setups +- All Services Certificates Servers, OpenID Connect setups, Services Certificates must be created and maintained manually. All other information is kept up to date by analysing the DetectionResults. @@ -74,9 +74,9 @@ AZURE_AZ_OIDC_REDIRECT_URI=https://itksites.local.itkdev.dk/openid-connect/gener There are not implemented on -* sites -* installations -* domains +- sites +- installations +- domains This is due to automated processes and scripts that listen from sites and data is therefore not relevant to have. The architecture makes it possible to delete @@ -150,7 +150,7 @@ and is not portable across tools. The following plugins are enabled in `.claude/settings.json`: | Plugin | Purpose | Source | -|---------------------|-----------------------------------------------------------------------------|------------------------------------------------------------------------------| +| ------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | | `php-lsp` | PHP language server for type-aware code intelligence | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | | `context7` | Up-to-date documentation lookup for Symfony, Doctrine, API Platform, etc. | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | | `code-review` | Pull request code review | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) | @@ -162,3 +162,43 @@ The following plugins are enabled in `.claude/settings.json`: > **Note:** The `php-lsp` plugin requires [Intelephense](https://intelephense.com/) > installed globally: `npm install -g intelephense`. All other plugins work > without additional dependencies. + +#### Claude Code agents + +Custom agents in `.claude/agents/` automate multi-step workflows: + +| Agent | Purpose | +| ------------------ | ----------------------------------------------------------------- | +| `pr-readiness` | Runs all CI-equivalent checks locally before creating a PR | +| `create-migration` | Generates and validates a Doctrine migration after entity changes | + +#### Claude Code skills + +Custom skills in `.claude/skills/` provide repeatable task shortcuts: + +| Skill | Invocation | Purpose | +| ----------------- | ------------------ | ----------------------------------------------------- | +| `update-api-spec` | `/update-api-spec` | Regenerate and stage OpenAPI spec files after changes | + +#### Claude Code hooks + +Hooks in `.claude/settings.json` run automatically on tool events: + +| Hook | Trigger | Purpose | +| -------------- | -------------- | ------------------------------------------------------ | +| Docker start | `SessionStart` | Starts Docker services on session start | +| PHP-CS-Fixer | `PostToolUse` | Auto-formats PHP files on edit | +| PHPStan | `PostToolUse` | Runs static analysis on edited PHP files | +| Twig-CS-Fixer | `PostToolUse` | Auto-formats Twig templates on edit | +| Composer norm | `PostToolUse` | Normalizes `composer.json` on edit | +| Prettier | `PostToolUse` | Auto-formats JS, CSS, YAML, and Markdown files on edit | +| Lock guard | `PreToolUse` | Blocks edits to lock files and `.env.local` | +| Container lint | `Stop` | Validates Symfony DI container before stopping | + +#### MCP servers + +A shared `.mcp.json` provides team-wide MCP server configuration: + +| Server | Purpose | +| ---------- | ------------------------------------------------------------------------- | +| `context7` | Live documentation lookup for Symfony, Doctrine, API Platform, and others | From bac1888436b03121a2a511dd97a370f43a88a779 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Fri, 27 Mar 2026 13:20:54 +0100 Subject: [PATCH 16/16] 6869: Fix markdown lint errors in README.md Fix MD030 violations: reduce list marker spacing from 3 to 1 space. Co-Authored-By: Claude Opus 4.6 (1M context) --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 573f212..d416ec4 100644 --- a/README.md +++ b/README.md @@ -16,17 +16,17 @@ information about sites and installations running on the server. These are sent This allows us to monitor -- What is installed and running -- Which sites/domains we are hosting -- What docker images we are running -- What packages and modules we are running -- If there are known CVE's for the packages/modules -- What git repositories we are hosting +- What is installed and running +- Which sites/domains we are hosting +- What docker images we are running +- What packages and modules we are running +- If there are known CVE's for the packages/modules +- What git repositories we are hosting Additionally we can register and document -- All OpenID Connect setups -- All Services Certificates +- All OpenID Connect setups +- All Services Certificates Servers, OpenID Connect setups, Services Certificates must be created and maintained manually. All other information is kept up to date by analysing the DetectionResults. @@ -74,9 +74,9 @@ AZURE_AZ_OIDC_REDIRECT_URI=https://itksites.local.itkdev.dk/openid-connect/gener There are not implemented on -- sites -- installations -- domains +- sites +- installations +- domains This is due to automated processes and scripts that listen from sites and data is therefore not relevant to have. The architecture makes it possible to delete