Files
ubuntu-post-install/docs/pstn-sms-test-checklist.md
T
Claude d9f6190da1 Add PSTN/DID/SMS end-to-end test checklist
docs/pstn-calling-voipms-plan.md (design log) and
docs/anveo-direct-setup-guide.md (account + droplet setup) already cover
getting a trunk/DID/SMS working from scratch, but neither is a quick
top-to-bottom checklist for verifying an already-installed setup still
works — registration, trunk reachability, tiers, outbound/inbound calls
(shared DID and personal DID), the spend-cap kill-switch, international
calling, internal SIP messaging, and SMS inbound, in order, with what to
check when each step fails. Pulls known gotchas (Commit Changes required
after dashboard tier edits, mobile vs geographic DIDs for verification
codes, the SIP-based SMS path Anveo doesn't actually offer) from the
existing docs so they're not missed mid-test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn
2026-08-11 18:29:04 +00:00

9.8 KiB

PSTN + DID + SMS — end-to-end test checklist

For verifying an already-installed Asterisk + PSTN trunk + SMS setup (droplet or home/LAN) actually works, top to bottom. Not a setup guide — see docs/anveo-direct-setup-guide.md for account/droplet setup from scratch, and docs/pstn-calling-voipms-plan.md for the design/architecture background. This doc assumes both are already done and just walks through proving it all still works, in order, with what to check when a step fails.

Run through this after any of: first go-live, a provider/DID change, an Asterisk or PSTN trunk reinstall, or just periodically to catch drift (a provider-side change, an expired international allow-list, a forgotten kill-switch trip).

0. Before you start

Confirm which layout this box uses — commands below need the right container name and directory:

docker ps --format '{{.Names}}' | grep -i easy-asterisk
# easy-asterisk        -> ~/docker/asterisk
# easy-asterisk-do     -> ~/docker/asterisk-digital-ocean (pre-merge droplet)

Set these once and reuse them in every command below:

CONTAINER=easy-asterisk        # or easy-asterisk-do
EA_DIR=~/docker/asterisk        # or ~/docker/asterisk-digital-ocean

Check the three services this checklist covers are actually installed:

sudo ./setup.sh --list | grep -E "asterisk|pstn-trunk|sms-inbound|security-dashboard"

Read your box's own current settings before testing — this file has your real DID, tiers reference, ring-group, and rate, regenerated on every pstn-trunk install/update:

cat $EA_DIR/README-pstn-trunk.md

1. Registration sanity check

Every extension you're about to test with needs to actually be registered before anything else will work.

docker exec -it $CONTAINER asterisk -rx "pjsip show endpoints"

Each extension you plan to test should show Avail (registered), not Unavail. If a softphone shows registered in its own UI but Asterisk disagrees, the extension's transport (UDP vs TLS) is the usual culprit — check it via the Security Dashboard's Extensions tab button on that row before going further, not by re-entering credentials.

2. Trunk itself

docker exec -it $CONTAINER asterisk -rx "pjsip show endpoint pstn-trunk"

Look for Contact state, not just that the endpoint exists. An IP-authenticated trunk has no registration to show — what matters here is that Asterisk considers the endpoint reachable, and that the provider's own portal doesn't report the account balance at $0 or the DID unassigned.

3. Permission tiers — set before testing calls

Every extension starts at internal (no PSTN at all) until granted a tier. Before testing outbound/inbound, set at least one extension to full via the Security Dashboard's Extensions tab (or restricted with an approved number, if that's what you want to test). Press "Commit Changes (Restart Asterisk)" after — tier/permission edits are written to disk immediately but the dialplan has been observed not picking them up until a full container restart, not just a reload (see "Dashboard changes may need Commit Changes" in docs/anveo-direct-setup-guide.md). Skipping this step is the single most common reason a "correctly configured" test call still fails.

4. Outbound call test

From a full-tier extension's softphone, dial a real US number as 1 + area code + number (11 digits — the dialplan matches the full NANP pattern, not a bare 10-digit number).

Watch the live console while dialing:

docker exec -it $CONTAINER asterisk -rvvv

Expected: the call connects, and a line appears in the call log:

tail -f $EA_DIR/logs/pstn-trunk-calls.log

If it fails, check in this order (matches the actual bugs this system has hit — see the "Bugs hit and fixed" section of docs/anveo-direct-setup-guide.md):

  • restricted/internal tier dialing a number not on its approved list — expected to fail with a busy signal, not a bug.
  • Concurrency cap already hit — check pstn-limits.conf or the dashboard's displayed caps.
  • Kill-switch tripped (see §7 below) — every PSTN call, in or out, blocked regardless of tier.
  • dialplan show intercom and count digits by hand against what you dialed — a pattern-length mismatch has bitten this exact system before.

5. Inbound call test — shared DID / ring-group

From any outside phone, dial the trunk's main DID (shown in README-pstn-trunk.md). Every full/restricted-tier member of the configured ring-group should ring simultaneously for ~20 seconds unless a personal DID routes it elsewhere (see §6).

docker exec -it $CONTAINER asterisk -rx "dialplan show from-pstn-trunk"

If nothing rings: confirm the calling number's actual Caller-ID is reaching Asterisk correctly — a bare Hangup()/no ring with no ntfy denial alert either usually means the inbound context isn't loading at all (check asterisk -rx "dialplan show from-pstn-trunk" returns content, not "No such context"). A Busy(15) + ntfy denial alert means it loaded fine and the caller's number just isn't on a restricted-tier member's approved list — expected behavior, not a bug.

6. Inbound call test — personal DID

If you've assigned a personal DID to a specific extension (Security Dashboard → PSTN Trunk tab → Personal numbers), dial that number instead of the shared trunk DID. Only the owning extension (or every current member, if assigned to a Group) should ring — no ring-group fallback. Confirm the owner's outbound Caller-ID also shows this DID instead of the shared trunk DID when they place a call out.

7. Spend-cap kill-switch (only if enabled)

Don't trigger this for real — it force-hangs-up active calls and blocks all PSTN traffic until manually cleared. To confirm it's wired up without tripping it:

cat $EA_DIR/config/asterisk/pstn-trunk-killswitch.conf
systemctl status pstn-trunk-usage.timer 2>/dev/null || crontab -l | grep pstn-trunk-usage

The timer/cron entry should be active and recent (journalctl -u pstn-trunk-usage.service -n 20 shows it actually ran within the last minute). If you do want to confirm the block itself works, lower MAX_MONTHLY_SPEND temporarily via sudo ./setup.sh pstn-trunk (update mode) to something you've already exceeded, confirm calling is blocked with the priority=urgent ntfy alert, then re-run and clear it (this is CLI-only by design — not on the dashboard).

8. International calling (only if you've allowed any countries)

cat $EA_DIR/config/asterisk/pstn-intl-allowed.conf

Only full-tier extensions can dial these regardless of the allow-list. Dial 011 + country code + number. If an expiry was set, confirm the allow-list actually clears itself after that date (the periodic usage-alert script does this, not a separate cron job) — worth checking once near the expiry date rather than assuming.

9. Internal SIP messaging (no PSTN/SMS involved)

From one extension enabled for messaging=yes (Security Dashboard → Extensions tab → Messaging column) to another, send a native SIP message in Sipnetic (or whichever softphone). Should land instantly, no carrier involved. Check the log if it doesn't arrive:

tail -f $EA_DIR/logs/sip-messages.log

An extension with messaging=no should have its message silently denied (fails closed) — confirm this too, not just the success path.

10. SMS inbound test

Prerequisite: sudo ./setup.sh sms-inbound already run, and the Anveo portal's DID → SMS tab → "Forward to URL" configured with the exact string the installer printed (see docs/anveo-direct-setup-guide.md §8 if this hasn't been done yet).

Text the DID's number from any outside phone. Expected: it lands in Sipnetic's message thread for whichever extension/group owns that DID within a few seconds — not a push notification, a real message in the softphone's own thread.

journalctl -u sms-inbound -f

Shows sender, recipient, message length, and the AMI exchange — never the message body itself. If nothing arrives:

  • Confirm the DID is a mobile-class number if you're testing a 2FA/verification code specifically — geographic DIDs get silently rejected by many services before a message is ever sent (see the setup guide's "Pick the right kind of number" section).
  • Confirm short-code SMS is actually enabled on this specific DID (not every number in the pool has it by default).
  • Check pstn-personal-dids.conf/pstn-groups.conf actually has an entry for the DID you texted — an unowned DID has nowhere to route to.

Outbound SMS from this box isn't a working path yet (see the setup guide's "What about sending?" section) — don't test for it.

11. Dashboard cross-check

Open the Security Dashboard's Calls & Texts tab and confirm the calls and messages from the tests above actually show up there — this is reading the same log files tested above, so an empty tab after a successful test call usually means the dashboard's ASTERISK_LOG_DIR/log paths have drifted from where Asterisk is actually writing, not that logging is broken. Also check the Extensions tab shows correct live status (online/offline) for whichever device you tested with.

Quick reference — verification commands

docker exec -it $CONTAINER asterisk -rx "pjsip show endpoints"
docker exec -it $CONTAINER asterisk -rx "pjsip show endpoint pstn-trunk"
docker exec -it $CONTAINER asterisk -rx "dialplan show intercom"
docker exec -it $CONTAINER asterisk -rx "dialplan show from-pstn-trunk"
tail -f $EA_DIR/logs/pstn-trunk-calls.log
tail -f $EA_DIR/logs/sip-messages.log
journalctl -u sms-inbound -f          # SMS via Anveo's HTTP webhook — the path §10 actually tests
tail -f $EA_DIR/logs/pstn-sms.log     # SMS-over-SIP dialplan path — confirmed NOT offered by Anveo;
                                       # only relevant if a future provider delivers texts over SIP
journalctl -u pstn-trunk-usage.service -n 20