Commit Graph

2 Commits (42fd059fddfe011daa5bf4209006dc5166472542)

Author SHA1 Message Date
nexxo 8b631acb72 Fix-Welle Ganz-Branch-Review: weltlesbare .env-Sicherung, blinder Test, drei Installer-Texte
Fuenf Befunde aus der abschliessenden Review, in einer Runde behoben:

- EnvFileEditor::backup() liess PHPs copy() die Umask entscheiden statt den
  Modus der Quelle zu uebernehmen — .env stand mit deploy/install.sh auf 0600,
  jede Sicherung landete trotzdem weltlesbar bei 0644, mit APP_KEY,
  DB_PASSWORD, VPN_CONFIG_KEY und STRIPE_SECRET darin. Reproduziert (per
  kurzzeitigem git stash des Fixes: 420 statt 384) und jetzt durch einen
  expliziten chmod nach dem Kopieren sowie einen neuen Test verhindert.

- HostSeparationTest pruefte "jede Route hat einen Hostnamen" nur scheinbar
  allgemein — deploy/install.sh schreibt ADMIN_HOST_EXCLUSIVE=false als
  Vorgabe, und im nicht-exklusiven Fallback registriert routes/web.php jede
  /admin/*-Route absichtlich ohne Domain. Der Test setzte zwar
  ADMIN_HOST_EXCLUSIVE=true, sagte aber nirgends, dass genau das die
  Voraussetzung der Pruefung ist. hostSeparationTable() gibt AdminArea::
  isExclusive() jetzt als Out-Parameter zurueck, gelesen waehrend die zweite
  Anwendung noch gebootet ist, und der Test besteht darauf.

- clupilot:bind-hosts existierte, aber nichts sagte einem Operator, dass es
  ihn braucht. deploy/update.sh druckt jetzt einen eigenen Hinweis, wenn
  APP_HOST in .env leer ist — mit der vollen docker-compose-Zeile statt der
  internen in_app-Abkuerzung, weil der Operator sie in seiner eigenen Shell
  eintippt.

- ask STATUS_DOMAIN und ask FILES_DOMAIN versprachen "blank to keep it auf
  jedem Host", fuellten Enter aber ueber den dritten ask()-Parameter mit dem
  Default. Fuer FILES_DOMAIN war das kein Schoenheitsfehler: der Default
  verschiebt /bootstrap.tar.gz vom Portal weg, bevor DNS fuer den neuen Namen
  existiert. Beide Defaults entfernt.

- ask WWW_DOMAIN erklaerte nicht, dass SITE_HOST mehrere kommagetrennte Namen
  traegt (der erste kanonisch, der Rest leitet dauerhaft um) — ein Operator,
  der die Apex-Domain zusaetzlich zu www. binden wollte, hatte keinen Weg,
  das aus dem Prompt zu erfahren. Nur der Prompt-Text geaendert, kein neuer
  Prompt, Default unveraendert.

Voller Testlauf: 2953 passed (Baseline 2952 + der neue Backup-Berechtigungs-
Test), 0 failed. routes/web.php, RestrictAdminHost, config/fortify.php und
PublicSiteGate unangetastet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 15:56:21 +02:00
nexxo 90131f088a Add a raw .env editor to the Integrations page, with a net under it
Everything the console has no field for is still real — MAIL_*, DB_*,
APP_KEY, whichever key nobody has built a form for yet — and without a way to
touch it from here, the operator needs a shell and the console page misses
its own point. EnvFileEditor is the net, not just the warning:

1. Validates before writing. A line that is neither blank, nor a comment, nor
   KEY=value is rejected outright, and an empty file (syntactically "valid" by
   that rule, but not survivable) is refused too. write() never touches the
   file before checking the new content.
2. Backs up before every write that actually happens — a timestamped copy
   beside .env, before the new content lands. Never pruned automatically; the
   page says so, next to where it says where they land.
3. Names the keys a mistake here can lock an operator out with — APP_KEY,
   DB_*, REDIS_*, SESSION_* — rather than a blanket warning nobody reads.
4. Gated by secrets.manage and the same confirmed password the vault entries
   use — this is the one place on the page that can reach every credential
   the vault otherwise keeps write-only.
5. Says plainly what saving does not do: queue, queue-provisioning, scheduler
   and reverb only read .env at their own startup, and names the restart
   command plus config:clear.
6. Marks which .env keys SecretVault currently overrides, so editing a line
   that a stored vault value already shadows does not look broken.

Two issues surfaced by Codex review and fixed before this commit: the raw
file content stayed in the Livewire component snapshot after the password
confirmation window expired on its own (not only on an explicit re-lock), and
the first save on an installation with no .env yet failed trying to back up a
file that was never there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 01:51:27 +02:00