Plan berichtigt: zwei Annahmen im Vorabdurchgang gefunden
InstanceFactory kennt keinen active()-Zustand — die Tests im Plan haetten nicht einmal kompiliert. Status und vmid stehen jetzt ausgeschrieben. Und eine Zusicherung in Aufgabe 1 war leer: sie prueft, dass der Nachbar NICHT auf 'info' zeigt, ohne ein Postfach fuer Abrechnung anzulegen — der Resolver liefert dann null, und null ist nun einmal nicht 'info'. Genau die Sorte Test, die gruen bleibt, waehrend die Sache kaputt ist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>feat/versandtakt
parent
850a9ebd5b
commit
e3f2e9a88b
|
|
@ -20,6 +20,7 @@
|
|||
- Kommentare auf Deutsch, im Ton des umliegenden Codes: sie erklären das **Warum**, nicht das Was.
|
||||
- Repo-Regeln **R18–R24** aus `CLAUDE.md` gelten und werden per Test erzwungen. Besonders: R20 (Bearbeiten im Modal), R23 (Bestätigen im Modal, nie `wire:confirm`), R24.3 (keine Blade-Direktive in der Attributliste eines Komponenten-Tags).
|
||||
- Jeder Befehl im `app`-Container nennt seinen Benutzer (`-u www-data` bzw. `-u root`) — erzwungen durch `tests/Feature/DeploymentRunsAsTheAppUserTest.php`.
|
||||
- **`InstanceFactory` kennt keinen `active()`-Zustand** — Status und `vmid` werden in den Tests ausgeschrieben. Wer einen Zustand ergänzen will, tut das in einer eigenen Aufgabe, nicht nebenbei.
|
||||
- Kommandos laufen im Container:
|
||||
`docker compose exec -u 1000:1000 -T app php artisan test`
|
||||
`docker compose exec -u 1000:1000 -e npm_config_cache=/tmp/npm-cache -T app npm run build`
|
||||
|
|
@ -86,9 +87,14 @@ it('legt eine einzelne Mailart auf ein anderes Postfach', function () {
|
|||
Settings::set(MailPurpose::settingKey(MailPurpose::SYSTEM), 'no-reply');
|
||||
Settings::set(MailRoute::settingKey('new-device'), 'info');
|
||||
|
||||
// Und nur diese eine: der Nachbar bleibt, wo er war. Mit einem EIGENEN
|
||||
// Postfach fuer Abrechnung — ohne das waere die Zusicherung leer, weil der
|
||||
// Resolver dann null liefert und null nun einmal nicht 'info' ist.
|
||||
$billing = Mailbox::factory()->create(['key' => 'billing', 'active' => true]);
|
||||
Settings::set(MailPurpose::settingKey(MailPurpose::BILLING), 'billing');
|
||||
|
||||
expect(MailRoute::purposeOrMailbox('new-device', MailPurpose::SYSTEM)?->id)->toBe($info->id)
|
||||
// Und nur diese eine: der Nachbar bleibt, wo er war.
|
||||
->and(MailRoute::purposeOrMailbox('invoice', MailPurpose::BILLING)?->key)->not->toBe('info');
|
||||
->and(MailRoute::purposeOrMailbox('invoice', MailPurpose::BILLING)?->id)->toBe($billing->id);
|
||||
});
|
||||
|
||||
it('faellt auf den Zweck zurueck, wenn das eingetragene Postfach abgeschaltet ist', function () {
|
||||
|
|
@ -541,7 +547,7 @@ it('sperrt ab zehn Fehlversuchen im Fenster', function () {
|
|||
$pve->guestScripts['nextcloud.log'] = ['out-data' => protokollZeilen('203.0.113.7', 10), 'exitcode' => 0];
|
||||
app()->instance(\App\Services\Proxmox\ProxmoxClient::class, $pve);
|
||||
|
||||
$instance = Instance::factory()->active()->create();
|
||||
$instance = Instance::factory()->create(['status' => 'active', 'vmid' => 101]);
|
||||
app(ScanForIntrusions::class)->handle();
|
||||
|
||||
expect(SecurityBlock::where('ip', '203.0.113.7')->exists())->toBeTrue();
|
||||
|
|
@ -552,7 +558,7 @@ it('sperrt bei neun Fehlversuchen nicht', function () {
|
|||
$pve->guestScripts['nextcloud.log'] = ['out-data' => protokollZeilen('203.0.113.7', 9), 'exitcode' => 0];
|
||||
app()->instance(\App\Services\Proxmox\ProxmoxClient::class, $pve);
|
||||
|
||||
Instance::factory()->active()->create();
|
||||
Instance::factory()->create(['status' => 'active', 'vmid' => 101]);
|
||||
app(ScanForIntrusions::class)->handle();
|
||||
|
||||
expect(SecurityBlock::count())->toBe(0);
|
||||
|
|
@ -572,7 +578,7 @@ it('sperrt nicht, wenn sich die Versuche ueber zwei Fenster verteilen', function
|
|||
$pve->guestScripts['nextcloud.log'] = ['out-data' => $alt."\n".protokollZeilen('203.0.113.7', 6), 'exitcode' => 0];
|
||||
app()->instance(\App\Services\Proxmox\ProxmoxClient::class, $pve);
|
||||
|
||||
Instance::factory()->active()->create();
|
||||
Instance::factory()->create(['status' => 'active', 'vmid' => 101]);
|
||||
app(ScanForIntrusions::class)->handle();
|
||||
|
||||
expect(SecurityBlock::count())->toBe(0);
|
||||
|
|
@ -586,7 +592,7 @@ it('faengt bei einem rotierten Protokoll wieder bei null an', function () {
|
|||
$pve->guestScripts['nextcloud.log'] = ['out-data' => protokollZeilen('203.0.113.7', 10), 'exitcode' => 0];
|
||||
app()->instance(\App\Services\Proxmox\ProxmoxClient::class, $pve);
|
||||
|
||||
$instance = Instance::factory()->active()->create(['security_log_offset' => 999999]);
|
||||
$instance = Instance::factory()->create(['status' => 'active', 'vmid' => 101, 'security_log_offset' => 999999]);
|
||||
app(ScanForIntrusions::class)->handle();
|
||||
|
||||
expect($instance->fresh()->security_log_offset)->toBeLessThan(999999)
|
||||
|
|
@ -616,7 +622,7 @@ it('ueberspringt einen Gast, der nicht antwortet, ohne den Versatz zu verlieren'
|
|||
$pve->guestScripts['nextcloud.log'] = ['exitcode' => 1];
|
||||
app()->instance(\App\Services\Proxmox\ProxmoxClient::class, $pve);
|
||||
|
||||
$instance = Instance::factory()->active()->create(['security_log_offset' => 4711]);
|
||||
$instance = Instance::factory()->create(['status' => 'active', 'vmid' => 101, 'security_log_offset' => 4711]);
|
||||
app(ScanForIntrusions::class)->handle();
|
||||
|
||||
expect($instance->fresh()->security_log_offset)->toBe(4711);
|
||||
|
|
@ -694,7 +700,7 @@ use Illuminate\Support\Facades\Mail;
|
|||
|
||||
it('schickt dem Inhaber eine Mail, wenn seine Instanz gesperrt wird', function () {
|
||||
Mail::fake();
|
||||
$instance = Instance::factory()->active()->create();
|
||||
$instance = Instance::factory()->create(['status' => 'active', 'vmid' => 101]);
|
||||
|
||||
app(BlockAddress::class)->forInstance($instance, '203.0.113.7', 12);
|
||||
|
||||
|
|
@ -705,7 +711,7 @@ it('schickt hoechstens eine Mail je Instanz und Stunde', function () {
|
|||
// Ein Angreifer, der Adressen durchwechselt, erzeugt sonst zwanzig Mails —
|
||||
// und die zwanzigste liest niemand mehr.
|
||||
Mail::fake();
|
||||
$instance = Instance::factory()->active()->create();
|
||||
$instance = Instance::factory()->create(['status' => 'active', 'vmid' => 101]);
|
||||
|
||||
app(BlockAddress::class)->forInstance($instance, '203.0.113.7', 12);
|
||||
app(BlockAddress::class)->forInstance($instance, '203.0.113.8', 12);
|
||||
|
|
@ -720,7 +726,7 @@ it('laesst die Sperre stehen, wenn die Mail scheitert', function () {
|
|||
// im Argen liegt.
|
||||
Mail::shouldReceive('to')->andThrow(new RuntimeException('Postfach kaputt'));
|
||||
|
||||
$instance = Instance::factory()->active()->create();
|
||||
$instance = Instance::factory()->create(['status' => 'active', 'vmid' => 101]);
|
||||
$block = app(BlockAddress::class)->forInstance($instance, '203.0.113.7', 12);
|
||||
|
||||
expect($block)->not->toBeNull()
|
||||
|
|
|
|||
Loading…
Reference in New Issue