feat: replace hardcoded service names with ServiceRegistry-driven Caddy and CoreDNS config
Unit Tests / test (push) Failing after 11s

Previously, CaddyManager and NetworkManager contained hardcoded lists of
service names (calendar, files, mail, webdav, etc.), meaning every new
service required a code change to appear in Caddy routes and DNS records.
Now both managers accept a service_registry parameter and derive their
service lists dynamically from the registry at runtime.

- CaddyManager: new _build_registry_service_routes() and
  _http01_service_pairs() methods pull routes from the registry
- NetworkManager: new _get_service_subdomains() method returns registry
  subdomains with a hardcoded fallback when no registry is wired in;
  _build_dns_records, stale-record detection, and service name sets all
  use the registry
- managers.py: service_registry constructed before network_manager so it
  can be injected into both CaddyManager and NetworkManager
- service_registry.py: validation chokepoint in get_caddy_routes() rejects
  invalid subdomain/backend values and reserved service names
- service_store_manager.py: _validate_manifest now validates top-level
  subdomain, backend, extra_subdomains, and extra_backends fields
- tests: 24 new tests covering registry-driven routing and DNS subdomain
  generation (test_caddy_registry_integration.py)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-28 18:27:52 -04:00
parent 63c0dfb9d9
commit 16fb362df7
12 changed files with 1312 additions and 46 deletions
+9 -4
View File
@@ -784,8 +784,8 @@ def apply_pending_config():
@bp.route('/api/config/backup', methods=['POST'])
def create_config_backup():
try:
from app import config_manager, service_bus, EventType
backup_id = config_manager.backup_config()
from app import config_manager, service_bus, service_registry, EventType
backup_id = config_manager.backup_config(service_registry=service_registry)
service_bus.publish_event(EventType.BACKUP_CREATED, 'api', {
'backup_id': backup_id,
'timestamp': datetime.utcnow().isoformat()
@@ -809,9 +809,14 @@ def list_config_backups():
@bp.route('/api/config/restore/<backup_id>', methods=['POST'])
def restore_config(backup_id):
try:
from app import config_manager, service_bus, EventType
from app import config_manager, service_bus, service_registry, EventType
data = request.get_json(silent=True) or {}
success = config_manager.restore_config(backup_id, services=data.get('services'))
services = data.get('services')
success = config_manager.restore_config(
backup_id,
services=services,
service_registry=service_registry if services is None else None,
)
if success:
service_bus.publish_event(EventType.RESTORE_COMPLETED, 'api', {
'backup_id': backup_id,