Commit Graph

71 Commits

Author SHA1 Message Date
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
48cb7c9e08 fix: resolve QG-001 typography token drift and QG-006 style violations
Replace raw line-height values with --leading-none/--leading-loose
design tokens in 3 CSS files. Fix 7 PHP style issues: import ordering,
unused imports, brace placement, multi-line argument formatting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 22:56:36 +01:00
fs
fcd8754d94 feat: app icon button round 2026-03-22 22:38:37 +01:00
fs
91d8aa5055 fix: prevent false dirty indicator on read-only detail pages
Async component init (e.g. MultiSelect replacing <select> with hidden
inputs) mutated the DOM after the initial form state snapshot, causing
a phantom "unsaved fields" warning. Re-baseline the initial state on
structural DOM changes until the first user interaction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 22:27:41 +01:00
fs
984d0430d3 fix: restyle tab overflow chevrons to subtle ghost icons with fade masks
Replace prominent outlined chevron buttons with borderless ghost icons
and gradient fade masks for a cleaner overflow indicator. Reset shell-level
button custom properties to prevent global button styles from bleeding through.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 17:26:36 +01:00
fs
2d9ca44c26 fix: save button 2026-03-22 16:52:23 +01:00
fs
7e2a1215d2 fix: repositioned icon on menu 2026-03-22 16:26:27 +01:00
fs
026002a501 feat: extract typography tokens into dedicated file with semantic aliases and a11y fallbacks
Create typography.tokens.css as single source of truth for the type system:
- Extract all primitive tokens from variables.base.css (--text-*, --leading-*, --font-*, --tracking-*)
- Add semantic aliases (--text-body, --text-label, --text-caption, --text-title, --text-page-title)
- Add --text-md (15px) escape hatch and --tracking-wider (0.05em) token
- Add prefers-reduced-motion fallbacks locking fluid headings to fixed midpoints
- Document scale ratio (1.25x major third, 14px base) with reference table
- Migrate h1/h2 in app-shell.css to semantic aliases
- Migrate 4 raw letter-spacing values to --tracking-* tokens
- Extend TypographyTokenContractTest with 3 new tests (letter-spacing, aliases, reduced-motion)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 16:25:51 +01:00
fs
be1314f8b8 fix: connect --app-font-size to --text-base token and remove redundant overrides
--app-font-size was still 100% (16px), disconnected from the type scale
tokens. Now references var(--text-base) so the 14px enterprise baseline
actually takes effect. Remove empty responsive @media font-size placeholders
in variables.base.css and raw heading size overrides in app-shell.css that
fought the clamp()-based tokens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 16:03:10 +01:00
fs
f9676cbacb refactor: rebase type scale at 14px for enterprise-density UI
Shift all typography tokens down to match industry standard for admin
dashboards (Atlassian, Carbon, Primer, SAP Fiori all use 14px base).
Browser root stays at 16px for accessibility zoom compliance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 16:00:24 +01:00
fs
fc2ebe9314 fix: address 6 low-severity findings from typography token code review
- Replace mislabeled sidebar title 10px with var(--text-2xs) (F-001)
- Replace font-size: small with var(--text-sm) in app-shell (F-002)
- Annotate @media heading overrides as potentially redundant with clamp() (F-003)
- Correct type scale comment to "approximate major-third ratio" (F-004)
- Differentiate h5 (--text-sm) from h4 (--text-base) (F-005)
- Tighten contract test to flag bare normal/bold keywords (F-006)

Task run: UI-TYPOGRAPHY-SCALE-002

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 15:56:58 +01:00
fs
e145b7d089 feat: introduce mathematical type scale with single-source-of-truth typography tokens
Define a major-third (1.25) type scale as CSS custom properties in the tokens
layer (--text-2xs through --text-5xl), along with line-height (--leading-*),
font-weight (--font-*), and letter-spacing (--tracking-*) tokens. Migrate all
28 core CSS files from ad-hoc values to token references with clamp()-based
responsive scaling for headings. Add TypographyTokenContractTest to enforce
token-only usage via grep-based assertions.

Task run: UI-TYPOGRAPHY-SCALE-001

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 15:47:55 +01:00
fs
60c27e50cb chore: snapshot notifications hardening and css/docs alignment 2026-03-20 00:05:03 +01:00
fs
fb6e30a062 feat: add notifications module with bell UI, event listeners, and cleanup job
In-app notification system with topbar bell icon, dropdown panel,
mark-as-read/dismiss actions, and scheduled cleanup of old read
notifications. Includes event listeners for user.created and
user.deleted events, authorization policy, and full test coverage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 22:09:44 +01:00
fs
3147009498 Fix tabbed form validation handling 2026-03-19 21:41:20 +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
93a1d95c07 docs: add CLI command reference and update key docs to use bin/console
New docs/reference-cli-commands.md covers all commands, bootstrap helpers,
and how to add new commands. Updated lokale-entwicklung, entwickler-checkliste,
betriebscheck-doctor, index, and web/index.php error message to reference
bin/console instead of legacy bin/*.php scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:25:38 +01:00
fs
5739cc1200 Refactor helper drift in lib: centralize theme/translation and remove app() hotspots 2026-03-19 08:23:14 +01:00
fs
476f688bd8 harden: web/index.php — runtime fingerprint, API channel isolation, extract() safety
Three robustness improvements to the request entry point:

P1a: Module runtime stale-detection via fingerprint
- ModuleRuntimePageBuilder gains writeFingerprint/readFingerprint/expectedFingerprint
- module-build.php writes storage/runtime/.module-fingerprint after each build
- web/index.php validates fingerprint on every request; throws RuntimeException
  with actionable message if stale (replaces silent auto-build in request path)
- Eliminates P2 (concurrency) by removing build from hot path entirely

P1b: API requests skip session/auth/cookie flows
- Channel detection (isApiRequest) moved before Session::start()
- Session::start(), remember-me, session timeout, tenant refresh and locale
  resolution wrapped in if-not-API guard
- API endpoints no longer set cookies or trigger login redirects
- Default locale set separately for API so t() works in error responses

P3: extract(Router::getParameters(), EXTR_SKIP)
- Prevents URL parameters from overwriting existing scope variables

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 22:41:59 +01:00
fs
c328067aa6 refactor: align addressbook module to MintyPHP\Module\AddressBook namespace
Migrates addressbook service classes from core namespace
(MintyPHP\Service\AddressBook\*) to proper module namespace
(MintyPHP\Module\AddressBook\Service\*), consistent with the
bookmarks module pattern.

Moved to module:
- AddressBookService → modules/addressbook/lib/Module/AddressBook/Service/
- AddressBookServicesFactory → modules/addressbook/lib/Module/AddressBook/Service/
- AddressBookServiceTest → modules/addressbook/tests/Module/AddressBook/Service/
- Pages, templates, CSS, JS all in module directory

All module PHP classes now live under MintyPHP\Module\<Name>\*,
enforced by ModuleStructureContractTest::testModuleClassesUseModuleNamespace.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 22:20:54 +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
921977bdd3 create without tab storage local 2026-03-14 16:08:19 +01:00
fs
00366d7000 UI max width details 2026-03-14 15:58:10 +01:00
fs
e1dac186ac fix: add background keepalive ping to sync frontend idle timer with server
Prevents session timeout for users who stay active on a single page
(scrolling, reading) without making requests. Pings every 5 min only
when interaction was detected since last sync — no false keep-alive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 15:57:36 +01:00
fs
a3a403c2ec refactor: wrap global search in exported init function with destroy() cleanup
Convert app-global-search.js from a self-executing module to an
exported initGlobalSearch() function following the established
component pattern. Extract 6 inline handlers to named variables,
add destroy() for proper listener cleanup, double-bind guard,
and return a public API (destroy, openSearch, focusSearch).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 23:01:04 +01:00
fs
35a36f1144 fix(security): replace innerHTML with safe DOM APIs, add destroy() cleanup
Replace innerHTML assignments in app-tabs.js and app-password-toggle.js
with createElement/appendChild to prevent potential XSS vectors. Add
destroy() methods to app-tabs, app-filter-drawer, and
app-toggle-aside-panels so document/window-level listeners can be
properly removed when components are torn down.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 22:35:01 +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
d9f07dcd63 fix: web/ quick wins — CSS cleanup, ARIA tabs, and file header comments
CSS:
- Remove duplicate li::before block in app-search.css
- Fix typo: search-reuslt → search-result in app-search.css
- Remove commented-out CSS rules in app-flash.css
- Add descriptive header comment to all 27 CSS component files

JS:
- Complete WAI-ARIA Tabs pattern: generate IDs, add aria-controls on
  tab buttons and aria-labelledby on tab panels (app-tabs.js)
- Add JSDoc header comments to ~33 JS files (core + components)
- Add explanatory block comment to app-boot.js (why classic IIFE)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 22:21:37 +01:00
fs
ee5930d728 style: update app-tabs and sidebar components
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:59:09 +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
a27b6a96ff fix: dismiss stale session-timeout flash on auto-login, resolve PHPStan and i18n issues
- Add Flash::dismissByKey() to clear flash messages by key+scope
- Dismiss 'session_timeout' flash after successful remember-me auto-login
  so the message doesn't persist through manual logout
- Suppress PHPStan false positives for dynamically defined MINTY_ALLOW_OUTPUT
- Remove unnecessary ?? [] fallbacks on preg_match_all results in tests
- Add missing i18n key 'No active roles are configured yet.'

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 18:56:19 +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
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
e9f73bc96a ui changes and role switch added 2026-03-12 09:41:18 +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
f94fa6ba2f Rename app branding from IMVS to CoreCore 2026-03-11 20:11:01 +01:00