Files
breadcrumb-the-shire/modules/security/CLAUDE.md

6.1 KiB
Raw Blame History

CLAUDE.md — Security Module

Self-contained MintyPHP module. Namespace: MintyPHP\Module\Security\*. Standalonerequires: [], no dependency on helpdesk. All changes stay inside modules/security/.

After any manifest change (route, permission, slot): docker compose exec php php bin/console module:sync


What it does

Lets the security officer run security checks for customers. A check is created via a wizard (select customer → domain → software product), then tracked on a checklist workspace that combines:

  1. A fixed 7-step internal process (SecurityCheckProcess, identical for every check), and
  2. A per-product technical checklist defined as a reusable template (the product catalog is owned by this module — the templates are the product list).

Overall status (openin_progresscompleted, plus manual archived) is derived from checklist progress. Each step/item records who completed it and when (completion log).


Architecture

lib/Module/Security/
  SecurityAuthorizationPolicy.php   — ability/permission constants + authorize()
  SecurityContainerRegistrar.php    — all DI bindings (add new services here)
  Providers/SecurityLayoutProvider.php — resolves can_* flags for the sidebar
  Repository/                       — SQL only (tenant-scoped, prepared statements)
  Service/
    SecurityCheckProcess.php        — fixed 7-step process + progress/status math (pure, no DI)
    SecurityCheckService.php        — check CRUD, saveState, status derivation, archive
    SecurityCheckTemplateService.php— template CRUD + tech-schema validation/slugify
    SecurityBcSettingsGateway.php   — global BC connection settings (core settings table, encrypted)
    SecurityOAuthTokenService.php   — OAuth2 token acquire + encrypted cache
    SecurityBcGateway.php           — thin BC OData (ONLY customer-search + domains-for-customer)
    SecurityReportPdfService.php    — customer PDF report (Dompdf); picks custom template or built-in PHTML default
    SecurityReportSettingsGateway.php— report HTML/CSS template (core settings table, clear text)
    SecurityReportTemplateService.php— {{var}} substitution into the admin template + default scaffold (pure)
    SecurityReportLogoService.php    — report logo upload/serve (storage/security/report-logo, ImageUploadTrait)
pages/security/                     — actions (*.php) + views (*.phtml)
  checks/report($id).php            — streams the customer report PDF (gated on steps 15 complete)
  report-design/                    — report look config: logo upload + HTML/CSS template editor; logo-file() serves the logo (settings.manage)
templates/aside-security-panel.phtml— sidebar navigation
templates/pdf/customer-report.phtml — built-in default report layout (used when no custom template is stored)
i18n/default_de.json + default_en.json — keep both in sync (identical key sets)
migrations/                         — 003 SQL files (module:migrate)
web/css/security.css | web/js/      — module styles + runtime components + page scripts
tests/Module/Security/Service/      — 10 test files (happy path + edge case)

Permissions (6)

All constants in SecurityAuthorizationPolicy:

Constant Key
ABILITY_ACCESS security.access — gates the main-menu entry
ABILITY_CHECKS_VIEW security.checks.view
ABILITY_CHECKS_CREATE security.checks.create — create + edit the checklist
ABILITY_CHECKS_MANAGE security.checks.manage — archive, delete
ABILITY_TEMPLATES_MANAGE security.templates.manage
ABILITY_SETTINGS_MANAGE security.settings.manage

Gate every action with Guard::requireAbilityOrForbidden(...); tenant scope enforced in repositories.


DB schema

Table Key columns
security_check_templates tenant_id, product_code (uniq), product_name, tech_schema_json, active, version
security_checks tenant_id, debitor_no, domain_no, product_code, template_id, owner_user_id, status, process_state_json, tech_schema_snapshot_json, tech_state_json
security_oauth_token_cache tenant_id, access_token_encrypted, expires_at

tech_schema_snapshot_json freezes the template's checklist onto the check at creation time, so later template edits never mutate in-flight checks. JSON state shapes:

  • tech schema: {version, items:[ {type:"section",label}, {type:"check",key,label,hint?} ]}
  • process_state: {<stepKey>: {done, by, at, note, fields?}}
  • tech_state: {<itemKey>: {done, by, at, note}}

Routes / pages

Main menu entry via the aside.tab_panel slot (icon bi-shield-check, permission security.access). Pages: security/checks (list), security/checks/create (wizard), security/checks/edit/{id} (workspace), security/checks/report/{id} (streams the customer PDF report), security/templates (+create/edit/{id}), security/settings, security/report-design (customer report look: logo + HTML/CSS template), plus data endpoints security/checks-data, security/templates-data, security/customer-search-data, security/customer-domains-data, security/settings/test-connection-data, security/report-design/logo-file (serves the uploaded report logo).

report-design reuses the security.settings.manage permission (no new permission key).

JS runtime components

data-app-component on the container: security-customer-domain-select (wizard domain picker), security-check-workspace (live progress), security-template-schema-editor (checklist editor), security-settings (auth-mode toggle + connection test). List pages load their own web/js/pages/*-index.js via <script type="module">.


Tests

docker compose exec php vendor/bin/phpunit modules/security/tests/ Pattern: mock repositories, ->willReturn(...) / ->willReturnCallback(...) to capture args (avoid ->with()). Every new/changed Service or Gateway needs happy path + edge case.

Deferred (not built)

Internal report PDF (the customer report is built — see SecurityReportPdfService), per-tenant BC connection overrides, per-step assignment, revision history.