Multiple DIDs can now share one trunk/account, each assigned to a specific
extension - additive to the existing shared trunk DID/ring-group, which
keeps working unchanged for everyone regardless of what's assigned here.
- New pstn-personal-dids.conf (DID -> owner extension), read live by the
dialplan for inbound routing: a call to a personal DID routes straight
to its owner, checked against the owner's own tier/approved-numbers, no
ring-group fallback since it's that extension's own line.
- New personal_did= field per extension in pstn-permissions.conf: the
outbound Caller-ID override, used by pstn_check_busy (the shared exit
point for both domestic and international dialing) instead of the
shared trunk DID when the calling extension has one assigned.
- Both files kept in sync automatically by one write path - CLI prompt at
install/update, or a new "Personal numbers" card in the Security
Dashboard's PSTN Trunk tab - rather than requiring hand-editing both
consistently. Reassigning a DID or giving an extension a new one cleanly
drops the stale side of the old mapping.
- Assigning a DID to an internal-tier extension is accepted but warned
about (won't ring anyone until also granted full/restricted tier),
matching this repo's permissive-with-warnings style rather than
blocking the action outright.
Also fixed a real bug found while building this: security-dashboard.sh's
write_permission() did cp.remove_section(ext) whenever tier was set to
"internal", silently discarding any messaging=yes or personal_did=
already set on that extension. Now removes only the tier/allowed_numbers
keys, dropping the section only once nothing else remains in it.
Separately, de-anchored pstn-trunk.sh's install prompts from VoIP.ms as
the implicit default (provider name default, server-hostname example
wording, rate-prompt wording) now that Anveo Direct is an equally
confirmed, tested provider option.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ho9mZgAkVpdz7S5wJkg8Nf