Rename app branding from IMVS to CoreCore
This commit is contained in:
14
.env.example
14
.env.example
@@ -1,4 +1,4 @@
|
|||||||
APP_NAME=IMVS
|
APP_NAME=CoreCore
|
||||||
APP_URL=http://localhost:8080
|
APP_URL=http://localhost:8080
|
||||||
APP_ENV=dev
|
APP_ENV=dev
|
||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
@@ -9,15 +9,15 @@ APP_LOCALE=de
|
|||||||
APP_LOCALES=de,en
|
APP_LOCALES=de,en
|
||||||
APP_I18N_DOMAIN=default
|
APP_I18N_DOMAIN=default
|
||||||
APP_CRYPTO_KEY=
|
APP_CRYPTO_KEY=
|
||||||
SESSION_NAME=IMVS
|
SESSION_NAME=CoreCore
|
||||||
TENANT_SCOPE_STRICT=true
|
TENANT_SCOPE_STRICT=true
|
||||||
|
|
||||||
DB_HOST=db
|
DB_HOST=db
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
DB_NAME=imvs
|
DB_NAME=corecore
|
||||||
DB_USER=imvs
|
DB_USER=corecore
|
||||||
DB_PASS=imvs
|
DB_PASS=corecore
|
||||||
DB_ROOT_PASSWORD=imvs_root
|
DB_ROOT_PASSWORD=corecore_root
|
||||||
|
|
||||||
CACHE_SERVERS=memcached:11211
|
CACHE_SERVERS=memcached:11211
|
||||||
|
|
||||||
@@ -32,5 +32,5 @@ SMTP_PORT=587
|
|||||||
SMTP_USER=no-reply@example.com
|
SMTP_USER=no-reply@example.com
|
||||||
SMTP_PASS=
|
SMTP_PASS=
|
||||||
SMTP_FROM=no-reply@example.com
|
SMTP_FROM=no-reply@example.com
|
||||||
SMTP_FROM_NAME=IMVS
|
SMTP_FROM_NAME=CoreCore
|
||||||
SMTP_SECURE=tls
|
SMTP_SECURE=tls
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
APP_NAME=IMVS
|
APP_NAME=CoreCore
|
||||||
APP_URL=https://example.com
|
APP_URL=https://example.com
|
||||||
APP_ENV=prod
|
APP_ENV=prod
|
||||||
APP_DEBUG=false
|
APP_DEBUG=false
|
||||||
@@ -9,13 +9,13 @@ APP_LOCALE=de
|
|||||||
APP_LOCALES=de,en
|
APP_LOCALES=de,en
|
||||||
APP_I18N_DOMAIN=default
|
APP_I18N_DOMAIN=default
|
||||||
APP_CRYPTO_KEY=replace-with-64-char-hex-or-base64-key
|
APP_CRYPTO_KEY=replace-with-64-char-hex-or-base64-key
|
||||||
SESSION_NAME=IMVS
|
SESSION_NAME=CoreCore
|
||||||
TENANT_SCOPE_STRICT=true
|
TENANT_SCOPE_STRICT=true
|
||||||
|
|
||||||
DB_HOST=db
|
DB_HOST=db
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
DB_NAME=imvs
|
DB_NAME=corecore
|
||||||
DB_USER=imvs
|
DB_USER=corecore
|
||||||
DB_PASS=replace-db-password
|
DB_PASS=replace-db-password
|
||||||
DB_ROOT_PASSWORD=replace-db-root-password
|
DB_ROOT_PASSWORD=replace-db-root-password
|
||||||
|
|
||||||
@@ -32,5 +32,5 @@ SMTP_PORT=587
|
|||||||
SMTP_USER=
|
SMTP_USER=
|
||||||
SMTP_PASS=
|
SMTP_PASS=
|
||||||
SMTP_FROM=
|
SMTP_FROM=
|
||||||
SMTP_FROM_NAME=IMVS
|
SMTP_FROM_NAME=CoreCore
|
||||||
SMTP_SECURE=tls
|
SMTP_SECURE=tls
|
||||||
|
|||||||
127
AGENTS.md
Normal file
127
AGENTS.md
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
Multi-tenant admin application built on MintyPHP. Manages tenants, users, departments, roles, permissions, address books, mail, CSV imports, scheduled jobs, and Microsoft Entra ID SSO.
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
|
||||||
|
- **Runtime:** PHP 8.5 (FPM) on MintyPHP framework (`mintyphp/core`)
|
||||||
|
- **Web server:** Nginx 1.25 (Alpine)
|
||||||
|
- **Database:** MariaDB 11.4
|
||||||
|
- **Cache:** Memcached 1.6
|
||||||
|
- **Frontend:** Vanilla JS (ES2022 modules), vanilla CSS with `@layer` system — no build step
|
||||||
|
- **Key PHP libs:** PHPMailer 7, Dompdf 3, endroid/qr-code 6, league/commonmark 2
|
||||||
|
- **Containerized:** Docker Compose (dev + prod variants)
|
||||||
|
|
||||||
|
## Quick Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start dev environment
|
||||||
|
docker compose up --build -d
|
||||||
|
# App: http://localhost:8080 | phpMyAdmin: http://localhost:8081
|
||||||
|
|
||||||
|
# Run PHPUnit tests (phpunit.xml configures bootstrap + testsuite)
|
||||||
|
docker compose exec php vendor/bin/phpunit
|
||||||
|
|
||||||
|
# Run PHPStan (level 5)
|
||||||
|
docker compose exec php vendor/bin/phpstan analyse -c phpstan.neon --no-progress
|
||||||
|
|
||||||
|
# Check unused Composer packages
|
||||||
|
docker compose exec php vendor/bin/composer-unused
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
lib/ # All backend PHP (namespace MintyPHP\)
|
||||||
|
App/ # DI container + bootstrap (AppContainer, Container/Registrars/)
|
||||||
|
Repository/ # SQL queries, prepared statements, filters/paging
|
||||||
|
Service/ # Business logic, validation, orchestration
|
||||||
|
Http/ # Auth guards, API auth, request helpers
|
||||||
|
Input/ # Request input handling (RequestInput, FormErrors)
|
||||||
|
Support/ # Crypto, flash, guard, search, helpers
|
||||||
|
pages/ # Actions (controllers) — file-based routing
|
||||||
|
pages/**/*.php # Action files (read input, check permissions, call services)
|
||||||
|
pages/**/*.phtml # View files (rendering only, no DB calls)
|
||||||
|
templates/ # Layouts and partials
|
||||||
|
partials/ # Reusable UI components
|
||||||
|
emails/ # Email HTML templates
|
||||||
|
pdfs/ # PDF templates (Dompdf)
|
||||||
|
config/ # App config (routes, assets, settings cache, themes)
|
||||||
|
web/ # Document root (entry point, CSS, JS, static assets)
|
||||||
|
js/core/ # DOM utilities, Grid.js factory
|
||||||
|
js/components/ # Reusable UI components
|
||||||
|
css/ # Layered CSS (base → components → layout → pages)
|
||||||
|
storage/ # Uploaded files (branding/, imports/, tenants/, users/)
|
||||||
|
db/init/init.sql # Full schema + seed data (no migration framework)
|
||||||
|
db/updates/ # Idempotent SQL update scripts for existing installs
|
||||||
|
tests/ # PHPUnit tests (namespace MintyPHP\Tests\)
|
||||||
|
docs/ # German-language documentation (Markdown)
|
||||||
|
i18n/ # Translation files (de, en)
|
||||||
|
bin/ # CLI scripts (scheduler, doctor.php health check)
|
||||||
|
tools/ # Dev tooling scripts
|
||||||
|
docker/ # Dockerfiles, Nginx configs, PHP configs
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture Rules
|
||||||
|
|
||||||
|
### Strict Layering (enforce in all changes)
|
||||||
|
|
||||||
|
1. **App** (`lib/App/`): DI container bootstrap. Registers all service/repository factories. No business logic.
|
||||||
|
2. **Repository** (`lib/Repository/`): All SQL lives here. No HTTP, session, or rendering.
|
||||||
|
3. **Service** (`lib/Service/`): Business rules and validation. No HTML. Four internal sub-types:
|
||||||
|
- **Service** (`*Service.php`): Business logic + orchestration. Coordinates repositories and gateways.
|
||||||
|
- **Gateway** (`*Gateway.php`): Adapter for a single external dependency (repository, settings, HTTP API, scope). No orchestration flow.
|
||||||
|
- **Factory** (`*Factory.php`): Only place inside `lib/Service/` that may call `new` on services/gateways/repositories. Registers via DI container.
|
||||||
|
- **Policy** (`*Policy.php` in `lib/Service/Access/`): Authorization decisions per resource type. Returns `AuthorizationDecision`. No HTTP, no business logic.
|
||||||
|
4. **Action** (`pages/**/*.php`): Reads input, checks permissions + tenant scope, calls services, sets view vars.
|
||||||
|
5. **View** (`pages/**/*.phtml`): Pure rendering. **No DB calls.** HTML escaping via `e(...)`.
|
||||||
|
6. **Template** (`templates/`): Layouts and partials.
|
||||||
|
|
||||||
|
### Routing
|
||||||
|
|
||||||
|
- File-based: `pages/admin/users/edit($id).php` → URL parameter `id`
|
||||||
|
- `...(none).phtml` → no template layout
|
||||||
|
- `data().php` suffix → data/AJAX endpoints
|
||||||
|
- Named aliases in `config/routes.php` with `public` flag for auth guard
|
||||||
|
|
||||||
|
### PHP Conventions
|
||||||
|
|
||||||
|
- PSR-4 autoload: `MintyPHP\` → `lib/`, `MintyPHP\Tests\` → `tests/`
|
||||||
|
- All user-facing text uses `t('key')` translation helper
|
||||||
|
- Permissions + tenant scope enforced in actions/services, never just in UI
|
||||||
|
- Security/integration settings stay in DB, not in `config/settings.php` file cache
|
||||||
|
|
||||||
|
### Frontend Conventions
|
||||||
|
|
||||||
|
- Vanilla ES2022 modules, no bundler
|
||||||
|
- CSS classes prefixed with `app-`
|
||||||
|
- Defensive DOM checks (elements may not exist on every page)
|
||||||
|
- No business logic in frontend
|
||||||
|
- Assets served raw with `assetVersion()` cache-busting (filemtime-based)
|
||||||
|
|
||||||
|
### UI Patterns
|
||||||
|
|
||||||
|
- Edit pages: tabs → `Master data` | `Visibility` | optional `Danger zone`
|
||||||
|
- Titlebar partial for primary actions (Save, Save & close)
|
||||||
|
- Secondary actions in Aside block via `app-details-aside-actions.phtml`
|
||||||
|
- Lists use Grid.js
|
||||||
|
- All visible text wrapped in `t('...')`
|
||||||
|
|
||||||
|
## Database
|
||||||
|
|
||||||
|
- Schema defined in `db/init/init.sql` (applied once on container init)
|
||||||
|
- No migration framework — schema changes for existing installs are idempotent SQL scripts
|
||||||
|
- Settings stored in `settings` DB table (single source of truth); `config/settings.php` is a partial file cache for hot-path UI reads only
|
||||||
|
|
||||||
|
## Quality Gates
|
||||||
|
|
||||||
|
- **PHPStan level 5** — scans `config/`, `lib/`, `pages/`, `tests/`
|
||||||
|
- **PHPUnit 11** — bootstrap: `tests/bootstrap.php`
|
||||||
|
- **Frontend Smoke-Check** — browser console bleibt fehlerfrei in Kernflows
|
||||||
|
- **composer-unused** — periodic check for unused dependencies
|
||||||
|
|
||||||
|
## Environment
|
||||||
|
|
||||||
|
- Config via `.env` (gitignored) — copy from `.env.example` for dev, `.env.prod.example` for prod
|
||||||
|
- `config/config.php` (gitignored) — copy from `config/config.php.example`
|
||||||
|
- `APP_CRYPTO_KEY` (64-char hex) needed for AES-256-GCM encryption of SSO secrets
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# CLAUDE.md — IMVS (ImmobilienMaklerVerkaufssoftware)
|
# CLAUDE.md — CoreCore (ImmobilienMaklerVerkaufssoftware)
|
||||||
|
|
||||||
Multi-tenant admin application built on MintyPHP. Manages tenants, users, departments, roles, permissions, address books, mail, CSV imports, scheduled jobs, and Microsoft Entra ID SSO.
|
Multi-tenant admin application built on MintyPHP. Manages tenants, users, departments, roles, permissions, address books, mail, CSV imports, scheduled jobs, and Microsoft Entra ID SSO.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# IMVS (MintyPHP)
|
# CoreCore (MintyPHP)
|
||||||
|
|
||||||
IMVS ist eine mandantenfaehige Admin-Anwendung auf Basis von MintyPHP.
|
CoreCore ist eine mandantenfaehige Admin-Anwendung auf Basis von MintyPHP.
|
||||||
Der Fokus liegt auf klarer Rollen-/Rechtestruktur, Tenant-Scope und einer konsistenten Admin-UI.
|
Der Fokus liegt auf klarer Rollen-/Rechtestruktur, Tenant-Scope und einer konsistenten Admin-UI.
|
||||||
|
|
||||||
## Funktionsumfang
|
## Funktionsumfang
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ $envList = static function (string $key, array $default): array {
|
|||||||
return array_values(array_filter(array_map('trim', explode(',', (string) $value))));
|
return array_values(array_filter(array_map('trim', explode(',', (string) $value))));
|
||||||
};
|
};
|
||||||
|
|
||||||
define('APP_NAME', $envString('APP_NAME', 'IMVS'));
|
define('APP_NAME', $envString('APP_NAME', 'CoreCore'));
|
||||||
define('APP_TIMEZONE', $envString('APP_TIMEZONE', 'Europe/Berlin'));
|
define('APP_TIMEZONE', $envString('APP_TIMEZONE', 'Europe/Berlin'));
|
||||||
define('APP_STORAGE_PATH', $envString('APP_STORAGE_PATH', __DIR__ . '/../storage'));
|
define('APP_STORAGE_PATH', $envString('APP_STORAGE_PATH', __DIR__ . '/../storage'));
|
||||||
define('APP_CRYPTO_KEY', $envString('APP_CRYPTO_KEY', ''));
|
define('APP_CRYPTO_KEY', $envString('APP_CRYPTO_KEY', ''));
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ Vorlage: `.env.example` — niemals echte Credentials committen.
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `DB_HOST` | `db` | Hostname des MySQL/MariaDB-Servers (Docker-Service-Name oder IP) |
|
| `DB_HOST` | `db` | Hostname des MySQL/MariaDB-Servers (Docker-Service-Name oder IP) |
|
||||||
| `DB_PORT` | `3306` | Port des Datenbankservers |
|
| `DB_PORT` | `3306` | Port des Datenbankservers |
|
||||||
| `DB_NAME` | `imvs` | Name der Datenbank |
|
| `DB_NAME` | `corecore` | Name der Datenbank |
|
||||||
| `DB_USER` | `imvs` | Datenbankbenutzer |
|
| `DB_USER` | `corecore` | Datenbankbenutzer |
|
||||||
| `DB_PASS` | `imvs` | Passwort des Datenbankbenutzers |
|
| `DB_PASS` | `corecore` | Passwort des Datenbankbenutzers |
|
||||||
| `DB_ROOT_PASSWORD` | `imvs_root` | Root-Passwort für Docker-Compose (wird nur vom DB-Container genutzt, nicht von PHP) |
|
| `DB_ROOT_PASSWORD` | `corecore_root` | Root-Passwort für Docker-Compose (wird nur vom DB-Container genutzt, nicht von PHP) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ Letzte Aktualisierung: 2026-03-06
|
|||||||
|
|
||||||
In 10 Minuten verstehen, was die Software tut, wie sie aufgebaut ist und welche Kernprinzipien immer gelten.
|
In 10 Minuten verstehen, was die Software tut, wie sie aufgebaut ist und welche Kernprinzipien immer gelten.
|
||||||
|
|
||||||
## Was ist IMVS?
|
## Was ist CoreCore?
|
||||||
|
|
||||||
IMVS ist eine mandantenfähige Admin-Software für Immobilienmakler-Prozesse mit klarer Rollen-/Rechtestruktur.
|
CoreCore ist eine mandantenfähige Admin-Software für Immobilienmakler-Prozesse mit klarer Rollen-/Rechtestruktur.
|
||||||
|
|
||||||
Kernmodule:
|
Kernmodule:
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ class BrandingFaviconService
|
|||||||
|
|
||||||
$title = $this->settingsAppGateway->getAppTitle();
|
$title = $this->settingsAppGateway->getAppTitle();
|
||||||
if ($title === null || $title === '') {
|
if ($title === null || $title === '') {
|
||||||
$title = defined('APP_NAME') ? APP_NAME : 'IMVS';
|
$title = defined('APP_NAME') ? APP_NAME : 'CoreCore';
|
||||||
}
|
}
|
||||||
|
|
||||||
$data['name'] = $title;
|
$data['name'] = $title;
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ function lurl(string $path = ''): string
|
|||||||
*/
|
*/
|
||||||
function appTitle(): string
|
function appTitle(): string
|
||||||
{
|
{
|
||||||
$default = defined('APP_NAME') ? APP_NAME : 'IMVS';
|
$default = defined('APP_NAME') ? APP_NAME : 'CoreCore';
|
||||||
$title = appSetting('app_title');
|
$title = appSetting('app_title');
|
||||||
if ($title !== null) {
|
if ($title !== null) {
|
||||||
return $title;
|
return $title;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
bootstrap="tests/bootstrap.php"
|
bootstrap="tests/bootstrap.php"
|
||||||
colors="true">
|
colors="true">
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<testsuite name="IMVS">
|
<testsuite name="CoreCore">
|
||||||
<directory>tests</directory>
|
<directory>tests</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ final class EnvValidatorTest extends TestCase
|
|||||||
$storagePath = sys_get_temp_dir();
|
$storagePath = sys_get_temp_dir();
|
||||||
|
|
||||||
return array_merge([
|
return array_merge([
|
||||||
'APP_NAME' => 'IMVS',
|
'APP_NAME' => 'CoreCore',
|
||||||
'APP_ENV' => 'dev',
|
'APP_ENV' => 'dev',
|
||||||
'APP_DEBUG' => 'true',
|
'APP_DEBUG' => 'true',
|
||||||
'APP_TIMEZONE' => 'Europe/Berlin',
|
'APP_TIMEZONE' => 'Europe/Berlin',
|
||||||
@@ -132,13 +132,13 @@ final class EnvValidatorTest extends TestCase
|
|||||||
'APP_I18N_DOMAIN' => 'default',
|
'APP_I18N_DOMAIN' => 'default',
|
||||||
'APP_URL' => 'http://localhost:8080',
|
'APP_URL' => 'http://localhost:8080',
|
||||||
'APP_CRYPTO_KEY' => '',
|
'APP_CRYPTO_KEY' => '',
|
||||||
'SESSION_NAME' => 'IMVS',
|
'SESSION_NAME' => 'CoreCore',
|
||||||
'TENANT_SCOPE_STRICT' => 'true',
|
'TENANT_SCOPE_STRICT' => 'true',
|
||||||
'DB_HOST' => 'db',
|
'DB_HOST' => 'db',
|
||||||
'DB_PORT' => '3306',
|
'DB_PORT' => '3306',
|
||||||
'DB_NAME' => 'imvs',
|
'DB_NAME' => 'corecore',
|
||||||
'DB_USER' => 'imvs',
|
'DB_USER' => 'corecore',
|
||||||
'DB_PASS' => 'imvs',
|
'DB_PASS' => 'corecore',
|
||||||
'CACHE_SERVERS' => 'memcached:11211',
|
'CACHE_SERVERS' => 'memcached:11211',
|
||||||
'FIREWALL_CONCURRENCY' => '10',
|
'FIREWALL_CONCURRENCY' => '10',
|
||||||
'FIREWALL_SPINLOCK_SECONDS' => '0.15',
|
'FIREWALL_SPINLOCK_SECONDS' => '0.15',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "IVMS",
|
"name": "CoreCore",
|
||||||
"short_name": "IVMS",
|
"short_name": "CC",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/favicon/web-app-manifest-192x192.png",
|
"src": "/favicon/web-app-manifest-192x192.png",
|
||||||
|
|||||||
Reference in New Issue
Block a user