*/ public static function all(): array { return [ new Check( key: 'provisioning.dns_token', group: self::GROUP, severity: Check::SEVERITY_BLOCKING, label: __('readiness.provisioning.dns_token'), breaks: __('readiness.provisioning.dns_token_breaks'), // The DNS card (token + zone + Traefik path) is on the // 'services' tab — 'integrations' is not a member of // Integrations::TABS at all (Fix-Runde, Befund 1). tab: 'services', satisfied: filled(app(SecretVault::class)->get('dns.token')), ), new Check( key: 'provisioning.dns_zone', group: self::GROUP, severity: Check::SEVERITY_BLOCKING, label: __('readiness.provisioning.dns_zone'), breaks: __('readiness.provisioning.dns_zone_breaks'), // Same DNS card as provisioning.dns_token just above. tab: 'services', satisfied: filled(ProvisioningSettings::dnsZone()), ), new Check( key: 'provisioning.traefik_path', group: self::GROUP, severity: Check::SEVERITY_WARNING, label: __('readiness.provisioning.traefik_path'), breaks: __('readiness.provisioning.traefik_path_breaks'), // Same DNS card — traefikDynamicPath is a field on it. tab: 'services', satisfied: filled(ProvisioningSettings::traefikDynamicPath()), ), new Check( key: 'provisioning.usable_host', group: self::GROUP, severity: Check::SEVERITY_BLOCKING, label: __('readiness.provisioning.usable_host'), breaks: __('readiness.provisioning.usable_host_breaks'), tab: 'hosts', // `active` ALONE is not enough. A host without a readable // token is still selectable to ReserveResources, and the // order then dies in CloneVirtualMachine — after payment. satisfied: Host::query() ->where('status', 'active') ->whereNotNull('api_token_ref') ->exists(), ), new Check( key: 'provisioning.vm_template', group: self::GROUP, severity: Check::SEVERITY_BLOCKING, label: __('readiness.provisioning.vm_template'), breaks: __('readiness.provisioning.vm_template_breaks'), tab: 'plans', // A field check only. Whether the template actually EXISTS on // a node is answered by the button in Task 9 — that has to // ask Proxmox, and a live API call does not belong on every // page load of this readiness page. satisfied: PlanVersion::query() ->whereNotNull('published_at') ->whereNull('template_vmid') ->doesntExist(), ), new Check( key: 'provisioning.monitoring_token', group: self::GROUP, // Follows the same condition RegisterMonitoring itself reads // (RegisterMonitoring.php: `if (config('provisioning. // monitoring.required', false)) { throw $e; }`). Warning by // default — monitoring degrades, then the run continues — but // an operator who has switched that setting on made // monitoring a real gate, and a fixed severity would then // claim a looser rule than the pipeline actually enforces. severity: config('provisioning.monitoring.required', false) ? Check::SEVERITY_BLOCKING : Check::SEVERITY_WARNING, label: __('readiness.provisioning.monitoring_token'), breaks: __('readiness.provisioning.monitoring_token_breaks'), // The monitoring card is on the 'services' tab too. tab: 'services', satisfied: filled(app(SecretVault::class)->get('monitoring.token')), ), ]; } }