Under a full parallel run the event-log and webhook inserts took longer than the sleep, so
2-3 tests failed on most runs (also before M11-T8). They poll for the rows now.
Task: M11-T8
The 08 §1 threat table checked line by line against the code, plus a review by a separate agent
that hadn't written it. Findings were reproduced with a failing test before each fix:
- Critical: "011…,4" turned the route's Goto into Goto(sp-route-…,011…,4,1), starting past the
class check, so any extension could call abroad. FILTER on the dialed number (also stops "&"
adding a Dial target). trunk-test.ts proves it.
- High: -web endpoints (desk phone's password, any transport) skipped the phone ACL; now
127.0.0.1 only when it's on. call-test.ts: UDP refused, WebSocket from 127.0.0.1 registers.
- IVR direct dial no longer reaches paging groups or parked calls (sp-ivr-direct).
- Trunks identify_by = ip: a From of trunk-<id> from anywhere no longer rings phones.
- .dockerignore is an allowlist, so the public source archive can't pick up stray files.
- CSRF check on the matched route (/%61pi/… got around it); Linphone tokens masked in logs;
/api/live checks Origin and re-checks the session; *45/** filter digits; pg_dump password in
the environment; more webhook ranges blocked.
The review and what's left for the owner are in 08 §6.
Task: M11-T8
API tokens (Settings -> API tokens): Authorization: Bearer sp_<40 base62>,
stored as sha256, shown once. A token acts as its admin with their current
role and stops when they're disabled; Bearer requests skip the CSRF header
and never fall back to the cookie. A token can't manage tokens.
Webhooks (Settings -> Webhooks): call.started/answered/ended,
voicemail.new, emergency.call, trunk/extension registration changes, from
the live state; queued per webhook, sent every 10 s with
X-SelfPhoneNG-Signature (HMAC of timestamp.body), retried after 1 m, 5 m,
30 m, 2 h, 12 h, then failed. Private/loopback targets are refused in the
connection's own DNS lookup (no rebinding), unless allowed. Send test and
a delivery log per webhook.
The e2e found voicemail.new missing for mailboxes without a user: the
voicemail scan now queues it for every mailbox. vmpin.test.ts gets 180 s:
Git Bash forks make it ~85 s on Windows (the earlier flaky gate run).
Task: M11-T5