113 lines
10 KiB
PHP
113 lines
10 KiB
PHP
<?php
|
|
|
|
/*
|
|
* Die Bereitschaftsprüfung (App\Support\Readiness). Jeder Satz unter
|
|
* `*_breaks` beantwortet nicht „was fehlt", sondern „was passiert, wenn es
|
|
* fehlt bleibt" — siehe den Kopfkommentar von App\Support\Readiness\Check.
|
|
*/
|
|
return [
|
|
'page_title' => 'Betriebsbereitschaft',
|
|
'page_sub' => 'Jedes Pflichtfeld dieser Installation an einer Stelle — bis oben „Bereit für Livebetrieb" steht, ist hier noch etwas offen.',
|
|
'ready_test' => 'Bereit für Testbetrieb',
|
|
'ready_live' => 'Bereit für Livebetrieb',
|
|
'not_ready' => '{1} Noch nicht bereit — :n blockierender Punkt offen|[2,*] Noch nicht bereit — :n blockierende Punkte offen',
|
|
|
|
'group' => [
|
|
'billing' => 'Abrechnung',
|
|
'onboarding' => 'Host-Onboarding',
|
|
'provisioning' => 'Bereitstellung',
|
|
'delivery' => 'Zustellung',
|
|
'operation' => 'Betrieb',
|
|
],
|
|
|
|
'status' => [
|
|
'satisfied' => 'Erfüllt',
|
|
'blocking' => 'Blockierend',
|
|
'warning' => 'Warnung',
|
|
],
|
|
|
|
'run_check' => 'Prüfen',
|
|
'check_ok' => 'Geprüft: in Ordnung',
|
|
'check_failed' => 'Geprüft: nicht in Ordnung',
|
|
'check_key_mode' => 'Der Schlüssel gehört zum Konto für :mode.',
|
|
'check_key_mode_conflict' => 'Diese Installation läuft aber im :mode — der Schlüssel liegt im falschen Platz.',
|
|
'fix_link' => 'Beheben',
|
|
'last_heartbeat' => 'Letzter Herzschlag: :when',
|
|
|
|
'mode' => [
|
|
'test' => 'Testbetrieb',
|
|
'live' => 'Livebetrieb',
|
|
],
|
|
|
|
'billing' => [
|
|
'stripe_secret' => 'Stripe-Schlüssel (:mode)',
|
|
'stripe_secret_breaks' => 'Ohne ihn nimmt die Kasse keine Bestellung an — es entsteht gar kein Auftrag.',
|
|
// Zwei getrennte Sätze, weil die Folgen entgegengesetzt sind: einmal
|
|
// fließt echtes Geld, das nicht fließen sollte, einmal fließt keines,
|
|
// das fließen sollte. Ein gemeinsamer Satz müsste beides andeuten und
|
|
// sagte am Ende keins von beidem.
|
|
'stripe_secret_test_slot_breaks' => 'Im Testplatz liegt ein Live-Schlüssel. Jede Bestellung bucht damit echtes Geld ab, während diese Seite und die Konsole „Testbetrieb" anzeigen — ein Probekauf ist dann ein echter Kauf, mit echter Karte und echter Abbuchung.',
|
|
'stripe_secret_live_slot_breaks' => 'Im Live-Platz liegt ein Testschlüssel. Der Kunde durchläuft die Kasse, es wird nie Geld eingezogen, und die Bestellung sieht trotzdem bezahlt aus — die Bereitstellung läuft, der Beleg wird ausgestellt, und auf dem Konto kommt nichts an.',
|
|
'webhook_secret' => 'Stripe-Signaturschlüssel',
|
|
'webhook_secret_breaks' => 'Ohne ihn wird eine Zahlung nie verbucht: der Kunde zahlt, und nichts passiert.',
|
|
'company_details' => 'Firmendaten vollständig',
|
|
'company_details_breaks' => 'IssueInvoice verweigert die Ausstellung. Die Bereitstellung läuft trotzdem durch — der Kunde bekommt eine laufende Cloud ohne Beleg.',
|
|
'invoice_series' => 'Rechnungsserie je Belegart',
|
|
'invoice_series_breaks' => 'IssueInvoice bricht beim Ausstellen ab, sobald eine Serie fehlt oder deaktiviert ist. Die Bereitstellung läuft trotzdem durch — der Kunde bekommt eine laufende Cloud ohne Beleg, und der Fehler landet nur im Log.',
|
|
'catalogue_synced' => 'Stripe-Katalog abgeglichen',
|
|
'catalogue_synced_breaks' => 'Ein geprüfter EU-Firmenkunde kann nicht bestellen, weil sein Netto-Preis bei Stripe fehlt.',
|
|
// Sagt, was passiert, und was dagegen hilft — inklusive der
|
|
// unbequemen Hälfte: `stripe:sync-catalogue` überspringt jede Zeile,
|
|
// die schon eine ID trägt, repariert das also NICHT von selbst. Ein
|
|
// Satz, der nur „bitte neu abgleichen" sagte, schickte den Betreiber
|
|
// auf einen Befehl, der ihm „already in step" antwortet.
|
|
'catalogue_account_breaks' => 'Die gespeicherten Stripe-Produkt- und Preis-IDs wurden in einem anderen Konto angelegt als dem, das jetzt gilt (:mode) — Stripe-Objekte gehören dem Konto, das sie ausgestellt hat. Jede Bestellung scheitert damit an der Kasse mit „No such price": kein Auftrag, keine Zahlung. Ein neuer Lauf von stripe:sync-catalogue allein genügt nicht, er überspringt jede Zeile, die schon eine ID trägt; erst nach dem Leeren von plan_families.stripe_product_id und plan_prices.stripe_price_id sowie der Register stripe_plan_prices und stripe_addon_prices legt er den Katalog im aktiven Konto neu an.',
|
|
],
|
|
|
|
'onboarding' => [
|
|
'ssh_key' => 'SSH-Schlüssel für Hosts',
|
|
'ssh_key_breaks' => 'EstablishSshTrust legt nur den öffentlichen Teil auf dem Host ab; jeder Schritt danach — und jede Traefik-Änderung auf einem bereits laufenden Host — verbindet sich mit diesem privaten Schlüssel. Ohne ihn bricht das Onboarding im zweiten Schritt ab, und kein Routing-Update erreicht mehr einen Host, der längst live ist.',
|
|
'secrets_key' => 'Tresor-Schlüssel (SECRETS_KEY)',
|
|
'secrets_key_breaks' => 'Ohne ihn kann kein Geheimnis in dieser Installation gespeichert oder gelesen werden — nicht der Stripe-Schlüssel, nicht der DNS-Token, kein Host-Token. Die Konsole zeigt jedes dieser Felder als leer, egal was je eingetragen wurde.',
|
|
'vpn_config_key' => 'VPN-Konfigurationsschlüssel (VPN_CONFIG_KEY)',
|
|
'vpn_config_key_breaks' => 'Ohne ihn verweigert ConfigVault das Speichern jeder VPN-Konfiguration, statt sie im Klartext abzulegen — ein ausgestellter Zugang lässt sich dann nirgends mehr nachlesen.',
|
|
'wg_hub' => 'WireGuard-Hub vollständig konfiguriert',
|
|
'wg_hub_breaks' => 'Zwei von drei Werten sind kein halber Tunnel, sondern gar keiner: ConfigureWireguard schreibt die Peer-Konfiguration aus allen dreien auf einmal. Fehlt einer, bekommt der neue Host keinen Tunnel zur Verwaltung, und niemand kann ihn erreichen.',
|
|
'datacenter' => 'Mindestens ein Rechenzentrum',
|
|
'datacenter_breaks' => 'Ohne Rechenzentrum hat das Host-Anlegen-Formular nichts zur Auswahl, und ValidateHostInput bricht als allererster Schritt der Kette ab — noch bevor überhaupt eine SSH-Verbindung versucht wird.',
|
|
],
|
|
|
|
'provisioning' => [
|
|
'dns_token' => 'Hetzner-DNS-Token',
|
|
'dns_token_breaks' => 'Ohne ihn scheitert ConfigureDnsAndTls am A-Eintrag für die neue Instanz — mitten in der Bereitstellung, nachdem die Maschine schon läuft und der Kunde schon bezahlt hat.',
|
|
'dns_zone' => 'DNS-Zone',
|
|
'dns_zone_breaks' => 'Leer, und HttpHetznerDnsClient sucht bei Hetzner nach einer Zone ohne Namen: zoneId() findet keine, wirft „DNS zone not found", und ConfigureDnsAndTls scheitert damit an genau der Stelle, an der auch der fehlende DNS-Token zuschlägt — mitten in der Bereitstellung, nachdem der Kunde schon bezahlt hat.',
|
|
'traefik_path' => 'Traefik-Konfigurationspfad',
|
|
'traefik_path_breaks' => 'Leer, und SshTraefikWriter schreibt die Routendatei an die Wurzel des Dateisystems statt in Traefiks eigenes Verzeichnis. Der Schritt meldet trotzdem Erfolg — Traefik sieht die neue Route nur nie, und die Cloud des Kunden bleibt über ihre Adresse unerreichbar.',
|
|
'usable_host' => 'Mindestens ein einsetzbarer Host',
|
|
'usable_host_breaks' => 'Ein aktiver Host ohne lesbaren Token wird von ReserveResources trotzdem für eine neue Bestellung ausgewählt. Der Auftrag stirbt danach in CloneVirtualMachine — nachdem der Kunde schon bezahlt hat.',
|
|
'vm_template' => 'VM-Vorlage je veröffentlichter Version',
|
|
'vm_template_breaks' => 'Eine veröffentlichte Version ohne template_vmid lässt CloneVirtualMachine sofort mit „template_missing" scheitern — für jede Bestellung dieses Plans, nachdem der Kunde schon bezahlt hat.',
|
|
'monitoring_token' => 'Überwachungs-Token',
|
|
'monitoring_token_breaks' => 'Ohne ihn scheitert RegisterMonitoring. Ist `monitoring.required` nicht gesetzt (die Vorgabe), liefert die Bereitstellung trotzdem aus — nur ohne Überwachung, bis der Schlüssel nachgetragen wird. Ist es gesetzt, bricht der Lauf stattdessen ab, und die Bereitstellung hält an, bis der Schlüssel da ist.',
|
|
],
|
|
|
|
'delivery' => [
|
|
'mailer_not_log' => 'Mailtransport stellt tatsächlich zu',
|
|
'mailer_not_log_breaks' => 'Bei mail.default=log, =array oder ganz ohne gesetzten Standard läuft die Maschine, der Beleg wird ausgestellt, und die Mail, die dem Kunden seine fertige Cloud ankündigt, verlässt den Server nie — sie landet in einer Datei oder verschwindet spurlos. Der Kunde erfährt nie, dass er bezahlt hat und etwas läuft.',
|
|
'mailbox' => 'Mindestens eine Mailbox',
|
|
'mailbox_breaks' => 'Ohne Mailbox wirft der Versand aus CompleteProvisioning eine Ausnahme — der letzte Schritt der Bereitstellung schlägt fehl und wiederholt sich, obwohl die Maschine längst läuft und der Kunde schon bezahlt hat.',
|
|
'mail_templates' => 'Mindestens eine Antwortvorlage',
|
|
'mail_templates_breaks' => 'Auf der Kundenseite bleibt die Vorlagen-Auswahl leer, wo sie sonst anklickbare Antworten anbietet — der Support-Mitarbeiter merkt es sofort beim Öffnen, findet aber nichts zum Einfügen und tippt jede Antwort neu. Zwei Kunden mit derselben Frage bekommen dadurch leicht zwei unterschiedliche Auskünfte, ohne dass irgendwo ein Fehler erscheint.',
|
|
'inbound_password' => 'Passwort für eingehende Mail',
|
|
'inbound_password_breaks' => 'Ohne es liefert der Mail-Abruf jedes Mal eine leere Liste. Der Zeitplan läuft unauffällig weiter, aber keine Kundenantwort erreicht je die Inbox der Konsole, und nirgends erscheint ein Fehler.',
|
|
],
|
|
|
|
'operation' => [
|
|
'scheduler' => 'Zeitplaner läuft',
|
|
'scheduler_breaks' => 'Ohne ihn läuft kein einziger Zeitplan aus routes/console.php — nicht die Rechnungsarchivierung, nicht die Vertragsprüfung, nicht dieser Herzschlag selbst. Eine bezahlte Bestellung wartet auf TickProvisioning, das nie angestoßen wird, und die Konsole zeigt dieselbe Ruhe wie an einem Tag ohne Bestellungen.',
|
|
'queue_provisioning' => 'Bereitstellungs-Worker läuft',
|
|
'queue_provisioning_breaks' => 'Der Zeitplaner kann laufen und Aufträge auf die provisioning-Warteschlange stellen, ohne dass sie je jemand abholt. Eine bezahlte Bestellung bleibt dann liegen — kein Fehler, keine Meldung, einfach nichts, bis jemand von Hand nachsieht.',
|
|
],
|
|
];
|