The previous commit gave each extension two independent lists — numbers it
may dial and caller IDs that may reach it. That was more than asked for: the
whitelist is one set of numbers per extension, and what varies is which
direction(s) it constrains.
pstn-permissions.conf now has an authored pair, 'restrict' and
'allowed_numbers', where restrict is one of:
none no PSTN at all open unrestricted both ways
out may only dial the list in may only be called by the list
both the list applies both ways
tier_out/allowed_out/tier_in/allowed_in are now derived from that pair rather
than authored directly, and remain what the dialplan reads — so the dialplan
is unchanged from the previous commit and stays tested. 'tier' still mirrors
tier_out for rollback. Keeping the compiled keys means the file has one place
a human edits and one place Asterisk reads, which is the same authored/
compiled split a named-number-list feature would need later.
The migration handles both prior shapes: a genuinely legacy single-tier file
(full becomes open, restricted becomes both — reproducing what the old
dialplan did), and the short-lived two-list shape from the previous commit
(inferred back to a mode, preferring the more restrictive reading). Still
idempotent, still backs up first.
The dashboard drops from two dropdowns and two fields to one of each, with
the whitelist greyed out for the modes that don't use one, and the PSTN
column sorting by how much reach a mode grants rather than alphabetically.
Verified: migration from both shapes; the dashboard round-trip writing
restrict=in with the list compiled to allowed_in only; and the group-ring
helper across all four modes — Restrict inbound rings only for a whitelisted
caller, Restrict outbound rings for everyone, Restrict both rings only for
its own list, No PSTN never rings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NAddJGE1G6eGaPzmScG5Vh