nexxo
f5f4d2a8cd
fix(security): close the Livewire bypass of the admin host restriction
...
Admin actions post to /livewire/update, which a path-scoped guard skips — an
operator session could drive admin components through a PUBLIC hostname despite
ADMIN_HOSTS. The restriction is now registered as Livewire-persistent middleware
and listed on the admin route group, so Livewire re-applies it from the
component snapshot.
Proven by replaying a snapshot taken from the real rendered page: identical
payload -> 404 on a public host, 200 on the allowed host (positive control, so
the test cannot pass for the wrong reason).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 20:50:22 +02:00
nexxo
0b2d762b88
fix(auth): scope registration throttle to its own route (per-IP), not all Fortify endpoints
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 18:41:30 +02:00
nexxo
87a81f5f40
fix(admin): read-only send-time guard (never drop mail on retry); document exactly-once residual for real-mail outbox
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 16:40:44 +02:00
nexxo
e09965f918
fix(admin): in-flight claim (claimed_at) for exactly-once maintenance send; scope permission rollback
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 16:38:44 +02:00
nexxo
28221549d1
fix(admin): defer maintenance sent_at to real delivery; read-only send-time dedup (no lost mail)
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 16:35:52 +02:00
nexxo
0cc5be5479
fix(admin): atomic send-time delivery claim so backlog duplicates ship exactly once
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 16:34:02 +02:00
nexxo
8bb93137a3
refactor(admin): extract MaintenanceNotifier; atomic provisioning retry; catch-up cancellation for race-delivered announcements
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 16:28:02 +02:00
nexxo
ae1f78f534
fix(admin): shown-once temp password for invited staff; suppress announcements for cancelled windows at send time
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 16:23:21 +02:00
nexxo
493b81aadf
fix(admin): confirm maintenance delivery via MessageSent (retryable until sent); guard resend/cancel on derived state; fix flaky non-unique host wg_ip
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 16:14:01 +02:00
nexxo
b4cf94ee1a
fix(engine-b): real backup/monitoring registration + OC_PASS scoping
...
- CreateCustomerAdmin puts OC_PASS on the docker invocation (survives the &&).
- RegisterBackup creates a real vzdump job via ProxmoxClient::createBackupJob.
- RegisterMonitoring registers via a new MonitoringClient service (interface +
fake + http). Both persist the external id [E] before the breadcrumb, so
acceptance reflects a real registration, not a fabricated row.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 12:33:45 +02:00
nexxo
446da58061
feat(engine-b): 15-step customer pipeline + DNS/Traefik services
...
validate->reserve(placement)->clone->cloudinit->start->guestagent->network->
deploy->nextcloud->admin->dns/tls->backup->monitoring->acceptance->complete.
HetznerDnsClient + TraefikWriter (interface+fake+real), CloudReady notification,
hosts.node (set by RegisterCapacity). Secrets transient/encrypted, never
plaintext. 21 tests incl. mocked end-to-end + crash idempotency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 11:50:26 +02:00
nexxo
4f724d57c9
feat(engine): orchestrator core (state machine + tick + lock)
...
StepResult, ProvisioningStep contract, PipelineRegistry, RunRunner (per-run
lock, advance/retry/fail, backoff, timeout, append-only events + Reverb
StepAdvanced), AdvanceRunJob (provisioning queue), minutely Tick, admin.runs
channel. 21 tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 09:54:52 +02:00
nexxo
254a7d46a0
feat(portal): Fortify auth + Login/2FA/Dashboard + component kit
...
Backend (Fortify):
- laravel/fortify with TOTP two-factor + recovery codes; User uses
TwoFactorAuthenticatable; 2FA credentials hidden from serialization.
- Views off — pages are full-page class-based Livewire components (R1/R2);
Fortify handles POST actions. Home redirect -> /dashboard. v1 scope: login +
2FA only (no public register/reset/passkeys). Seeder gated to local/testing.
Component kit (Blade, token-based, a11y):
- button, input, checkbox, alert, card, badge, stat-tile, otp-input (Alpine,
auto-advance/paste, -safe submit), progress-stepper, nav-item, icon
(Lucide), plus layouts/portal-app app-shell (sidebar drawer + topbar + menu).
Screens (localized DE/EN, R16):
- Login (form -> login.store), Two-factor challenge (OTP + recovery fallback),
Dashboard (KPI stat tiles, instance card, provisioning stepper fixtures,
activity). Routes English (R13).
Tests + verification:
- Pest: 14 green (login ok/invalid/throttle, dashboard guard, component render).
- R12 browser (Puppeteer, prod assets): /, /login, /two-factor-challenge and
the authenticated /dashboard all HTTP 200 with ZERO console errors; login
flow verified end-to-end.
- Test isolation fixed (force test env over injected .env).
- Reviewed with Codex (R15): 4 rounds, all findings fixed, final pass clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 01:20:25 +02:00
nexxo
2ae7595aff
chore: bootstrap CluPilot control-plane (Laravel 13, Docker stack)
...
- Docker dev stack: app (php-fpm+nginx+vite via supervisor), reverb, queue,
scheduler, mariadb 11.4, redis 7 — env-driven ports/UID (HOST_UID=1000).
- Laravel 13.8 + Livewire 3.8 (pinned v3 per R2), Tailwind v4, Reverb, Echo,
phpseclib, wire-elements/modal.
- .env wired to service names; DE default locale (R16); browser Reverb host
env-driven; self-hosted-fonts-ready vite.config (R14).
- Entrypoint bootstraps vendor/node_modules on fresh checkout; bin/clupilot
helper (UID/port env-driven) + shell aliases.
- Reviewed with Codex (R15): 7 findings fixed, 1 verified false-positive.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 00:21:30 +02:00