package config import "strings" // defaultServiceChecklist runs one orchestration or CLI step. // Signature: defaultServiceChecklist() []ServiceChecklistCheck. // Why: startup must verify real external behavior per service (not only generic // ingress reachability) so false positives do not pass drills. func defaultServiceChecklist() []ServiceChecklistCheck { return []ServiceChecklistCheck{ { Name: "gitea-api", URL: "https://scm.bstein.dev/api/healthz", AcceptedStatuses: []int{200}, BodyContains: "pass", TimeoutSeconds: 12, }, { Name: "grafana-api", URL: "https://metrics.bstein.dev/api/health", AcceptedStatuses: []int{200}, BodyContains: "\"database\":\"ok\"", TimeoutSeconds: 12, }, { Name: "keycloak-oidc", URL: "https://sso.bstein.dev/realms/atlas/.well-known/openid-configuration", AcceptedStatuses: []int{200}, BodyContains: "\"issuer\":\"https://sso.bstein.dev/realms/atlas\"", TimeoutSeconds: 12, }, { Name: "harbor-registry-api", URL: "https://registry.bstein.dev/v2/", AcceptedStatuses: []int{401}, BodyContains: "unauthorized", TimeoutSeconds: 12, }, { Name: "alerts-ui", URL: "https://alerts.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "Alertmanager", TimeoutSeconds: 12, }, { Name: "auth-gateway-user-session", URL: "https://auth.bstein.dev/", AcceptedStatuses: []int{200}, RequireRobotAuth: true, FollowRedirects: true, BodyContains: "Authenticated", TimeoutSeconds: 12, }, { Name: "home-site", URL: "https://bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "Titan Lab", TimeoutSeconds: 12, }, { Name: "actual-budget-ui", URL: "https://budget.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "Actual", TimeoutSeconds: 12, }, { Name: "element-call-ui", URL: "https://call.live.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "Element Call", TimeoutSeconds: 12, }, { Name: "flux-gitops-ui", URL: "https://cd.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "Weave GitOps", TimeoutSeconds: 12, }, { Name: "chat-ai-health", URL: "https://chat.ai.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "\"ok\": true", TimeoutSeconds: 12, }, { Name: "jenkins-auth-gate", URL: "https://ci.bstein.dev/", AcceptedStatuses: []int{403}, BodyContains: "commenceLogin", TimeoutSeconds: 12, }, { Name: "nextcloud-login-redirect", URL: "https://cloud.bstein.dev/", AcceptedStatuses: []int{302}, LocationContains: "/index.php/login", TimeoutSeconds: 12, }, { Name: "wger-redirect", URL: "https://health.bstein.dev/", AcceptedStatuses: []int{302}, LocationContains: "/en/", TimeoutSeconds: 12, }, { Name: "livekit-edge", URL: "https://kit.live.bstein.dev/", AcceptedStatuses: []int{404}, BodyContains: "404 page not found", TimeoutSeconds: 12, }, { Name: "element-web-ui", URL: "https://live.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "<title>Element", TimeoutSeconds: 12, }, { Name: "logging-ui-user-session", URL: "https://logs.bstein.dev/", AcceptedStatuses: []int{200}, RequireRobotAuth: true, FollowRedirects: true, FinalURLNotContains: "/protocol/openid-connect/auth", BodyContains: "OpenSearch Dashboards", TimeoutSeconds: 12, }, { Name: "logging-api-user-session", URL: "https://logs.bstein.dev/api/status", AcceptedStatuses: []int{200}, RequireRobotAuth: true, FollowRedirects: true, BodyContains: "\"state\":\"green\"", TimeoutSeconds: 12, }, { Name: "longhorn-api-user-session", URL: "https://longhorn.bstein.dev/v1", AcceptedStatuses: []int{200}, RequireRobotAuth: true, FollowRedirects: true, FinalURLNotContains: "/protocol/openid-connect/auth", BodyContains: "\"id\":\"v1\"", TimeoutSeconds: 12, }, { Name: "matrix-auth-ui", URL: "https://matrix.live.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "matrix-authentication-service", TimeoutSeconds: 12, }, { Name: "monero-edge", URL: "https://monero.bstein.dev/", AcceptedStatuses: []int{404}, TimeoutSeconds: 12, }, { Name: "firefly-login-redirect", URL: "https://money.bstein.dev/", AcceptedStatuses: []int{302}, LocationContains: "/login", TimeoutSeconds: 12, }, { Name: "outline-ui", URL: "https://notes.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "Outline", TimeoutSeconds: 12, }, { Name: "collabora-probe", URL: "https://office.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "OK", TimeoutSeconds: 12, }, { Name: "pegasus-ui", URL: "https://pegasus.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "Pegasus", TimeoutSeconds: 12, }, { Name: "harbor-ui", URL: "https://registry.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "Harbor", TimeoutSeconds: 12, }, { Name: "vault-ui-redirect", URL: "https://secret.bstein.dev/", AcceptedStatuses: []int{307}, LocationContains: "/ui/", TimeoutSeconds: 12, }, { Name: "sentinel-user-session", URL: "https://sentinel.bstein.dev/healthz", AcceptedStatuses: []int{200}, RequireRobotAuth: true, FollowRedirects: true, FinalURLNotContains: "/protocol/openid-connect/auth", BodyContains: "ok", TimeoutSeconds: 12, }, { Name: "keycloak-admin-user-session", URL: "https://sso.bstein.dev/admin/", AcceptedStatuses: []int{200}, RequireRobotAuth: true, FollowRedirects: true, FinalURLContains: "/admin/master/console/", FinalURLNotContains: "/login-actions/authenticate", BodyContains: "Keycloak Administration Console", TimeoutSeconds: 12, }, { Name: "jellyfin-edge", URL: "https://stream.bstein.dev/", AcceptedStatuses: []int{302}, LocationContains: "web/", TimeoutSeconds: 12, }, { Name: "planka-ui", URL: "https://tasks.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "PLANKA", TimeoutSeconds: 12, }, { Name: "vaultwarden-ui", URL: "https://vault.bstein.dev/", AcceptedStatuses: []int{200}, BodyContains: "Vaultwarden Web", TimeoutSeconds: 12, }, } } // defaultCriticalServiceEndpoints runs one orchestration or CLI step. // Signature: defaultCriticalServiceEndpoints() []string. // Why: service edge checks are insufficient for protected stacks; endpoint // presence verifies that backends are actually routable before startup success. func defaultCriticalServiceEndpoints() []string { return []string{ "monitoring/victoria-metrics-single-server", "monitoring/grafana", "monitoring/kube-state-metrics", "logging/oauth2-proxy-logs", "logging/opensearch-dashboards", "logging/opensearch-master", } } // mergeServiceChecklistDefaults runs one orchestration or CLI step. // Signature: mergeServiceChecklistDefaults(existing, defaults []ServiceChecklistCheck) []ServiceChecklistCheck. // Why: host configs can keep custom checks while still inheriting mandatory // baseline checks introduced after incident learnings. func mergeServiceChecklistDefaults(existing, defaults []ServiceChecklistCheck) []ServiceChecklistCheck { if len(existing) == 0 { out := make([]ServiceChecklistCheck, 0, len(defaults)) out = append(out, defaults...) return out } defaultByName := map[string]struct{}{} for _, check := range defaults { name := strings.TrimSpace(check.Name) if name == "" { continue } defaultByName[name] = struct{}{} } out := make([]ServiceChecklistCheck, 0, len(defaults)+len(existing)) out = append(out, defaults...) for _, check := range existing { name := strings.TrimSpace(check.Name) if name == "" { continue } if _, exists := defaultByName[name]; exists { continue } out = append(out, check) } return out } // mergeStringDefaults runs one orchestration or CLI step. // Signature: mergeStringDefaults(existing, defaults []string) []string. // Why: keeps baseline startup guards applied while preserving site-specific // additions already declared in host configs. func mergeStringDefaults(existing, defaults []string) []string { if len(existing) == 0 { out := make([]string, 0, len(defaults)) out = append(out, defaults...) return out } seen := map[string]struct{}{} out := make([]string, 0, len(existing)+len(defaults)) for _, item := range existing { key := strings.TrimSpace(item) if key == "" { continue } if _, ok := seen[key]; ok { continue } seen[key] = struct{}{} out = append(out, key) } for _, item := range defaults { key := strings.TrimSpace(item) if key == "" { continue } if _, ok := seen[key]; ok { continue } seen[key] = struct{}{} out = append(out, key) } return out }