Commit Graph

163 Commits

Author SHA1 Message Date
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
2f0f407268 feat(helpdesk): redesign dashboards with KPI groups, skeleton loading, and unified spacing
Restructure Support dashboard into 2 KPI groups (Tickets + Contracts) with
section dividers, merge escalations and recommendations into "Attention needed".
Redesign Sales dashboard with clickable contract timeline and dialog.
Add CSS shimmer skeleton loading for all dashboard tabs and aside.
Unify vertical rhythm via * + * sibling combinator on tab content containers.
Remove ~265 lines of dead CSS (contract cards, escalation styles) and unused JS
functions. Refactor hydrateTicketCategoryFilter into generic hydrateSelectFilter.
Fix role="button" CSS bleed from shell and remove extra future year from timeline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 16:32:34 +02:00
fs
aee9cb10f3 feat(helpdesk): add dashboards, communication feed, settings UI and fix routing
Add support/sales/controlling dashboards with KPIs, trend charts and
risk indicators. Add debitor communication timeline, contact filters,
system recommendations engine, and configurable controlling risk rules.

Rename search→index to fix query-string preservation on back navigation.
Remove fake escalation rate metric, add KPI info tooltips, and switch
trend chart colors to red (created) / green (closed) for clarity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 18:34:03 +02:00
fs
a0d7670dd7 feat(helpdesk): align module with core list/drawer standards
- add helpdesk module pages, services, settings and tests

- standardize debtor list on drawer/grid contracts and robust filter drawer behavior

- add helpdesk aside panel navigation and settings visibility provider

- switch primary list slug to helpdesk/debitor and remove helpdesk/search compatibility

- include required core contract updates for list contracts and detail/drawer integration
2026-04-02 17:48:27 +02:00
fs
5699bc6c5b refactor(config): remove runtime config files and centralize route/bootstrap 2026-04-01 20:27:42 +02:00
fs
dba589b495 chore(agents): implement v2 hardening and enforcement-ready QA 2026-04-01 19:41:56 +02:00
fs
7121732fcf refactor(cli)!: hard-cut legacy scripts and standardize console runtime
- remove legacy bin/module-*.php and bin/doctor.php entry scripts

- move module/doctor execution into class-based runners under lib/Console

- add stable JSON output for doctor and module:sync

- introduce bin/dev for init/up/down/logs/console/qa workflow

- update DI wiring, phpstan scan config, tests, and docs to new CLI contract
2026-04-01 17:14:20 +02:00
fs
83b65812d0 little refactore 2026-04-01 16:31:59 +02:00
fs
5b2ea6bf27 refactor(addressbook): move from aside icon-bar to explorer nav link
Introduce generic explorer.nav_item slot type in app-main-aside.phtml
so modules can contribute links to the explorer nav panel.

Switch addressbook module from aside.tab_panel to explorer.nav_item.
Remove aside department-filter panel, AddressBookLayoutProvider, and
AddressBookSessionProvider (only served the now-removed aside panel).

Fix grid Name column overflow into Email column: CSS selector
.grid-name-cell > span:last-child never matched the <a> name link;
changed to :last-child and scoped flex-shrink:0 to :first-child only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 15:06:15 +01:00
fs
570e3923b7 refactor(audit): remove factory chain and repository interfaces
Remove AuditRepositoryFactory and AuditServicesFactory — two-layer
factory chain replaced by direct DI container wiring. Delete 4
single-consumer repository interfaces. Register all 4 repositories
and SystemAuditRedactionService directly in container. Update all
service constructors to type-hint concrete classes. Fix architecture
test and documentation references to deleted factories.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 12:33:59 +01: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
e10b1215da fix(audit): restructure module pages to avoid admin/ path collision
Module pages must use a unique top-level directory (audit/) instead of
nesting under admin/ which collides with core's pages/admin/ during
module:build symlink creation. Routes still map admin/* URLs to the
audit/ page directory via manifest route targets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 08:13:37 +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
c609753570 refactor(tests): remove redundant tests and fix assertion style
Remove subset/duplicate architecture tests already covered by broader
checks, and replace assertTrue(true) with self::addToAssertionCount(1)
for explicit no-exception-thrown intent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 18:46:49 +01:00
fs
cb5f7037b2 Harden module runtime: audited listener failures and DI-first resolver 2026-03-25 10:02:03 +01:00
fs
80f48f4aba fix: option to supress vendor deprecation 2026-03-25 07:39:08 +01:00
fs
d1eeac6692 feat: add LDAP authentication as per-tenant login method
Add LDAP as a third authentication option alongside local password and
Microsoft Entra ID SSO. Per-tenant configuration supports Active Directory,
OpenLDAP, and FreeIPA with configurable attribute mapping, search-then-bind
and direct-bind methods, encrypted bind credentials (AES-256-GCM),
profile sync on login, and user auto-provisioning via external identity
linking.

Includes admin UI for connection settings with test-connection button,
login page LDAP form, 25 new PHPUnit tests, and de/en translations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 07:26:04 +01:00
fs
a0d816caaa fix(error): harden logging, i18n, a11y and handler tests 2026-03-24 22:00:14 +01:00
fs
ad9101df8e feat: add developer error page with request ID tracking and structured logging
Custom-built error handler for the web channel that shows a tabbed debug
dashboard (exception, request context, environment, SQL queries) in dev mode
and a clean branded error page with copyable request ID in prod mode.
All errors are logged as JSON lines to storage/logs/errors/ for lookup by
request ID. Uses the project's design tokens for visual consistency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:49:22 +01:00
fs
c34e62d729 harden: restore gate baseline, split dev/prod PHP profile, atomic module runtime build
Phase A — Gate Reliability:
- Fix typography token violations in app-breadcrumb.css
- Switch QG-006 from composer cs:check to direct php-cs-fixer
- Align all docs/skills with new gate command

Phase B — Production Profile:
- Multi-stage Dockerfile: dev (xdebug) / prod (no xdebug)
- Compose files target explicit build stages

Phase C — Module Runtime Hardening:
- Atomic staging+swap build in ModuleRuntimePageBuilder
- SHA-256 fingerprint from manifest content + page entries
- 11 new regression tests for build safety and fingerprint drift

Task: STARTERKIT-HARDENING-ONPREM-001

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:13:16 +01:00
fs
1c5648c727 fix: replace grid action column with link-column on primary data cell
Remove the dedicated "Edit"/"Open" action button column from all list
pages. Instead, wrap the primary data column (name, description, subject,
etc.) in a clickable <a> link via the new rowInteraction.linkColumn option.

Double-click, Enter-key, and click-to-focus row navigation preserved.
Pages with explicit actions config are unaffected. Address-book opts out
of auto-wrapping (linkColumn: false) and renders the link in its own
formatter to avoid nested <a> with avatar lightbox.

Also fixes pre-existing XSS in insertActionColumn (unescaped href/label)
and updates typography test for --text-page-title token change.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:43:03 +01:00
fs
07fbb96246 test: add PHPUnit coverage for 7 critical Tier 1 services (GR-TEST-001)
199 new tests across 9 files covering auth, user lifecycle, and settings:
- ApiTokenService: create/validate/rotate/revoke, timing-safe hash, tenant scope
- ApiTokenEndpointService: pagination, scope filtering, tenant resolution, expiry
- SsoUserLinkService: 2-phase identity lookup, provisioning, profile+avatar sync
- UserAssignmentService: sync methods, assignable-role freeze, transactions
- UserLifecycleAuditService: encrypted snapshots, enum normalization, retention
- UserLifecycleRestoreService: full restore flow, 9 error exits, rollback
- AdminSettingsService: API/lifecycle, Microsoft/telemetry, color/SMTP validation

Workflow: TEST-TIER1-001 (Analyst → Planner → Executor → Code Review → Security Review → Acceptance → Finalizer — all pass)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 23:29:07 +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
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
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
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
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
be8bf496cb test: add architecture contract tests for layering, sessions, and asset versioning
New contracts enforce repository layer isolation, no HTML in services,
no DB calls in views, module session key prefixes, and asset versioning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 14:15:41 +01:00
fs
555199b217 fix: PHPStan and test strictness improvements
Add bin/ scripts to PHPStan scanFiles, suppress property.onlyWritten for
by-ref test properties, add exhaustive default match arm, use explicit
expects() on mock stubs, fix data provider return type, and simplify
redundant null check in NotificationServiceTest.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 14:15:36 +01:00
fs
141f0a0155 refactor: extract shared code from bin/ scripts and remove legacy scheduler runner
- Extract ModuleManifestLoader for standalone manifest loading (used by
  module-deactivate and ValidateCommand)
- Extract SqlStatementParser, ModuleMigrationRepository, and
  ModuleMigrationService from bin/module-migrate.php to enforce strict
  layering (SQL in repository, orchestration in service)
- Delete bin/scheduler-run.php (fully superseded by bin/console scheduler:run)
- Update docs and test fixtures to reference bin/console

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:45:16 +01:00
fs
975651b183 fix: eliminate $_SESSION drift in SessionProvider and add notification UI states
Pass AppContainer to SessionProvider::clear() so all module providers use
SessionStoreInterface consistently instead of raw $_SESSION. Also add
loading and error states to the notification bell dropdown (GR-UI-014).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 22:49:03 +01:00
fs
1f0b1caf54 feat: module-owned i18n with merge-at-boot translation loading
Each module can now ship its own i18n/ directory with translation files
(default_de.json, default_en.json). At boot time, ModuleI18nLoader
preloads core translations then merges module translations on top via
Reflection into I18n::$strings — the t() helper stays unchanged.

- Add i18nPath property to ModuleManifest
- Add ModuleI18nLoader with Reflection-based preload
- Extract 59 module-exclusive keys from core i18n into module files
  (notifications: 8, bookmarks: 41, addressbook: 10)
- Expand TranslationKeysTest to scan modules/ and validate against
  merged core + module translations
- Add ModuleI18nContractTest for per-module de/en parity and completeness

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 22:08:34 +01:00
fs
ae74fc3251 Stabilize service suite hygiene 2026-03-19 20:35:15 +01:00
fs
b873efc973 Strengthen settings gateway tests 2026-03-19 20:32:34 +01:00
fs
56c3e30f43 Strengthen service workflow tests 2026-03-19 20:28:04 +01:00
fs
f7b03926b0 Clarify test suite taxonomy 2026-03-19 20:22:10 +01:00
fs
011d662dfc Drop redundant crypto gateway tests 2026-03-19 20:17:11 +01:00
fs
72c7f1b337 Tighten service test signal 2026-03-19 20:15:48 +01:00
fs
28008c008c Trim remember me delegation tests 2026-03-19 20:04:14 +01:00
fs
12bc58dffa chore: remove legacy tools/codex-skills (moved to .agents/skills), split filter drawer tests, clean up stale docs
- tools/codex-skills/ removed — skills now live in .agents/skills/
- docs/reference-agents-*.md removed — replaced by .agents/workflow.md
- FilterDrawerContractTest split into Runtime + Template contract tests
- bin scripts and .gitignore updated for .agents/ paths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:59:08 +01:00
fs
c89501bbed Remove low-value service delegation tests 2026-03-19 19:46:07 +01:00
fs
5c7a1148ac Consolidate settings session policy tests 2026-03-19 19:45:16 +01:00
fs
bc72fa50a6 Consolidate settings normalization tests 2026-03-19 19:43:55 +01:00
fs
83aadb3535 Deduplicate crypto gateway tests 2026-03-19 19:36:17 +01:00
fs
8cd21f3c8a fix: permission sync was deactivating core permissions, not just module-owned ones
deactivateOrphaned() treated ALL is_system=1 permissions as module-owned.
Core seed permissions (users.view, tenants.view, etc.) are also is_system=1,
so they were incorrectly deactivated — breaking admin panel access.

Fix: scan all module manifests on disk (enabled or not) to build the set of
module-owned permission keys. Only deactivate permissions whose key appears
in that set. Core seed permissions are never touched.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:32:36 +01:00
fs
e40cba23a1 Split list titlebar contracts 2026-03-19 19:29:45 +01:00
fs
ba1186c525 refactor: console improvements — auto-discovery, centralized bootstrap, per-command help
- ConsoleApplication.discoverCommands() scans lib/Console/Commands/ automatically;
  adding a new command no longer requires editing bin/console
- Command base class provides bootstrapApp(), bootstrapModuleApp(), requireBinScript()
  and projectRoot() helpers — eliminates fragile 4-level relative require_once paths
- Per-command --help support via optional usage() method on Command
- Docker-compose scheduler updated to use bin/console scheduler:run
- Old bin scripts now emit deprecation hint to stderr when called directly

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:16:36 +01:00
fs
f7787465f7 Split aside navigation contracts 2026-03-19 19:13:51 +01:00
fs
115723fcd6 Split auth login accessibility contracts 2026-03-19 19:12:25 +01:00