From 154988bbeb8c226fb55aee82cfec5997c81a36c4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 11:39:40 +0000 Subject: [PATCH] Address review feedback: fix hostname regex, use CSS class for NWC warning banner, clarify test comment --- app/sovran_systemsos_web/server.py | 7 +++++-- app/sovran_systemsos_web/static/css/domain-setup.css | 12 ++++++++++++ app/sovran_systemsos_web/static/js/features.js | 4 ++-- app/tests/test_domain_conflict.py | 5 ++++- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/app/sovran_systemsos_web/server.py b/app/sovran_systemsos_web/server.py index b7c08ca..9d4880d 100644 --- a/app/sovran_systemsos_web/server.py +++ b/app/sovran_systemsos_web/server.py @@ -4091,8 +4091,11 @@ def _validate_safe_name(name: str) -> bool: return bool(name) and _SAFE_NAME_RE.match(name) is not None -# Hostname characters: letters, digits, hyphens, dots (no underscores in FQDNs) -_HOSTNAME_RE = re.compile(r'^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$') +# Hostname characters: letters, digits, hyphens only within labels; dots separate labels. +# Each label must start and end with a letter or digit; no consecutive dots. +_HOSTNAME_RE = re.compile( + r'^[a-z0-9]([a-z0-9\-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9\-]*[a-z0-9])?)*$' +) # Managed domain keys that produce Caddy virtual-host blocks (excluding sslemail) _MANAGED_DOMAIN_KEYS: frozenset[str] = frozenset([ diff --git a/app/sovran_systemsos_web/static/css/domain-setup.css b/app/sovran_systemsos_web/static/css/domain-setup.css index 8b0e770..2db406e 100644 --- a/app/sovran_systemsos_web/static/css/domain-setup.css +++ b/app/sovran_systemsos_web/static/css/domain-setup.css @@ -171,3 +171,15 @@ domain-field-actions { .port-req-status { font-weight: 600; } + +/* ── Wallet Connections unique-hostname warning ───────────────────── */ + +.domain-nwc-warning { + margin-bottom: 14px; + padding: 10px 14px; + background: rgba(255, 180, 0, 0.10); + border: 1px solid var(--warning-color, #f59e0b); + border-radius: 8px; + font-size: 0.88rem; + line-height: 1.6; +} diff --git a/app/sovran_systemsos_web/static/js/features.js b/app/sovran_systemsos_web/static/js/features.js index 8b4339c..fcb7b8d 100644 --- a/app/sovran_systemsos_web/static/js/features.js +++ b/app/sovran_systemsos_web/static/js/features.js @@ -76,7 +76,7 @@ function openDomainSetupModal(feat, onSaved) { } var nwcWarning = isWalletConnections - ? '
' + + ? '
' + '⚠ Wallet Connections requires its own unique hostname. ' + 'Use a new subdomain such as lightning.yourdomain.com, or a separate domain. ' + 'Do not reuse a domain already assigned to Matrix, Nextcloud, WordPress, BTCPay Server, Vaultwarden, Haven, or another Caddy site.' + @@ -193,7 +193,7 @@ function openDomainReconfigureModal(feat, existingDomain, onSaved) { } var nwcWarning = isWalletConnections - ? '
' + + ? '
' + '⚠ Wallet Connections requires its own unique hostname. ' + 'Use a new subdomain such as lightning.yourdomain.com, or a separate domain. ' + 'Do not reuse a domain already assigned to Matrix, Nextcloud, WordPress, BTCPay Server, Vaultwarden, Haven, or another Caddy site.' + diff --git a/app/tests/test_domain_conflict.py b/app/tests/test_domain_conflict.py index f28bffd..01605bc 100644 --- a/app/tests/test_domain_conflict.py +++ b/app/tests/test_domain_conflict.py @@ -165,7 +165,10 @@ class ValidateHostnameTests(unittest.TestCase): self.assertFalse(server._validate_hostname("")) def test_invalid_trailing_dot(self): - # After normalization a trailing dot should have been removed. + # The hostname validator rejects trailing dots directly. + # In the API flow, normalization removes exactly one trailing dot before + # this validator is called, so a single trailing dot in user input is + # handled before reaching validation. self.assertFalse(server._validate_hostname("foo.example.com.")) def test_invalid_with_underscore(self):