Commit Graph

33 Commits

Author SHA1 Message Date
fs
53ccd212d5 docs(agents): encode list-export convention as GR-UI-EXPORT guard
Make the core-primitive-end-to-end rule for Grid.js list exports binding
instead of advisory — so future consumers (and reviewers) cannot quietly
drift back into inline fputcsv / hand-rolled headers / bespoke click
listeners / lurl() for query-carrying URLs.

- CLAUDE.md: new UI Patterns bullet + two "Never Do This" entries
  spelling out the server/view/client contract in one place.
- .agents/checks/guard-catalog.json: new GR-UI-EXPORT entry describing
  the end-to-end requirement (exportRequireGetRequest + exportCapLimit +
  exportSendCsv + ExportColumn + shared filter-schema + dropdown partial
  + endpointUrl() + initListExport).
- .agents/checks/guard-enforcement-map.json: wire the new guard to
  tests/Architecture/ListExportContractTest.php as the automated
  evidence source.
- .agents/checks/guard-checklist.md & .agents/prompts/reviewer-code.md:
  add GR-UI-EXPORT so the Code Reviewer prompt and the checklist flag
  violations alongside GR-UI-LIST.
- tests/Architecture/ListExportContractFiles: registry of every list
  export (currently helpdesk-domains, admin/users, audit/system-audit).
  Adding a new list = one entry, contract test covers the rest.
- tests/Architecture/ListExportContractTest: six checks per registered
  entry — endpoint uses the primitive, no hand-rolled output, data and
  export share the same filter-schema, template includes the dropdown
  partial and uses endpointUrl(), page module imports and invokes
  initListExport, and the shared dropdown partial stays zero-config.
- pages/admin/users/export().php: align with the new contract by
  switching from ad-hoc requestInput()->queryAll() reads to
  gridParseFiltersFromSchemaFile(__DIR__ . '/filter-schema.php'), same
  as the data endpoint — eliminates the last place Grid and export
  could disagree on what "the current filter" means.

Gates: PHPUnit 1900 OK (+6 contract checks), PHPStan 0 errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 22:50:43 +02:00
fs
0e82e00495 feat(core): endpointUrl() helper — query-safe URLs for module routes
Introduce a helper that returns the registered route TARGET for a given
source path, so URLs built for endpoints that carry query parameters do
not rely on MintyPHP's applyRoutes() rewrite layer — that layer compares
the full request URI (including `?query`) against source paths and
silently misses modules where path ≠ target.

- core/Support/helpers/app.php: endpointUrl($path) consults
  ModuleRegistry::getRoutes(), returns lurl(target) when the path is a
  registered module source path, otherwise falls through to lurl($path).
  Safe fallback when the container or registry is unavailable.
- modules/audit/pages/audit/system-audit/index(default).phtml: replace
  the ad-hoc target-path workaround with endpointUrl('admin/system-audit/
  export'). Callers can now write the natural source path without
  knowing about the rewrite trap.
- Apply the same helper to modules/helpdesk/.../domains/index and
  pages/admin/users/index for consistency — a no-op where path already
  equals target, but establishes the convention: every export/data
  endpoint URL in page configs goes through endpointUrl().
- tests/Support/Helpers/EndpointUrlTest: 5 cases covering source→target
  resolution, idempotence when path == target, fall-through for
  unregistered paths, leading-slash normalization, and graceful
  degradation when the registry is missing. Uses
  AppContainerIsolationTrait per the contract test in
  tests/Architecture/AppContainerIsolationContractTest.

Gates: PHPUnit 1894 OK, PHPStan 0 errors, module:sync ok.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 22:39:36 +02:00
fs
5ba086adee refactor(admin/users): migrate CSV export to core primitive
Replace the inline export implementation with the new generic primitive
(core/Service/Export + helpers/export + app-list-export.js). No more
hand-rolled fputcsv loop, header setup, or escape closure duplicated
here — one implementation, tested once, reused everywhere.

- export().php: uses exportRequireGetRequest, exportCapLimit,
  exportResolveFlavor, ExportColumn[], exportSendCsv. Phone/mobile/
  short_dial keep allowSignedNumeric=true so +49 numbers render
  untouched.
- export(none).phtml: deleted — headers + fputcsv now live in the
  core helper.
- index(default).phtml: inline <details class="dropdown"> "Export CSV"
  replaced by the reusable app-list-export-dropdown partial, exposing
  CSV and Excel flavors. exportUrl added to pageConfig.
- app-users-list.js: hand-rolled export-button binding removed in
  favor of initListExport({ gridConfig, exportUrl }).
- admin-users-index.js: forwards config.exportUrl into
  initUsersListPage.

Net effect: ~100 lines of duplicated export plumbing removed from the
users page; users gain the Excel flavor for free.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 21:57:31 +02:00
fs
9a4d59eb4c feat: add reusable app-file-upload component with drag-and-drop and preview
Replace bare <input type="file"> across all upload locations with a
card-based dropzone component via shared partial. Three visual states:
current server file (thumbnail + Replace/Delete), empty dropzone, and
pending file preview (local FileReader thumbnail + metadata). Delete
actions use data-confirm-message for confirmation dialog.

Centralized as templates/partials/app-file-upload.phtml to prevent
markup drift — documented as deliberate exception to plain-HTML inputs
convention in CLAUDE.md and developer checklist.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 11:58:14 +02:00
fs
b749b5d192 feat: centralize breadcrumbs in topbar and remove history navigation
Move breadcrumb rendering from individual page templates into the core
topbar. Each page now sets $breadcrumbs in its action .php file; the
topbar renders it automatically via the shared partial.

- Remove global back/forward buttons and app-nav-history.js component
- Remove Alt+Arrow keyboard shortcuts for history navigation
- Render breadcrumb in topbar-left section (replaces button area)
- Clean up breadcrumb CSS: context-neutral base (flex, no margin)
- Recalculate sticky titlebar offset in details container
- Migrate all 41 pages (core + helpdesk, audit, addressbook, api-docs)
- Add missing breadcrumbs to addressbook detail view
- Update architecture contract tests (nav-history references removed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 17:17:06 +02:00
fs
7a222f0b1f fix(audit): harden module isolation and fix post-extraction drift
Fix 5 broken FQCN references (runtime errors) where core pages referenced
non-existent MintyPHP\Service\Audit\AuditMetadataEnricher and SystemAuditService.
Add AuditMetadataEnricherInterface with NullAuditMetadataEnricher fallback so
deactivating the audit module no longer crashes core edit pages.

Move audit search resources from core Search*Provider files into the module
via a new AuditSearchResourceProvider implementing the existing
SearchResourceProvider contract. Add module-specific purge permissions
(audit.api.purge, audit.imports.purge) replacing core ABILITY_ADMIN_SETTINGS_UPDATE.

Also fixes: session key prefix convention, hardcoded English string, $_SERVER
superglobal fallback, and manifest schema drift (i18n_path, group in ui_slots).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 10:03:27 +01:00
fs
06e619f26c feat: show "View X" instead of "Edit X" for read-only users
Titlebar, breadcrumbs, and page title now reflect the user's actual
permission level across all 6 edit pages (roles, users, departments,
tenants, permissions, scheduled jobs). Added i18n keys for de and en.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 22:28:19 +01:00
fs
c429ff43cd refactor: fix 7 CRUD system inconsistencies for robustness and maintainability
- Add user-assignment dependency check to DepartmentService.deleteByUuid (409 when users assigned)
- Standardize POST detection to isMethod('POST') in 10 create/edit actions
- Align RoleService code uniqueness to warning pattern (matching departments)
- Normalize repository create() return types from mixed to int|false (3 repos + 3 interfaces)
- Add JSON response branches to 4 non-user delete actions
- Document delete authorization ordering pattern
- Decompose AdminSettingsService.updateFromAdmin into domain-scoped private methods

Workflow: .agents/runs/CRUD-CONSISTENCY-001/
Reviewed by: Code Reviewer (pass), Security Reviewer (pass), Acceptance Tester (pass)
Quality gates: QG-001 PHPUnit pass, QG-002 PHPStan pass, QG-003 Architecture pass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:25:33 +01:00
fs
72311ddb97 fix: standardize save buttons to use app-action-success class
Replace inconsistent `primary` class with `app-action-success` on all
standalone save buttons so they match the green titlebar convention.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 16:48:57 +01:00
fs
60c27e50cb chore: snapshot notifications hardening and css/docs alignment 2026-03-20 00:05:03 +01:00
fs
c7b8fd516a feat: extend module platform with UI slots, runtime components, CLI tooling and {{userId}} search support
Completes the generic module platform that enables modules to contribute
UI elements, runtime JS components, and search resources without any
core hardcoding.

New generic UI slot types:
- topbar.right_item: module-contributed topbar buttons
- layout.body_end_template: module-contributed dialog/overlay templates
- layout.head_style: module-contributed global CSS
- runtime.component: declarative JS component registration with phase ordering

New infrastructure:
- ModuleAutoloader: PSR-4 autoloading for module-local PHP classes
- ModuleRuntimePageBuilder: symlinks module pages into runtime directory
- ModuleRuntimeAssetPublisher: publishes module CSS/JS to web/modules/
- ModulePermissionSynchronizer: syncs module permissions to DB
- CLI scripts: module-runtime-sync, module-build, module-migrate,
  module-permissions-sync, module-assets-sync
- {{userId}} placeholder in SearchDataService for user-scoped search queries
- Component runtime with phased initialization (early/default/late)
- AppContainer.protectExistingBindings() to prevent module→core overwrites
- Architecture tests: ModuleStructureContractTest, CoreTemplateIsolationTest,
  FrontendComponentRuntimeContractTest, AppContainerIsolationContractTest

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 22:19:56 +01:00
fs
921977bdd3 create without tab storage local 2026-03-14 16:08:19 +01:00
fs
aaea038619 assign role roles 2026-03-13 21:11:48 +01:00
fs
010690de19 refactor(actions): deduplicate audit metadata and grid user count enrichment 2026-03-13 12:05:11 +01:00
fs
892da0048d refactor(arch): enforce gateway compliance and remove service-wrapping gateways 2026-03-13 11:31:33 +01:00
fs
082fa4c9a5 empty states 2026-03-13 09:49:11 +01:00
fs
cb7256aebc variablen und empty states 2026-03-12 16:47:53 +01:00
fs
277168f7e8 feat(admin): preserve list return target for back and close actions 2026-03-11 23:32:11 +01:00
fs
71b2d4a696 Extend users detail empty states to remaining non-list areas 2026-03-11 22:05:03 +01:00
fs
4885135849 Adopt global empty-state for remaining user form empties 2026-03-11 21:42:43 +01:00
fs
a1c7c9cf7d Standardize global empty-state UI component 2026-03-11 21:38:15 +01:00
fs
fd90065048 fix(security): add CSRF protection to all POST endpoints + contract tests (B2)
CSRF guards added to 16 admin pages that previously accepted POST requests
without token verification (GR-SEC-001): departments, permissions, roles,
settings, tenants, users (create/edit/bulk/tokens), and lang switch.

New contract tests:
- PostEndpointCsrfContractTest: scans all pages/ for POST handlers and
  verifies checkCsrfToken is present (API/data endpoints exempt).
- DatabaseUpdatesContractTest: validates db/updates/ scripts follow naming
  convention and use idempotent SQL patterns (GR-CORE-010).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:40:07 +01:00
fs
fb6f87374f fix(theme): stabilize tenant switch theme propagation and toggle race handling
Task: REVIEW-USER-THEME-001
2026-03-07 20:14:29 +01:00
fs
205da203cc refactor(pages): replace superglobals with request/session abstractions 2026-03-06 11:28:22 +01:00
fs
9a08f96c11 agent foundation 2026-03-06 00:44:52 +01:00
fs
c5f657c8c8 listen ansichten verbessert 2026-03-05 11:17:42 +01:00
fs
4b31fc7664 Repo Interface für tests 2026-03-05 08:26:51 +01:00
fs
8f4dd5840d major update 2026-03-04 15:56:58 +01:00
fs
16759a2732 weitere updates für instanzierbarkeit und sauberes testing 2026-02-24 08:49:40 +01:00
fs
99db252f60 instances added god may help 2026-02-23 12:58:19 +01:00
fs
25370a1a55 add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
fs
3eb9cc0ac4 big restructure 2026-02-11 19:28:12 +01:00
fs
cd59ccd99b baseline 2026-02-04 23:31:53 +01:00