1
0
Files
breadcrumb-the-shire/CLAUDE.md
2026-03-19 19:04:28 +01:00

9.0 KiB

CLAUDE.md — CoreCore

Multi-tenant admin application built on MintyPHP. Manages tenants, users, departments, roles, permissions, address books, mail, CSV imports, scheduled jobs, and Microsoft Entra ID SSO.

Agent workflow: guards, quality gates, role prompts, contracts, and skills live in .agents/ — start with .agents/README.md.

Tech Stack

  • Runtime: PHP 8.5 (FPM) on MintyPHP framework (mintyphp/core)
  • Web server: Nginx 1.25 (Alpine)
  • Database: MariaDB 11.4
  • Cache: Memcached 1.6
  • Frontend: Vanilla JS (ES2022 modules), vanilla CSS with @layer system — no build step
  • Key PHP libs: PHPMailer 7, Dompdf 3, endroid/qr-code 6, league/commonmark 2
  • Containerized: Docker Compose (dev + prod variants)

Quick Commands

# Start dev environment
docker compose up --build -d
# App: http://localhost:8080 | phpMyAdmin: http://localhost:8081

# Run PHPUnit tests (phpunit.xml configures bootstrap + testsuite)
docker compose exec php vendor/bin/phpunit

# Run PHPStan (level 5)
docker compose exec php vendor/bin/phpstan analyse -c phpstan.neon --no-progress

# CLI commands (single entry point)
docker compose exec php php bin/console list
docker compose exec php php bin/console module:sync              # full module runtime sync
docker compose exec php php bin/console module:migrate           # apply module SQL migrations
docker compose exec php php bin/console module:permissions-sync  # sync + deactivate orphaned
docker compose exec php php bin/console module:build             # build runtime page root
docker compose exec php php bin/console module:assets-sync       # publish module web assets
docker compose exec php php bin/console module:deactivate <id> --confirm
docker compose exec php php bin/console scheduler:run
docker compose exec php php bin/console doctor

# Check unused Composer packages
docker compose exec php vendor/bin/composer-unused

Project Structure

lib/                    # All backend PHP (namespace MintyPHP\)
  App/                  # DI container + bootstrap (AppContainer, Container/Registrars/)
    Module/             # Module platform (Registry, Manifest, Autoloader, Builder)
  Repository/           # SQL queries, prepared statements, filters/paging
  Service/              # Business logic, validation, orchestration
  Http/                 # Auth guards, API auth, request helpers
    Input/              # Request input handling (RequestInput, FormErrors)
  Console/              # CLI command framework (ConsoleApplication, Command base class)
    Commands/           # Command classes (Module/, Scheduler/, Tools/)
  Support/              # Crypto, flash, guard, search, helpers
modules/                # Self-contained feature modules (namespace MintyPHP\Module\<Name>\)
  <id>/module.php       # Module manifest (routes, slots, providers, permissions)
  <id>/lib/             # Module PHP classes (Service, Repository, Providers)
  <id>/pages/           # Module actions + views (symlinked into runtime)
  <id>/templates/       # Module-specific templates
  <id>/web/             # Module CSS/JS (published to web/modules/<id>/)
  <id>/tests/           # Module PHPUnit tests
pages/                  # Core actions (controllers) — file-based routing
  pages/**/*.php        # Action files (read input, check permissions, call services)
  pages/**/*.phtml      # View files (rendering only, no DB calls)
templates/              # Core layouts and partials
  partials/             # Reusable UI components
  emails/               # Email HTML templates
  pdfs/                 # PDF templates (Dompdf)
config/                 # App config (routes, assets, settings cache, themes, modules)
web/                    # Document root (entry point, CSS, JS, static assets)
  js/core/              # DOM utilities, Grid.js factory, component runtime
  js/components/        # Reusable UI components
  css/                  # Layered CSS (base → components → layout → pages)
  modules/              # Published module assets (symlinks to modules/<id>/web/)
storage/                # Uploaded files + runtime state
  runtime/pages/        # Symlinked page tree (core + modules, built by module-build)
db/init/init.sql        # Full schema + seed data (no migration framework)
db/updates/             # Idempotent SQL update scripts for existing installs
tests/                  # PHPUnit tests (namespace MintyPHP\Tests\)
docs/                   # German-language documentation (Markdown)
i18n/                   # Translation files (de, en)
bin/                    # CLI entry point (bin/console) + legacy scripts + shell tools
docker/                 # Dockerfiles, Nginx configs, PHP configs
.agents/                # Agent workflow system (contracts, prompts, checks, skills, runs)

Architecture Rules

Strict Layering (enforce in all changes)

  1. App (lib/App/): DI container bootstrap. Registers all service/repository factories. No business logic.
  2. Repository (lib/Repository/): All SQL lives here. No HTTP, session, or rendering.
  3. Service (lib/Service/): Business rules and validation. No HTML. Four internal sub-types:
    • Service (*Service.php): Business logic + orchestration. Coordinates repositories and gateways.
    • Gateway (*Gateway.php): Adapter for a single external dependency (repository, settings, HTTP API, scope). No orchestration flow.
    • Factory (*Factory.php): Only place inside lib/Service/ that may call new on services/gateways/repositories. Registers via DI container.
    • Policy (*Policy.php in lib/Service/Access/): Authorization decisions per resource type. Returns AuthorizationDecision. No HTTP, no business logic.
  4. Action (pages/**/*.php): Reads input, checks permissions + tenant scope, calls services, sets view vars.
  5. View (pages/**/*.phtml): Pure rendering. No DB calls. HTML escaping via e(...).
  6. Template (templates/): Layouts and partials.

Modules

  • Modules are self-contained feature packages under modules/<id>/
  • Namespace: MintyPHP\Module\<Name>\* — never use core namespaces (MintyPHP\Service\*, MintyPHP\Repository\*)
  • Manifest: module.php declares routes, UI slots, providers, permissions, scheduler jobs
  • UI integration: Only via platform slots (aside.tab_panel, topbar.right_item, layout.head_style, runtime.component, etc.) — no core template hardcoding
  • Session keys: Prefixed with module.<id>.*
  • Activation: config/modules.php or APP_ENABLED_MODULES env override
  • Runtime sync: php bin/module-runtime-sync.php after any module/manifest change (builds page symlinks, syncs permissions, publishes assets)
  • Fingerprint guard: web/index.php validates runtime state matches active modules; fails fast if stale
  • API isolation: API requests (api/ prefix) skip session/auth/cookie flows entirely; modules using API endpoints rely on ApiBootstrap.php

Routing

  • File-based: pages/admin/users/edit($id).php → URL parameter id
  • Module pages: modules/<id>/pages/ symlinked into storage/runtime/pages/ at build time
  • ...(none).phtml → no template layout
  • data().php suffix → data/AJAX endpoints
  • Named aliases in config/routes.php with public flag for auth guard
  • Module routes declared in manifest, merged at boot (fail-fast on collision)

PHP Conventions

  • PSR-4 autoload: MintyPHP\lib/, MintyPHP\Module\*modules/*/lib/, MintyPHP\Tests\tests/
  • All user-facing text uses t('key') translation helper
  • Permissions + tenant scope enforced in actions/services, never just in UI
  • Security/integration settings stay in DB, not in config/settings.php file cache

Frontend Conventions

  • Vanilla ES2022 modules, no bundler
  • CSS classes prefixed with app-
  • Defensive DOM checks (elements may not exist on every page)
  • No business logic in frontend
  • Assets served raw with assetVersion() cache-busting (filemtime-based)

UI Patterns

  • Edit pages: tabs → Master data | Visibility | optional Danger zone
  • Titlebar partial for primary actions (Save, Save & close)
  • Secondary actions in Aside block via app-details-aside-actions.phtml
  • Lists use Grid.js
  • All visible text wrapped in t('...')

Database

  • Schema defined in db/init/init.sql (applied once on container init)
  • No migration framework — schema changes for existing installs are idempotent SQL scripts
  • Settings stored in settings DB table (single source of truth); config/settings.php is a partial file cache for hot-path UI reads only

Quality Gates

  • PHPStan level 5 — scans config/, lib/, modules/, pages/, tests/
  • PHPUnit 11 — bootstrap: tests/bootstrap.php
  • Frontend Smoke-Check — browser console bleibt fehlerfrei in Kernflows
  • composer-unused — periodic check for unused dependencies

Environment

  • Config via .env (gitignored) — copy from .env.example for dev, .env.prod.example for prod
  • config/config.php (gitignored) — copy from config/config.php.example
  • APP_CRYPTO_KEY (64-char hex) needed for AES-256-GCM encryption of SSO secrets