ops: Lokale Datenbank gegen fremde Testläufe absichern — DB_* nicht mehr als Container-Umgebung, Agenten-Regel, Testdatenbank-Pflicht im Baukasten
Am 07.10.2026 hat das RefreshDatabase eines frischen Demo-Projekts (Test der Vorlagen aus dev/git-deploy-monitoring) die lokale Datenbank `pressekonto` auf global-mysql vollständig geleert (Binärlog binlog.000009, Pos. 566161486). Ursache: docker-compose.yml setzte DB_* als Container-Umgebungsvariablen, die in Laravel Vorrang vor jeder .env haben; die phpunit.xml des Demo-Projekts erzwang kein SQLite. Die eigene Suite war nicht beteiligt (force="true" und Guard in tests/TestCase.php greifen; Gegenprobe mit MySQL-Variablen grün). - docker-compose.yml: DB_* entfernt (Werte identisch in .env), wirksam nach Neuerstellen des Containers. - Baukasten: „Testdatenbank absichern" (phpunit.xml mit force, Guard, Gegenprobe) als Pflicht vor RefreshDatabase. - .ai/rules/general.md und CLAUDE.md: fremde/frische Laravel-Projekte nur mit SQLite :memory: testen; migrate hier erst nach migrate:status. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
32e1349517
commit
fd8dd74d5f
6 changed files with 81 additions and 9 deletions
15
.ai/rules/general.md
Normal file
15
.ai/rules/general.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
paths:
|
||||
- '**/*'
|
||||
---
|
||||
|
||||
# General
|
||||
|
||||
## Befehle direkt im Dev-Container ausführen
|
||||
Die Arbeitsumgebung /var/www/html liegt bereits im DEV-Container. PHP-/Artisan-, Composer- und Node-Befehle dort direkt ausführen (z. B. php artisan test --compact), ohne vendor/bin/sail davor. Eine Sail-Meldung über nicht laufendes Docker ist in diesem Container kein Nachweis, dass Docker auf dem Host gestoppt ist. Diese ausdrückliche Benutzeranweisung ersetzt die allgemeine Sail-Prefix-Vorgabe für diese Umgebung.
|
||||
|
||||
## Fremde oder frische Laravel-Projekte nie gegen die lokale Datenbank testen
|
||||
Auf `global-mysql` liegen die Datenbanken mehrerer Projekte, und Container-Umgebungsvariablen haben in Laravel Vorrang vor `.env` und nicht erzwungenen `phpunit.xml`-Werten. Ein frisches Laravel-Projekt hat die SQLite-Zeilen in `phpunit.xml` nur auskommentiert — `RefreshDatabase` führt dann `migrate:fresh` auf der Datenbank aus, die die Umgebung vorgibt (07.10.2026: so wurde `pressekonto` vollständig geleert). Deshalb:
|
||||
- Tests, `migrate`, `migrate:fresh`, `db:wipe` oder Seeder eines anderen bzw. frisch angelegten Laravel-Projekts in diesem Container nur mit `DB_CONNECTION=sqlite DB_DATABASE=:memory: DB_URL=` davor ausführen, z. B. `DB_CONNECTION=sqlite DB_DATABASE=:memory: DB_URL= php artisan test`.
|
||||
- Vorher prüfen, dass `phpunit.xml` dort SQLite `:memory:` mit `force="true"` setzt (siehe `dev/git-deploy-monitoring/02-fehlerprotokoll-glitchtip.md`, „Testdatenbank absichern“).
|
||||
- `php artisan migrate` in diesem Projekt erst nach `php artisan migrate:status`: Stehen unerwartet viele Migrationen aus, ist die Datenbank nicht die erwartete — anhalten und nachfragen.
|
||||
7
.ai/rules/index.md
Normal file
7
.ai/rules/index.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Project Rules Index
|
||||
|
||||
Before planning or editing, find the row whose globs match the file's path and read that rule file.
|
||||
|
||||
| Applies to | Rule file |
|
||||
| --- | --- |
|
||||
| **/* | .ai/rules/general.md |
|
||||
|
|
@ -178,6 +178,7 @@ workflow and the privacy rules for error reporting. Monitoring decisions:
|
|||
- Configuration: `phpunit.xml` and `tests/Pest.php`
|
||||
- Test database: Uses `DB_DATABASE=testing` environment (configured in phpunit.xml)
|
||||
- Test directories: `tests/Feature/` (authentication, dashboard, settings) and `tests/Unit/`
|
||||
- **Never run tests, migrations or seeders of another or freshly created Laravel project in this container against MySQL.** `global-mysql` holds several projects' databases and container env vars beat `.env`; a fresh project's `RefreshDatabase` wiped `pressekonto` on 07.10.2026. Prefix such runs with `DB_CONNECTION=sqlite DB_DATABASE=:memory: DB_URL=` and check `migrate:status` before `migrate` here (details: `.ai/rules/general.md`).
|
||||
|
||||
## Important Files & Configuration
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,50 @@ glitchtip“), `ErrorSignalsTest.php`, `BrowserErrorReportingTest.php`,
|
|||
Die Tests setzen `RefreshDatabase` voraus (in `tests/Pest.php` aktivieren) und
|
||||
eine `User`-Factory.
|
||||
|
||||
### Testdatenbank absichern (vor `RefreshDatabase`!)
|
||||
|
||||
`RefreshDatabase` führt `migrate:fresh` aus und **löscht alle Tabellen** der
|
||||
Datenbank, auf die die Tests zeigen. In einer frischen Laravel-Installation
|
||||
sind die SQLite-Zeilen in `phpunit.xml` auskommentiert, und ohne `force="true"`
|
||||
haben vorhandene Umgebungsvariablen (Docker-/Container-`environment`, CI) Vorrang
|
||||
vor `phpunit.xml` und `.env`. So hat am 07.10.2026 das Testen dieser Vorlagen
|
||||
in einem Demo-Projekt die lokale Datenbank eines anderen Projekts geleert, das
|
||||
im selben Container lief.
|
||||
|
||||
`phpunit.xml`, im `<php>`-Block:
|
||||
|
||||
```xml
|
||||
<env name="DB_CONNECTION" value="sqlite" force="true"/>
|
||||
<env name="DB_DATABASE" value=":memory:" force="true"/>
|
||||
<env name="DB_URL" value="" force="true"/>
|
||||
<server name="DB_CONNECTION" value="sqlite" force="true"/>
|
||||
<server name="DB_DATABASE" value=":memory:" force="true"/>
|
||||
<server name="DB_URL" value="" force="true"/>
|
||||
```
|
||||
|
||||
Guard in `tests/TestCase.php` — `setUpTraits()` läuft vor jedem
|
||||
Datenbank-Trait und bricht ab, bevor etwas geleert wird (auch bei einem
|
||||
gecachten `bootstrap/cache/config.php`):
|
||||
|
||||
```php
|
||||
protected function setUpTraits(): array
|
||||
{
|
||||
$default = (string) \Illuminate\Support\Facades\DB::getDefaultConnection();
|
||||
$connection = (array) config('database.connections.'.$default, []);
|
||||
|
||||
if (! empty($connection['url'])
|
||||
|| ($connection['driver'] ?? null) !== 'sqlite'
|
||||
|| ($connection['database'] ?? null) !== ':memory:') {
|
||||
throw new \RuntimeException("Tests laufen nicht gegen SQLite :memory: ({$default}) — abgebrochen, bevor RefreshDatabase etwas leert.");
|
||||
}
|
||||
|
||||
return parent::setUpTraits();
|
||||
}
|
||||
```
|
||||
|
||||
Wer Vorlagen in einem Wegwerf-Projekt ausprobiert, startet die Tests
|
||||
zusätzlich explizit mit `DB_CONNECTION=sqlite DB_DATABASE=:memory: php artisan test`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Regeln für den Code
|
||||
|
|
|
|||
|
|
@ -32,7 +32,13 @@ Platzhalter: `meineapp` (Projektname), `meineapp.de` (Live-Domain),
|
|||
- [ ] `AppServiceProvider::boot()`: `Queue::failing` → `OperationalAlert`, `AboutCommand::add`
|
||||
- [ ] Vite-Eingang `resources/js/error-reporting.js`; `<x-monitoring.browser-errors build="build" area="…" />` in jedem Layout-`<head>`
|
||||
- [ ] Basic Auth / `trustHosts`: `/health` ausgenommen bzw. erreichbar
|
||||
- [ ] `phpunit.xml`: Sentry-DSNs leer (`force="true"`); `tests/Pest.php` mit `RefreshDatabase`
|
||||
- [ ] **Vor** `RefreshDatabase`: Testdatenbank absichern (02 §5, „Testdatenbank absichern“):
|
||||
`phpunit.xml` mit SQLite `:memory:` **und `force="true"`** (`DB_CONNECTION`, `DB_DATABASE`, `DB_URL` leer;
|
||||
je als `<env>` und `<server>`), dazu der Guard in `tests/TestCase.php`. Eine frische Laravel-Installation
|
||||
hat diese Zeilen nur auskommentiert — ohne `force` gewinnen vorhandene Umgebungsvariablen.
|
||||
- [ ] Gegenprobe: `DB_CONNECTION=mysql DB_DATABASE=gibtsnicht php artisan test` muss trotzdem grün laufen
|
||||
(bzw. der Guard laut abbrechen) — nie eine echte Datenbank leeren
|
||||
- [ ] `phpunit.xml`: Sentry-DSNs leer (`force="true"`); danach `tests/Pest.php` mit `RefreshDatabase`
|
||||
- [ ] `.env.example` um `vorlagen/env-beispiel.env` ergänzt
|
||||
- [ ] Tests grün: `php artisan test --compact tests/Feature/Monitoring tests/Unit/Monitoring` (30 Tests)
|
||||
- [ ] Datenschutzerklärung: Fehlerprotokollierung (Kategorien, Frist, Rechtsgrundlage)
|
||||
|
|
|
|||
|
|
@ -21,14 +21,13 @@ services:
|
|||
IGNITION_LOCAL_SITES_PATH: '${PWD}'
|
||||
|
||||
# --- Anbindung an das Mutterschiff ---
|
||||
DB_CONNECTION: mysql
|
||||
DB_HOST: global-mysql
|
||||
DB_PORT: 3306
|
||||
# Hier definieren wir nur die Haupt-Datenbank für .env
|
||||
# Die anderen beiden richtest du in Laravel ein
|
||||
DB_DATABASE: pressekonto
|
||||
DB_USERNAME: root
|
||||
DB_PASSWORD: password
|
||||
# Die Datenbank-Zugangsdaten (DB_*) stehen bewusst NUR in der .env,
|
||||
# nicht hier: Container-Umgebungsvariablen haben in Laravel Vorrang
|
||||
# vor jeder .env. Jedes andere Laravel-Projekt, das in diesem
|
||||
# Container läuft (z. B. ein frisches Demo-Projekt), würde sonst
|
||||
# automatisch auf `pressekonto` zeigen — am 07.10.2026 hat so das
|
||||
# RefreshDatabase eines Demo-Projekts die lokale Datenbank geleert
|
||||
# (dev/sicherheit/ENTWICKLUNGSPLAN-SICHERHEIT-2026-10-07.md).
|
||||
MAIL_HOST: global-mailpit
|
||||
MAIL_PORT: 1025
|
||||
REDIS_HOST: global-redis
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue