Commit Graph

48 Commits

Author SHA1 Message Date
fs
b871dacde2 refactor(ui): move Documentation and System Info from admin to help panel
Remove Documentation and System Info nav items from the admin sidebar
System group — they now live in the help-center panel. The admin
System group retains only Settings. Removes unused $canViewSystemInfo
variable from the sidebar template.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 14:30:48 +01:00
fs
02a7d2fe90 feat(api-docs): extract API docs viewer into standalone module
Move the Swagger UI viewer from core (pages/admin/api-docs/) into
modules/api-docs/ as a self-contained module. Create module manifest
with routes, permission, sidebar.admin_nav_item slot, asset group,
and authorization policy. Remove API docs ability from core
OperationsAuthorizationPolicy and UiCapabilityMap. Remove hardcoded
sidebar nav item — now contributed via module slot. Add
admin-automation group meta to sidebar template for module nav items.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 14:02:42 +01:00
fs
6ea3c2b88c feat(ui): standardize dialog widths with tiered size system (sm/md/lg)
Add three reusable size tier classes (app-dialog-sm, app-dialog-md,
app-dialog-lg) to base dialog CSS, replacing per-variant max-width
rules. Each tier uses width: min(Xrem, calc(100vw - 2rem)) for
consistent fixed widths with responsive mobile fallback.

- Confirm dialog + session warning: app-dialog-sm (24rem)
- Bookmark + bookmark group dialog: app-dialog-md (32rem)
- Remove max-width from app-confirm-dialog.css and app-bookmark-form.css

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 10:48:12 +01:00
fs
cd4055894d fix(sidebar): render audit module nav group as details/summary section
Module-contributed sidebar.admin_nav_item slots are now rendered as
complete <details><summary> nav groups appended to the admin panel,
matching the same pattern as core groups (Organization, Roles, etc.).

Fixes undefined $moduleNavItemSlots by reading layoutNav early.
Merges mail log into the module-contributed Audit & logs group when
both exist.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 08:22:04 +01:00
fs
83d91789c1 feat(sidebar): render module-contributed admin nav items via sidebar.admin_nav_item slot
The sidebar template now reads sidebar.admin_nav_item UI slots from
modules and merges them into the matching admin nav group (by group
key). Module permissions are resolved via layoutAuth which already
includes module UI abilities from ModuleRegistry::getModuleUiAbilities().

This restores audit nav items (API audit, System audit, Import logs,
User lifecycle logs) in the Logs group when the audit module is active.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 08:16:58 +01:00
fs
0c351f6aff refactor(audit): extract audit domain into self-contained module
Move the entire audit subsystem (system audit, API audit, import audit,
user lifecycle audit, frontend telemetry) from core into modules/audit/.

Core decoupling via interface-based injection:
- AuditRecorderInterface replaces SystemAuditService in 10+ core services
- UserLifecycleAuditInterface / ImportAuditInterface for specialized flows
- NullAuditRecorder fallback when audit module is disabled
- ApiBootstrap/ApiResponse use null-safe callable resolvers

Module structure (modules/audit/):
- Manifest with routes, permissions, scheduler jobs, authorization policy
- 9 services, 8 repositories, 6 domain enums, 4 job handlers
- 33 page files, 4 JS files, 8 test files, migration scripts, i18n

Core cleanup:
- OperationsAuthorizationPolicy, UiCapabilityMap, PermissionService
  surgically cleaned of audit-specific constants
- Sidebar template cleared of hardcoded audit navigation
- AuditModuleIsolationContractTest ensures no future core→module coupling

All quality gates pass: 1346 tests (19,276 assertions), PHPStan level 5
clean, architecture contracts verified.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 21:12:49 +01:00
fs
44620bd786 fix: refactor breadcrumb partial to WAI-ARIA best-practice pattern
- Replace <div>+<i> structure with <nav aria-label>+<ol>+<li>
- Move separators from DOM to CSS pseudo-elements (li+li::before)
- Add hover/focus-visible states and color differentiation
- Replace hard-coded px values with design tokens
- Explicitly reset shell nav/ol/li rules for self-contained styling
- Add i18n key for breadcrumb nav landmark label

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 14:51:40 +01:00
fs
3c0821fcd7 fix: small aside sidebar and search ui/ux changes 2026-03-24 14:21:32 +01:00
fs
0c334731b2 fix: add P0 accessibility fixes to sidebar icon bar and search form
- Add :focus-visible outline to icon bar buttons/links (desktop + mobile)
- Add aria-label to icon bar <nav> for screen reader landmark distinction
- Add role="search" to sidebar search form
- Add "Main menu" / "Hauptmenü" translation key

Workflow: A11Y-SIDEBAR-P0-001

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 14:12:49 +01:00
fs
fcd8754d94 feat: app icon button round 2026-03-22 22:38:37 +01:00
fs
2d9ca44c26 fix: save button 2026-03-22 16:52:23 +01:00
fs
cf8c59d3f8 feat: add read-only System Info admin page with health checks and module inventory
New page at /admin/system-info with three tabs:
- Overview: PHP version, SAPI, environment, 6 health checks (DB, schema,
  storage, RBAC baseline, admin role, scheduler heartbeat)
- Modules: table of active modules with version, dependencies, permission count
- Permissions: active/inactive counts and per-source breakdown

Gated behind new system_info.view permission assigned to Admin role.
No mutations — purely diagnostic/observability.

Includes SystemHealthService, SystemInfoService, SystemHealthRepository
with interface, DI registration, i18n keys (de+en), idempotent DB update
script, and 17 new PHPUnit tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 15:08:02 +01:00
fs
1ba6829a1c fix: toast visibility — opaque backgrounds and flash scope matching with query strings
Two bugs in the toast redesign:

1. Variant backgrounds (success/warning/info/error) used rgba with 12-20%
   opacity, making toasts semi-transparent over page content. Fixed by
   layering the tint over a solid background via linear-gradient compositing.

2. Flash messages with scoped paths including query strings (e.g.
   edit pages with ?return=...) were not matched by Flash::peek(Request::path())
   since path() strips the query. Added fallback to pathWithQuery() matching.

Also moved flash partial before JS init scripts to ensure DOM is present
when the component runtime mounts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:58:15 +01:00
fs
bc72fa50a6 Consolidate settings normalization tests 2026-03-19 19:43:55 +01:00
fs
4871c6032e feat: extract bookmarks as standalone module with MintyPHP\Module\Bookmarks namespace
Moves bookmarks from core hardcoding into modules/bookmarks/ as a
fully self-contained module, following the same pattern as addressbook.

Module contributions via platform slots:
- aside.tab_panel: bookmark sidebar panel
- topbar.right_item: bookmark toggle button
- layout.body_end_template: bookmark/group dialogs
- layout.head_style: bookmark CSS (form + sidebar)
- runtime.component: bookmark-save and bookmark-panel (phase: late)
- search.resource_item: bookmarks in global search (user-scoped via {{userId}})

Backend fully in module namespace (MintyPHP\Module\Bookmarks\*):
- Service: BookmarkService, BookmarkServicesFactory, BookmarkRepositoryFactory
- Repository: BookmarkRepository, BookmarkGroupRepository, BookmarkNavigationRepository
- Support: BookmarkUrlNormalizer
- Providers: BookmarksSessionProvider, BookmarksLayoutProvider, BookmarksSearchProvider

Core cleanup:
- Removed all bookmark-specific markup from core templates
- Removed core DI registrations for bookmark services
- Removed core bookmark pages, JS, CSS
- AuthSessionTenantContextService delegates to module SessionProvider

Architecture guards:
- NoBookmarksHardcodingTest: verifies zero bookmark references in core
- testModuleClassesUseModuleNamespace: prevents core namespace leakage

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 22:20:20 +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
c364e2b46d feat: introduce module system and extract address book as first module (MODULAR-MONOLITH-V1-001)
Add a module kernel (ModuleManifest, ModuleRegistry) that allows modules to
contribute routes, UI slots, search providers, layout context, session
lifecycle, and permissions. Modules are activated via config/modules.php or
APP_ENABLED_MODULES env variable. Conflicts (duplicate routes, permissions,
slot keys) cause a fail-fast with a clear error message.

Extract the address book from hardcoded Core integration points into the
first module (modules/addressbook/). The module provides:
- Aside icon-bar tab + People panel via UI slot system
- Global search resource via AddressBookSearchProvider
- Layout context data via AddressBookLayoutProvider
- Session lifecycle via AddressBookSessionProvider

Core cleanup removes address-book hardcodings from SearchSqlResourceProvider,
SearchUiMetaProvider, SearchItemMapperProvider, appBuildLayoutNavContext(),
and the aside templates. Permissions (ADDRESS_BOOK_VIEW) and business logic
(AddressBookService) remain in Core as they gate general user visibility.

Includes 38 new tests (894 total), PHPStan level 5 clean, and architecture
tests verifying zero hardcoded address-book references in search/templates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 15:43:25 +01:00
fs
d9805c45d3 fix: address code review findings for bookmark feature (H1–L5)
Fix broken tests (H1), align interface signatures with implementations (H3),
remove dead code (H4), add missing input guard (M1), replace raw $_SESSION
access with SessionStoreInterface (M2), sync update script schema (M4),
use shared getAppBase utility (L2), document fragment stripping (L3),
and apply app- CSS class prefix convention (L5).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 22:58:07 +01:00
fs
9688848401 Global Boomarks 2026-03-14 21:45:58 +01:00
fs
1cc63a5fbe fix: add missing system-audit search key to sidebar template
The backend returns system-audit results but the sidebar had no
matching <li data-search-key="system-audit"> element, causing a
console warning on every global search query.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 22:40:48 +01:00
fs
2b915f5a43 refactor: extract shared form utils, add aria-live regions and reduced-motion support
DRY duplicated helpers (escapeAttr, belongsToForm, isSubmitControl,
isEditableTarget) into web/js/core/app-form-utils.js and update 7
consumers. Add aria-live="polite" to flash messages, async messages,
and search results for screen reader announcements. Add
prefers-reduced-motion support to CSS tooltips.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 22:28:46 +01:00
fs
ad8f30cb09 feat(security): add Content-Security-Policy headers with strict script-src
Eliminate all inline scripts to enable script-src 'self' without
'unsafe-inline', providing strong XSS mitigation via CSP.

Inline script removal:
- login.phtml: replace inline APP_ASSET_BASE with data-asset-base
  attribute + app-boot.js (matching default.phtml pattern)
- api-docs: extract SwaggerUI init to js/pages/admin-api-docs-index.js
- docs: extract checkbox enablement to js/pages/admin-docs-index.js
- language-switcher: replace onchange handler with data-auto-submit
  attribute + js/components/app-auto-submit.js event listener

CSP policy (dev + prod nginx):
  default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline';
  img-src 'self' data:; font-src 'self'; connect-src 'self';
  form-action 'self'; base-uri 'self'; frame-ancestors 'none';
  manifest-src 'self'

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 19:24:10 +01:00
fs
e1c211069e fix(session): preserve intended URL across session timeout with remember-me
Session timeout redirected to /de/login?return_to=... but the remember-me
cookie was not cleared by logoutDueToSessionTimeout(). On the next request,
autoLoginFromCookie() silently re-logged the user in, causing the MintyPHP
router to resolve the login route to pages/index().php (dashboard) instead
of the login action — the intended URL redirect logic never executed.

Fix: intercept ?return_to= immediately after successful auto-login in
index.php and redirect to the sanitized route path. Also harden the login
flow with hidden return_to form fields and POST body fallback for cases
without remember-me.

Additional improvements in this commit:
- Convert stored REQUEST_URI to router-compatible path (strip leading
  slash and locale prefix) via IntendedUrlService::toRoutePath()
- Consolidate duplicate CSRF data attributes into shared data-csrf-key
  and data-csrf-token on <html> element
- Add tenant branding (logo) to auth pages via appAuthLogoUrl() helper

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 18:28:13 +01:00
fs
add5cca222 settings cache 2026-03-13 14:38:58 +01:00
fs
04995e3712 feat(session): preserve intended URL across session timeout and add expiry warning dialog
When a session expires, the user's current URL is now captured and restored
after re-authentication (via remember-me cookie or manual login), instead of
always redirecting to the dashboard. A JavaScript session warning dialog
appears ~2 minutes before idle timeout, allowing users to extend their session
with a single click. Includes open-redirect prevention via URL validation,
Microsoft SSO callback support, and 33 unit tests.

Refs: SESSION-REDIRECT-PRESERVE-001

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:28:49 +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
0b9014dcbf page update 2026-03-12 14:09:06 +01:00
fs
39a113c5fc fixed wrong warning with single tenant 2026-03-12 12:22:36 +01:00
fs
24a6b79f7a Fix tenant SSO status mode and refactor status UI tiles 2026-03-12 10:01:24 +01:00
fs
1cdd7e59c1 chore(ui): update shell layout and header/footer partials 2026-03-11 23:33:17 +01:00
fs
277168f7e8 feat(admin): preserve list return target for back and close actions 2026-03-11 23:32:11 +01:00
fs
a1c7c9cf7d Standardize global empty-state UI component 2026-03-11 21:38:15 +01:00
fs
60b890d367 Finalize init defaults and auth flow UX improvements 2026-03-11 21:11:19 +01:00
fs
7153fec05c feat(auth): harden login flows and finalize quality-check coverage 2026-03-07 22:54:33 +01:00
fs
9168730a8a further things around login 2026-03-07 21:21:47 +01:00
fs
e3a0c0eb37 ui/ux login optimization 2026-03-07 14:10:36 +01:00
fs
5fb89485f4 login improvements 2026-03-06 21:59:41 +01:00
fs
9a08f96c11 agent foundation 2026-03-06 00:44:52 +01:00
fs
9819cba733 aside anapssungen 2026-03-05 13:07:43 +01:00
fs
b2dab5bd6c topbar anpassungen 2026-03-05 12:51:53 +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