docs(cache): add comprehensive cache configuration and permission handling guides

- Introduce `cache-configuration.md` for detailed instructions on cache setup, permission troubleshooting, and best practices.
- Add `cache-permissions-quick-fix.md` for concise resolutions to common permission errors.
- Include a detailed `FILECACHE_PERMISSION_FIX_PLAN.md` outlining solutions for permission-related issues.
- Enhance `docker-entrypoint.sh` with permission fixes for multi-user caches.
- Update `Makefile` with cache clear commands for local and staging environments.
- Improve `FileCache` for graceful degradation on permission errors, ensuring reliability under multi-user scenarios.
This commit is contained in:
2025-11-03 23:54:27 +01:00
parent a1242f776e
commit 56f09b5001
8 changed files with 610 additions and 11 deletions

View File

@@ -0,0 +1,217 @@
# FileCache Permission Problem - L?sungsplan
## Problem-Analyse
### Fehler
```
PHP Fatal error: Uncaught App\Framework\Filesystem\Exceptions\FilePermissionException [FS007]:
Permission denied for delete on file: var/www/html/storage/cache/8993618a07a0f5ee371a4d3b029abf09_1762296020.cache.php
(File is not writable)
```
### Root Cause
1. **Bug in `FileStorage::delete()`** (Zeile 222):
- Die Methode pr?ft `is_writable($resolvedPath)` auf die Datei selbst
- **FALSCH**: F?r das L?schen einer Datei braucht man nur Schreibrechte im **Verzeichnis**, nicht auf der Datei selbst!
- Unix-Regel: `unlink()` ben?tigt nur Schreibrechte im Parent-Verzeichnis
2. **Cache-Dateien werden mit 0644 erstellt**:
- Owner: `rw-` (read-write)
- Group: `r--` (read-only)
- Others: `r--` (read-only)
- Problem: Wenn verschiedene Prozesse/User Dateien erstellen, k?nnen sie Dateien des anderen nicht l?schen (Owner-Mismatch)
3. **Staging-Server Infrastruktur**:
- M?glicherweise werden Cache-Dateien von verschiedenen Usern/Prozessen erstellt
- PHP-Prozess l?uft als anderer User als der, der die Dateien erstellt hat
## L?sungsplan
### L?sung 1: Bug-Fix in `FileStorage::delete()` (H?CHSTE PRIORIT?T)
**Problem**: Falsche Pr?fung - Datei muss nicht beschreibbar sein zum L?schen
**Fix**: Entferne `is_writable()` Pr?fung auf die Datei selbst
```php
public function delete(string $path): void
{
$resolvedPath = $this->resolvePath($path);
// ... existing validation ...
if (! is_file($resolvedPath)) {
throw new FileNotFoundException($path);
}
// Pr?fe Directory-Permissions (DAS IST WICHTIG!)
$dir = dirname($resolvedPath);
if (! is_writable($dir)) {
throw FilePermissionException::delete($path, 'Directory is not writable: ' . $dir);
}
// ENTFERNT: Pr?fe File-Permissions
// F?r unlink() braucht man nur Verzeichnis-Rechte!
// if (! is_writable($resolvedPath)) {
// throw FilePermissionException::delete($path, 'File is not writable');
// }
if (! @unlink($resolvedPath)) {
$error = error_get_last();
if ($error && str_contains($error['message'], 'Permission denied')) {
throw FilePermissionException::delete($path, $error['message']);
}
throw new FileDeleteException($path);
}
// ... logging ...
}
```
**Warum**: Unix `unlink()` ben?tigt nur Schreibrechte im Parent-Verzeichnis, nicht auf der Datei selbst.
---
### L?sung 2: Graceful Degradation in FileCache (HOHE PRIORIT?T)
**Problem**: FileCache wirft Fatal Error bei Permission-Exceptions
**Fix**: Catch FilePermissionException in FileCache-Methoden
**Betroffene Stellen**:
1. `getSingleKey()` - beim L?schen abgelaufener Dateien
2. `set()` - beim L?schen alter Cache-Dateien
3. `forget()` - beim expliziten L?schen
4. `clear()` - beim L?schen aller Cache-Dateien
**Implementierung**:
```php
// In getSingleKey()
if ($expiresAt > 0 && $expiresAt < time()) {
try {
$this->fileSystem->delete($fullPath);
} catch (\App\Framework\Filesystem\Exceptions\FilePermissionException $e) {
// Permission denied - continue (graceful degradation)
// Datei wird beim n?chsten Cleanup gel?scht
continue;
} catch (\Throwable $e) {
// Other errors - continue
continue;
}
}
// In set(), forget(), clear() - ?hnlich
```
**Vorteil**: Cache funktioniert weiter, auch wenn einzelne Dateien nicht gel?scht werden k?nnen.
---
### L?sung 3: Optionale Auto-Fix vor L?schen (NIEDRIGE PRIORIT?T)
**Option**: Versuche Berechtigungen zu fixen, bevor gel?scht wird
**Implementierung**:
```php
private function tryDeleteWithFix(string $path): bool
{
try {
$this->fileSystem->delete($path);
return true;
} catch (\App\Framework\Filesystem\Exceptions\FilePermissionException $e) {
// Versuche Berechtigungen zu fixen
try {
// Versuche chmod auf 0644 (falls m?glich)
@chmod($path, 0644);
// Versuche erneut zu l?schen
$this->fileSystem->delete($path);
return true;
} catch (\Throwable $e2) {
// Auto-fix fehlgeschlagen
return false;
}
}
}
```
**Warnung**: Funktioniert nur, wenn der Prozess Owner oder root ist. Sonst wird `chmod()` fehlschlagen.
---
### L?sung 4: Infrastruktur-Fix f?r Staging (MITTEL PRIORIT?T)
**Problem**: Cache-Dateien werden von verschiedenen Usern/Prozessen erstellt
**L?sungen**:
#### Option A: Fix Berechtigungen im Entrypoint-Script
```bash
# In docker/php/docker-entrypoint.sh
# Nach Volume-Mounting:
chown -R appuser:appuser /var/www/html/storage/cache 2>/dev/null || true
chmod -R 775 /var/www/html/storage/cache 2>/dev/null || true
```
#### Option B: Fix Berechtigungen bei Cache-Erstellung
```php
// In FileStorage::put() - nach dem Schreiben
// Stelle sicher, dass Owner/Group korrekt ist
if (function_exists('posix_geteuid')) {
$currentUid = posix_geteuid();
@chown($resolvedPath, $currentUid);
}
```
#### Option C: Verwendung von Group-Writable Permissions
```php
// In FileStorage::put() - statt 0644
$this->permissions->setPermissions(
$path,
ValueObjects\FilePermissions::readWriteOwnerReadGroupWritable() // 0664
);
```
**Empfehlung**: Option A + Option C kombiniert
---
## Implementierungsreihenfolge
1. ? **L?sung 1** (Bug-Fix) - SOFORT
- Behebt das Hauptproblem
- Semantisch korrekt (Unix-Verhalten)
2. ? **L?sung 2** (Graceful Degradation) - SOFORT
- Verhindert Fatal Errors
- Cache bleibt funktionsf?hig
3. ?? **L?sung 4** (Infrastruktur) - NACH Code-Fix
- Verhindert zuk?nftige Probleme
- Dokumentiere in `docs/deployment/`
4. ?? **L?sung 3** (Auto-Fix) - NUR WENN N?TIG
- Kann Probleme verschlimmern, wenn nicht richtig implementiert
- Nur verwenden, wenn L?sungen 1+2+4 nicht ausreichen
## Testing
Nach Implementierung testen:
1. **Unit-Test**: `delete()` sollte funktionieren, auch wenn Datei nicht beschreibbar ist
2. **Integration-Test**: FileCache sollte funktionieren, auch wenn einige Dateien nicht gel?scht werden k?nnen
3. **Staging-Test**: Cache-Operationen sollten keine Fatal Errors mehr werfen
## Dokumentation
? **Dokumentation erstellt**:
- ? `docs/deployment/cache-configuration.md` - Vollst?ndige Cache-Konfigurations-Dokumentation
- `docs/claude/error-handling.md` - Cache-specific error handling (optional)
## Status
? **L?sung 1**: Bug-Fix in `delete()` - IMPLEMENTIERT
? **L?sung 2**: Graceful Degradation in FileCache - IMPLEMENTIERT
? **L?sung 4**: Infrastruktur-Dokumentation - IMPLEMENTIERT
?? **L?sung 3**: Auto-Fix mit chmod() - NUR WENN N?TIG