diff --git a/services/security-dashboard.sh b/services/security-dashboard.sh
index 1e207bb..564e8e7 100644
--- a/services/security-dashboard.sh
+++ b/services/security-dashboard.sh
@@ -209,14 +209,8 @@ not in Docker — it needs to call \`cscli\` and read Asterisk's log directly.
- **Unwhitelist + Ban** does that *and* immediately bans (24h) every IP
CrowdSec has ever recorded for that ASN, for accidental-whitelist cases
where you don't want to wait for it to misbehave again.
-- **PSTN Trunk** — an "Internal SIP messaging" card at the top is always
- available, whether or not a PSTN trunk has ever been installed: a
- checkbox per known extension (parsed from \`pjsip.conf\`) for
- Asterisk's native SIP texting, independent of PSTN calling entirely (no
- cost, no carrier, no DID, no dependency on \`services/pstn-trunk.sh\`
- having been run — see its "Known gap" note on messaging for what this
- flag does and doesn't do yet at the Asterisk level). Right below it, a
- **Groups** card (also always available) lets you name a set of
+- **PSTN Trunk** — a **Groups** card at the top (always available, whether
+ or not a PSTN trunk has ever been installed) lets you name a set of
extensions and bulk-enable/disable messaging for all of them at once —
a management convenience only, not a runtime concept: applying an action
just writes the same per-extension \`pstn-permissions.conf\` key each
@@ -235,7 +229,11 @@ not in Docker — it needs to call \`cscli\` and read Asterisk's log directly.
which the dialplan reads fresh on every call. The spend-cap kill-switch
and international-calling allow-list are deliberately **not** managed
here — CLI-only, via \`sudo ./setup.sh pstn-trunk\` — since both are more
- security-sensitive than what this tab already exposes.
+ security-sensitive than what this tab already exposes. An "Internal SIP
+ messaging" card at the **bottom** of the tab (a checkbox chip per known
+ extension, independent of PSTN calling entirely — no cost, no carrier, no
+ DID, no dependency on a PSTN trunk being installed) is always available
+ regardless of any of the above.
- **Asterisk Admin** — an embedded, lazy-loaded iframe of the real Asterisk
web admin (only fetched the first time you open the tab), plus an
"open in a new tab" fallback link that's always there regardless. Only
@@ -1506,8 +1504,8 @@ INDEX_HTML = """
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: #e6e6e6; }
th.sortable .arrow { opacity: 0.5; font-size: 0.75em; margin-left: 0.25em; }
- .filter-row th { padding-top: 0; padding-bottom: 0.5rem; font-weight: normal; }
- .filter-row input { width: 100%; box-sizing: border-box; background: #0f1115; border: 1px solid #2a2e38; color: #e6e6e6; border-radius: 4px; padding: 0.25rem 0.4rem; font-size: 0.8rem; }
+ .chip-row { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; }
+ .chip-row label { white-space: nowrap; font-size: 0.85rem; color: #9aa4b2; }
.sev-Error { color: #ff6b6b; }
.sev-Warning { color: #f5b342; }
.sev-Informational { color: #7fbf7f; }
@@ -1535,16 +1533,13 @@ INDEX_HTML = """
Recent Asterisk SIP security events, newest first. Errors/warnings are real auth failures; informational lines are normal registration traffic.
-
-
Time
Event
Account
Remote
Severity
-
-
-
-
-
-
-
-
+
+
Time
+
Event
+
Account
+
Remote
+
Severity
+
@@ -1572,14 +1567,6 @@ INDEX_HTML = """
-
-
Internal SIP messaging
-
- Asterisk's native SIP texting between extensions — no carrier SMS, no PSTN, no cost, and no dependency on a PSTN trunk being installed at all. Independent of the calling permissions below. Enforced live by a dedicated dialplan context (see services/asterisk-digital-ocean.sh's README) — install/rerun that service to pick up the dialplan wiring if this box predates it.
-
-
Ext
Name
Enabled
-
-
Groups
@@ -1590,12 +1577,16 @@ INDEX_HTML = """
-
Group
Members
+
+
Group
+
Members
+
+
PSTN trunk not installed
-
No PSTN trunk dialplan was found on this box — sudo ./setup.sh pstn-trunk hasn't been run (or its config was removed). The calling permissions/caps/personal-numbers below aren't enforced yet; install it first to use them. Internal SIP messaging above works independently of this.
+
No PSTN trunk dialplan was found on this box — sudo ./setup.sh pstn-trunk hasn't been run (or its config was removed). The calling permissions/caps/personal-numbers below aren't enforced yet; install it first to use them. Internal SIP messaging (bottom of this tab) works independently of this.
@@ -1619,7 +1610,14 @@ INDEX_HTML = """
Messaging — Asterisk's native internal SIP texting (no carrier SMS, no PSTN, no cost), independent of the calling tier. Enforced live by a dedicated dialplan context — see services/asterisk-digital-ocean.sh's README for how, and its caveat on the sender-extraction logic still needing real-traffic confirmation.
-
Ext
Name
Tier
Approved numbers (restricted only)
Messaging
+
+
Ext
+
Name
+
Tier
+
Approved numbers (restricted only)
+
Messaging
+
+
@@ -1632,10 +1630,23 @@ INDEX_HTML = """
-
DID
Owner
+
+
DID
+
Owner
+
+
+
+
Internal SIP messaging
+
+ Asterisk's native SIP texting between extensions — no carrier SMS, no PSTN, no cost, and no dependency on a PSTN trunk being installed at all. Independent of the calling permissions above. Enforced live by a dedicated dialplan context (see services/asterisk-digital-ocean.sh's README) — install/rerun that service to pick up the dialplan wiring if this box predates it.
+