get('/superuser/coolify', function () { global $response; $this->requirePermission('superuser_coolify_view'); $response->success((new coolify_manager())->summary()); }, [ 'superuser_coolify_view' => 'View Coolify-managed replicated infrastructure targets', ]); $this->get('/superuser/coolify/load-balancer', function () { global $response; $this->requirePermission('superuser_coolify_view'); $response->success((new coolify_manager())->loadBalancerSummary()); }, [ 'superuser_coolify_view' => 'View the Coolify public gateway Load Balancer state', ]); $this->post('/superuser/coolify/load-balancer/reconcile', function () { global $response; $this->requirePermission('superuser_coolify_manage'); try { $parameters = $this->getParametersAsArray(); $dryRun = array_key_exists('dry_run', $parameters) ? filter_var($parameters['dry_run'], FILTER_VALIDATE_BOOLEAN) : !filter_var($parameters['enforce'] ?? false, FILTER_VALIDATE_BOOLEAN); $result = (new coolify_manager())->reconcileLoadBalancer($dryRun, $this->actorUserId()); if (($result['ok'] ?? false) !== true) { $response->error($result, 409); } $response->success($result); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 409); } }, [ 'superuser_coolify_manage' => 'Reconcile Hetzner Load Balancer targets and services for the Coolify gateway', ]); $this->post('/superuser/coolify/load-balancer/routes/deploy', function () { global $response; $this->requirePermission('superuser_coolify_manage'); try { $parameters = $this->getParametersAsArray(); $dryRun = array_key_exists('dry_run', $parameters) ? filter_var($parameters['dry_run'], FILTER_VALIDATE_BOOLEAN) : !filter_var($parameters['enforce'] ?? false, FILTER_VALIDATE_BOOLEAN); $result = (new coolify_manager())->deployGatewayApplicationRoutes($dryRun, $this->actorUserId()); if (($result['ok'] ?? false) !== true) { $response->error($result, 409); } $response->success($result); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 409); } }, [ 'superuser_coolify_manage' => 'Deploy the Coolify API application route for the public gateway host', ]); $this->post('/superuser/coolify/load-balancer/api/deploy', function () { global $response; $this->requirePermission('superuser_coolify_manage'); try { $parameters = $this->getParametersAsArray(); $dryRun = array_key_exists('dry_run', $parameters) ? filter_var($parameters['dry_run'], FILTER_VALIDATE_BOOLEAN) : !filter_var($parameters['enforce'] ?? false, FILTER_VALIDATE_BOOLEAN); $deployRoutes = array_key_exists('deploy_routes', $parameters) ? filter_var($parameters['deploy_routes'], FILTER_VALIDATE_BOOLEAN) : true; $result = (new coolify_manager())->deployGatewayApiCode($dryRun, $deployRoutes, $this->actorUserId()); if (($result['ok'] ?? false) !== true) { $response->error($result, 409); } $response->success($result); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 409); } }, [ 'superuser_coolify_manage' => 'Deploy the latest Coolify API code for the public gateway host', ]); $this->get('/superuser/coolify/github-runners', function () { global $response; $this->requirePermission('superuser_coolify_view'); $response->success((new coolify_manager())->githubRunnerSummary()); }, [ 'superuser_coolify_view' => 'View Coolify-managed GitHub Actions runner state', ]); $this->post('/superuser/coolify/github-runners/deploy', function () { global $response; $this->requirePermission('superuser_coolify_manage'); try { $parameters = $this->getParametersAsArray(); $parameters['dry_run'] = array_key_exists('dry_run', $parameters) ? filter_var($parameters['dry_run'], FILTER_VALIDATE_BOOLEAN) : !filter_var($parameters['enforce'] ?? false, FILTER_VALIDATE_BOOLEAN); $result = (new coolify_manager())->deployGithubRunners( $parameters, $this->actorUserId() ); if (($result['ok'] ?? false) !== true) { $response->error($result, 409); } $response->success($result); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 409); } }, [ 'superuser_coolify_manage' => 'Create or update the Coolify-managed GitHub Actions runner service', ]); $this->get('/superuser/coolify/gateways', function () { global $response; $this->requirePermission('superuser_coolify_view'); $response->success((new coolify_manager())->listLoadBalancerGateways()); }, [ 'superuser_coolify_view' => 'List Coolify public gateway Load Balancer targets', ]); $this->post('/superuser/coolify/gateways', function () { global $response; $this->requirePermission('superuser_coolify_manage'); try { $response->success((new coolify_manager())->saveLoadBalancerGateway( $this->getParametersAsArray(), $this->actorUserId() ), 201); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 400); } }, [ 'superuser_coolify_manage' => 'Create or update Coolify public gateway Load Balancer targets', ]); $this->post('/superuser/coolify/gateways/{id}/test', function () { global $response; $this->requirePermission('superuser_coolify_manage'); try { $response->success((new coolify_manager())->testLoadBalancerGateway( $this->routeId(), $this->actorUserId() )); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 409); } }, [ 'superuser_coolify_manage' => 'Probe an individual Coolify public gateway target', ]); $this->post('/superuser/coolify/instances', function () { global $response; $this->requirePermission('superuser_coolify_manage'); try { $response->success((new coolify_manager())->createInstance( $this->getParametersAsArray(), $this->actorUserId() ), 201); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 400); } }, [ 'superuser_coolify_manage' => 'Create and update Coolify API connections', ]); $this->post('/superuser/coolify/instances/{id}/test', function () { global $response; $this->requirePermission('superuser_coolify_manage'); $response->success((new coolify_manager())->testInstance($this->routeId(), $this->actorUserId())); }, [ 'superuser_coolify_manage' => 'Test Coolify API connectivity', ]); $this->get('/superuser/coolify/instances/{id}/placement', function () { global $response; $this->requirePermission('superuser_coolify_view'); try { $response->success((new coolify_manager())->discoverInstancePlacement($this->routeId())); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 502); } }, [ 'superuser_coolify_view' => 'Discover Coolify projects, environments, and servers for target placement', ]); $this->get('/superuser/coolify/targets', function () { global $response; $this->requirePermission('superuser_coolify_view'); $kind = (string)($this->getParameter('kind') ?? ''); $response->success((new coolify_manager())->listTargets($kind !== '' ? $kind : null)); }, [ 'superuser_coolify_view' => 'List Coolify-managed replication targets', ]); $this->post('/superuser/coolify/targets', function () { global $response; $this->requirePermission('superuser_coolify_manage'); try { $response->success((new coolify_manager())->createTarget( $this->getParametersAsArray(), $this->actorUserId() ), 201); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 409); } }, [ 'superuser_coolify_manage' => 'Create Coolify-managed MariaDB, Redis, and MinIO replication targets', ]); $this->post('/superuser/coolify/targets/{id}/reconcile', function () { global $response; $this->requirePermission('superuser_coolify_reconcile'); try { $result = (new coolify_manager())->reconcileTarget($this->routeId(), $this->actorUserId()); if (($result['ok'] ?? false) !== true) { $response->error($result, 409); } $response->success($result); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 409); } }, [ 'superuser_coolify_reconcile' => 'Reconcile expected Coolify deployment state without primary downtime', ]); $this->post('/superuser/coolify/targets/{id}/deploy', function () { global $response; $this->requirePermission('superuser_coolify_reconcile'); try { $result = (new coolify_manager())->deployTarget($this->routeId(), $this->actorUserId()); if (($result['ok'] ?? false) !== true) { $response->error($result, 409); } $response->success($result); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 409); } }, [ 'superuser_coolify_reconcile' => 'Deploy and provision a passive Coolify-managed replication target', ]); $this->post('/superuser/coolify/targets/{id}/restart', function () { global $response; $this->requirePermission('superuser_coolify_reconcile'); try { $result = (new coolify_manager())->restartTarget($this->routeId(), $this->actorUserId()); if (($result['ok'] ?? false) !== true) { $response->error($result, 409); } $response->success($result); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 409); } }, [ 'superuser_coolify_reconcile' => 'Restart a passive Coolify target without restarting the active primary', ]); $this->post('/superuser/coolify/targets/{id}/failover', function () { global $response; $this->requirePermission('superuser_coolify_failover'); try { $response->success((new coolify_manager())->failoverTarget($this->routeId(), $this->actorUserId())); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 409); } }, [ 'superuser_coolify_failover' => 'Promote a healthy Coolify-managed replica through the replication module', ]); $this->delete('/superuser/coolify/targets/{id}', function () { global $response; $this->requirePermission('superuser_coolify_manage'); try { $response->success((new coolify_manager())->deleteTarget( $this->routeId(), $this->getParametersAsArray(), $this->actorUserId() )); } catch (Throwable $throwable) { $response->error(['message' => $throwable->getMessage()], 409); } }, [ 'superuser_coolify_manage' => 'Delete Coolify target mappings with explicit destructive confirmation', ]); } private function routeId(): int { $id = (int)$this->fromRoute('id'); $this->requireParameterIntPositive($id, 'id'); return $id; } private function actorUserId(): ?int { try { $user = (new authentication())->get_user(); return $user !== false && isset($user->id) ? (int)$user->id : null; } catch (Throwable) { return null; } } }