diff --git a/internal/core/templates/add_repeater.html b/internal/core/templates/add_repeater.html index 0262ae0..070fca4 100644 --- a/internal/core/templates/add_repeater.html +++ b/internal/core/templates/add_repeater.html @@ -176,14 +176,16 @@
diff --git a/internal/core/templates/config_regions_edit.html b/internal/core/templates/config_regions_edit.html index fd785d1..91c6c6f 100644 --- a/internal/core/templates/config_regions_edit.html +++ b/internal/core/templates/config_regions_edit.html @@ -129,11 +129,14 @@ function addBlock(kind) {
-
+
-
+
-
+
{{/* Settings/state: the region's own properties, shown as switches (matching the root's flood switch) so each toggle reads clearly with its label, diff --git a/internal/core/templates/repeater_docs.html b/internal/core/templates/repeater_docs.html index ead6ed3..6c7684d 100644 --- a/internal/core/templates/repeater_docs.html +++ b/internal/core/templates/repeater_docs.html @@ -16,7 +16,8 @@ Shown on the public page when one is published. Do not put gate codes, lock combinations, or other site-access secrets here — use the internal section below for those.

- + @@ -29,7 +30,8 @@ Sensitive site-access details — gate codes, lock combinations, landlord/contact info, climbing notes. Only the owner, stewards, and people you've shared with can read this. Never shown on the public page.

- + diff --git a/internal/marketing/templates/docs.html b/internal/marketing/templates/docs.html index e8f3363..dcf0f1a 100644 --- a/internal/marketing/templates/docs.html +++ b/internal/marketing/templates/docs.html @@ -25,7 +25,8 @@

Run this on your repeater — through the repeater console in the MeshCore companion app, directly over USB serial, or let MeshTender run it for you during USB setup:

{{if .SetPermCommand}}
- +

The long value is MeshTender's public key — not your repeater's. If you see a guest-access warning after confirming a repeater, this is the fix: run the command above, then confirm again.

diff --git a/internal/web/security_test.go b/internal/web/security_test.go index 1e0e631..ac8dbc9 100644 --- a/internal/web/security_test.go +++ b/internal/web/security_test.go @@ -1,6 +1,7 @@ package web import ( + "bytes" "net/http" "net/http/httptest" "os" @@ -192,6 +193,94 @@ func TestTemplatesHeadingConventions(t *testing.T) { } } +// controlRe matches a form control's opening tag. +var controlRe = regexp.MustCompile(`(?is)<(input|select|textarea)\b([^>]*)>`) + +// namedRe matches the attributes that give a control an accessible name directly. +var namedRe = regexp.MustCompile(`(?i)aria-label\s*=|aria-labelledby\s*=|\btitle\s*=`) + +// skipTypes are input types with no user-visible value to name. +var skipTypes = map[string]bool{ + "hidden": true, "submit": true, "button": true, "image": true, "reset": true, +} + +// TestTemplatesFormControlsAreLabeled enforces that every form control has an +// accessible name. Without one, a screen reader announces "edit text, blank" and the +// user has to guess from surrounding prose — assuming they find it at all. +// +// A control counts as named by any of: +// - aria-label / aria-labelledby / title on the control +// - a