# Reusable ServiceConcerns presets for component defaults. # # Component contracts.ncl files declare `concerns | _concerns_lib.ServiceConcerns | optional` # and their defaults.ncl files set `concerns | default = presets.` to give # the component an honest declarative surface without repeating boilerplate. # # Presets cover the recurring archetypes in libre-wuji: # - stateless : no TLS/DNS/data — most container runtimes, # kernel modules, OS-level taskservs # - infra_storage_managed : storage backends that handle their own # backup outside per-component policies # (Longhorn engine state via SystemBackupDef) # - tls_endpoint_with_acme : public service with cert-manager TLS # and ACME issuer config; backup decided # at workspace level # - observability_telemetry : Prometheus/Grafana/Loki/Vector — config # in git, data either transient or already # shipped to S3 # - infrastructure_glue : controllers/operators with no user data # (cilium, hccm, csi, ops-controller) let _pending_obs = { kind = 'pending, reason = "ObservabilityImpl iteration deferred — surface stub only", backlog_ref = "OBS-001", } in let _pending_sec = { kind = 'pending, reason = "SecurityImpl iteration deferred — surface stub only", backlog_ref = "SEC-001", } in { presets = { # ── Stateless service ──────────────────────────────────────────────── # Container runtimes (containerd, runc, crun, youki), OS modules, # kernel-level taskservs. No persistent state, no network endpoints # exposed at the component level. stateless = { tls = { kind = 'disabled, reason = "no TLS termination at this layer" }, dns = { kind = 'disabled, reason = "no DNS records owned by this component" }, certs = { kind = 'disabled, reason = "no ACME issuer required" }, backup = { kind = 'disabled, reason = "stateless: configuration in git, no runtime data to capture", }, observability = _pending_obs, security = _pending_sec, }, # ── Storage backend with its own backup model ──────────────────────── # Longhorn (engine state in SystemBackupDef.longhorn_engine), local-path # provisioner, Hetzner CSI, democratic CSI. Their data is captured by # the system-level backup, not per-component. infra_storage_managed = { tls = { kind = 'disabled, reason = "internal cluster storage, no TLS endpoint" }, dns = { kind = 'disabled, reason = "no DNS records owned by this component" }, certs = { kind = 'disabled, reason = "no ACME issuer required" }, backup = { kind = 'disabled, reason = "engine state captured by SystemBackupDef.longhorn_engine (or equivalent system target)", }, observability = _pending_obs, security = _pending_sec, }, # ── Public service with cert-manager TLS + ACME ────────────────────── # docker-mailserver, odoo, zot, anything that terminates HTTPS or SMTPS # via cert-manager. Tls/Dns/Certs concerns get populated from existing # tls_secret/cluster_issuer/cert/dns_records fields. Backup decided at # workspace level (concerns.backup overridden in infra//components/.ncl). tls_endpoint_with_acme = fun args => { tls = { kind = 'enabled, tls_impl = { secret_name = args.tls_secret, issuer_ref = args.cluster_issuer, hostnames = args.hostnames, }, }, dns = { kind = 'enabled, dns_impl = { internal = args.dns_internal, zone = args.dns_zone, }, }, certs = { kind = 'enabled, certs_impl = { acme_server = args.acme_server, email = args.acme_email, secret_ref = args.cert_secret_ref, provider = args.cert_provider, }, }, backup = { kind = 'pending, reason = "BackupPolicy declared at workspace level", backlog_ref = args.backup_backlog_ref, }, observability = _pending_obs, security = _pending_sec, }, # ── Observability stack components (Prometheus/Grafana/Loki/Vector) ── # No user data; configuration in git; metric/log data either transient # (Prometheus WAL) or already shipped to S3 (Loki via boltdb-shipper). observability_telemetry = { tls = { kind = 'disabled, reason = "internal cluster service, ingress-level TLS handled separately" }, dns = { kind = 'disabled, reason = "no DNS records owned by this component" }, certs = { kind = 'disabled, reason = "no ACME issuer required" }, backup = { kind = 'disabled, reason = "config in git; runtime data either transient or shipped to S3 backend", }, observability = { kind = 'enabled, observability_impl = { metrics = { enabled = true, port = 9090, path = "/metrics" }, logs = { enabled = true, sink = 'loki }, traces = { enabled = false }, alerts = [], }, }, security = _pending_sec, }, # ── Infrastructure glue (controllers/operators) ────────────────────── # cilium, hccm, hetzner-csi, ops-controller. State lives in K8s API, # captured by SystemBackupDef.cluster_resources. infrastructure_glue = { tls = { kind = 'disabled, reason = "controller-level RBAC, not TLS endpoint" }, dns = { kind = 'disabled, reason = "no DNS records owned by this component" }, certs = { kind = 'disabled, reason = "no ACME issuer required" }, backup = { kind = 'disabled, reason = "state in K8s API captured by SystemBackupDef.cluster_resources", }, observability = _pending_obs, security = _pending_sec, }, # ── DNS provider service (CoreDNS, external-dns) ───────────────────── # Owns DNS records but typically not TLS endpoint of its own. dns_provider = { tls = { kind = 'disabled, reason = "DNS server, not TLS endpoint" }, dns = { kind = 'enabled, dns_impl = { internal = [], zone = "", }, }, certs = { kind = 'disabled, reason = "no ACME issuer required" }, backup = { kind = 'pending, reason = "zone files captured by SystemBackupDef.external_dns", backlog_ref = "BACKUP-DNS-001", }, observability = _pending_obs, security = _pending_sec, }, # ── Database (PostgreSQL, MariaDB, SurrealDB) ───────────────────────── # Backup with database scope + dump strategy. Decided at workspace level. database = { tls = { kind = 'disabled, reason = "internal cluster service, ingress-level TLS handled separately" }, dns = { kind = 'disabled, reason = "no public DNS records" }, certs = { kind = 'disabled, reason = "no ACME issuer required" }, backup = { kind = 'pending, reason = "BackupPolicy with database scope + dump_strategy declared at workspace level", backlog_ref = "BACKUP-DB-001", }, observability = _pending_obs, security = _pending_sec, }, }, # ── Helper for components that need to compose a custom ServiceConcerns # from individual variants (rather than picking a preset wholesale). builders = { pending = fun reason backlog => { kind = 'pending, reason = reason, backlog_ref = backlog, }, disabled = fun reason => { kind = 'disabled, reason = reason }, }, }