Commit Graph

322 Commits

Author SHA1 Message Date
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
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
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
fs
2de0039d4f Split status taxonomy contracts 2026-03-19 19:11:03 +01:00
fs
5582a55208 Split security logging contracts 2026-03-19 19:08:28 +01:00
fs
0bacf2a7a6 Split auth help link contracts 2026-03-19 19:05:29 +01:00
fs
522705dd33 Split detail page contracts 2026-03-19 19:04:28 +01:00
fs
f6046c9168 Split detail action policy contracts 2026-03-19 19:03:10 +01:00
fs
cc653cb4cd Split detail validation contracts 2026-03-19 19:02:04 +01:00
fs
95ab6b8c6c Split module registry contracts 2026-03-19 19:00:29 +01:00
fs
475524bfd4 Rename module extraction contracts 2026-03-19 18:57:03 +01:00
fs
b9f566c49f Split meta architecture contracts 2026-03-19 18:52:36 +01:00
fs
ac9cc4955a Split public page contracts 2026-03-19 18:48:16 +01:00
fs
98520dcc6a Split filter drawer contracts 2026-03-19 18:41:08 +01:00
fs
0f8fff8daf Split frontend runtime contracts 2026-03-19 18:34:02 +01:00
fs
ee5fdaaff7 Split module structure contracts 2026-03-19 18:30:14 +01:00
fs
1e993e470c Refactor architecture test contracts 2026-03-19 18:25:19 +01:00
fs
4dd6d451f6 refactor: relocate agent-system/ to .agents/ with 7-role workflow restructure
Moves the agent workflow system from agent-system/ to .agents/ (dotfile convention).
Restructured from 5-role to 7-role pipeline: adds Analyst and splits Reviewer into
Code Reviewer + Security Reviewer. Removes all old workflow run artifacts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 18:23:04 +01:00
fs
ef72b34c40 feat: module architecture improvements — session keys, dependency graph, event dispatcher, deactivation hooks
Six targeted improvements to the modular monolith platform:

1. Fix AddressBook session key prefix to follow module.<id>.* convention
2. Move ADDRESS_BOOK_VIEW permission constant from core PermissionService into module
3. Add declarative JSON schema for module manifests (.agents/contracts/)
4. Add `requires` field with missing-dependency and circular-dependency detection
5. Add lightweight fire-and-forget event dispatcher (user.created/deleted/login/logout)
6. Add module deactivation hook interface and CLI script (bin/module-deactivate.php)

Includes 15 new architecture/unit tests covering all new functionality.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 18:20:13 +01:00
fs
866d43e15a Refactor bin scripts: shared CLI bootstrap, robust module migrate, and runtime locking 2026-03-19 10:34:35 +01:00
fs
0b7b27409d refactor: remove slot-type validation from ModuleRegistry
Drop UI_SLOT_REQUIRED_KEYS constant and validateUiSlotContributionByType()
(-97 lines). Slot field requirements are now enforced only by architecture
tests (testUiSlotContributionsHaveRequiredKeys, testPanelTemplatesExist)
and by the rendering templates themselves. The registry stays responsible
for key uniqueness, ordering, and module_id tagging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 08:36:37 +01:00
fs
cb27fe090d refactor: simplify module platform — drop custom autoloader, layout_capabilities indirection, and absolute template paths
- Replace ModuleAutoloader with Composer ClassLoader (addPsr4 via spl_autoload_functions)
- Eliminate layout_capabilities mapping; UI slots reference ability strings directly
- Resolve relative template paths in ModuleRegistry instead of baking __DIR__ into manifests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 08:26:45 +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
5da506a20f documentation update with module guidelines 2026-03-18 22:58:15 +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
d3da54ce55 docs: add session management explanation and update rate limiting docs
New explanation page covers full session lifecycle: idle/absolute timeouts,
remember-token mechanics, frontend keepalive, and cookie attributes.
Updates rate limiting docs with remember-token limits and smoke test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 15:57:44 +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
c45c636614 feat(security): add Memcached-based rate limiting for remember-token auto-login
Prevents brute-force attacks against remember-me cookies. Uses Memcached
(Cache::add + increment) to track failures per IP: 5 attempts in 15 min
window, auto-expiring via TTL. Counter resets on successful auto-login.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 15:57:29 +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
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
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
f4ce9f3378 docs: add class docblocks, business-rule comments, and transaction wrapper
- Add single-line class docblocks to all 59 repository classes and interfaces
  describing scope and responsibility
- Add multi-line docblocks to key services documenting business rules:
  AuthService (6-step login cascade), ImportService (3-phase CSV workflow),
  TenantScopeService (strict/permissive modes), PermissionService (RBAC
  resolution + two-tier caching), UserAccountService (atomicity + audit)
- Add transaction(callable) wrapper to DatabaseSessionRepository to DRY up
  begin/commit/rollback boilerplate

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:58:51 +01:00
fs
aaea038619 assign role roles 2026-03-13 21:11:48 +01:00
fs
b89fd792bf fix(security): harden PHP configuration for dev and production
Apply consistent security settings to both environments so issues
surface early in development rather than first appearing in prod.

Both environments:
- expose_php=Off — hide PHP version from X-Powered-By
- allow_url_include=Off — prevent remote file inclusion
- open_basedir=/var/www:/tmp — restrict filesystem access
- disable_functions — block shell execution functions unused by the app
- Session: strict_mode, httponly, samesite=Lax, use_only_cookies

Production additionally:
- display_errors=0, log_errors=1
- session.cookie_secure=1 (HTTPS-only)

Removed deprecated sid_length/sid_bits_per_character (PHP 8.5+).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 19:58:23 +01:00
fs
2b9ed78efd fix(security): harden production PHP configuration
- expose_php=Off — hide PHP version from response headers
- allow_url_include=Off — prevent remote file inclusion
- open_basedir=/var/www:/tmp — restrict filesystem access
- disable_functions — block shell execution functions not used by the app
- Session hardening: strict_mode, httponly, secure, samesite=Lax,
  use_only_cookies, 48-char session IDs with 6 bits/char

Note: allow_url_fopen left On (required by PHPMailer for SMTP streams).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 19:55:11 +01:00