# 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