calls: limit outside calls at once, per extension and in total
ci / check (push) Successful in 1m16s
ci / images (push) Successful in 22s

Owner's decision after the M11-T8 review: nothing capped how many calls a stolen password could
run at once. Settings → Security: calls.maxPerExtension (3) and calls.maxTotal (10), 0 = no
limit. Each sp-route-* counts the caller's extension (or whose forward it is: SP_LIMITEXT from
sp-sub-forward) with GROUP(spext) and every outside call with GROUP(spout); over a limit the
caller hears "all circuits are busy". 911 is never limited.

trunk-test.ts on a real Asterisk, limits 1 and 2: a 2nd call from 101's phone and a 3rd in total
are refused (with both 0 the same check fails). call-limits.test.ts covers the 0 combinations.
Also fixes the Security tab's hint: browser phones still work from anywhere.

Task: M11-T8
This commit is contained in:
iamdoubz committed 2026-10-20 13:14:20 -05:00
1 parent e4e50f1c0d
commit f6a9b9a4b1
25 files changed
+203 -9

No files matched your search

+3
View File
@@ -73,6 +73,9 @@ export const SettingsSchemas = {
'sms.webhookToken': z.string().regex(/^[A-Za-z0-9]{32}$/),
'sip.restrictPhonesToLocalNets': z.boolean().default(false),
'sip.extraAllowedNets': z.array(z.cidrv4()).default([]),
// Toll fraud (08 §1): outside calls going out at once, per extension and in total. 0 = no limit.
'calls.maxPerExtension': z.number().int().min(0).max(100).default(3),
'calls.maxTotal': z.number().int().min(0).max(1000).default(10),
'provisioning.lanOnly': z.boolean().default(false),
'provisioning.enabled': z.boolean().default(true),
'system.restartRequired': z.boolean().default(false),