The server checks itself (public IP, DNS, local networks, phone ACL, SIP transports, free audio
ports) and says how to fix each problem. A quick or complete network test asks the probe
(apps/probe, own image) to test this server from outside: HTTP/HTTPS, SIP over UDP/TCP/TLS, the
browser phone's /ws, sampled audio ports. The probe only tests the address that asks.
The audio port range comes from RTP_PORT_START/END (default 10000-20000).
/api/devices CRUD (MAC in any format → 12 lowercase hex; a 20-char
provisioning password, stored encrypted and shown to admins, who type
it into the phone) and GET /:id/config-preview with passwords masked.
GET /prov/... per 07 §2: <mac>.cfg (Yealink), cfg<mac>.xml
(Grandstream), the empty Yealink common file. Basic auth with the MAC
and the device's password (timing-safe), 404 for unknown MACs or the
other vendor's file, 403 outside the local nets when LAN-only, 404 when
provisioning is off, Cache-Control no-store, last provisioned time and
IP recorded. Limits: 20 requests / 10 min per IP outside the local nets
(an office's phones rebooting together would pass it), and 10 failures
block the IP for an hour. A first request without credentials isn't a
failure: phones ask that way and retry after the 401.
Templates (pure functions of a ProvisionContext) hold the account,
voicemail, pickup codes and the provisioning settings; BLF, time zone
and phonebook come with M10-T2.
Web: Phones page (table, drawer with what to type into the phone,
config preview; manual settings for generic phones). e2e m10-t1: phone
added in the UI, 401 then the file, and a baresip phone registers with
only the account from it.
Also: the loadSnapshot test made its database inside the test (20 s);
under a full parallel run that timed out now and then. It now does it
in a hook like the others.
Task: M10-T1
res_parking was configured in M0 (700, slots 701-720, slot hints); this
makes parked calls visible. ParkingTracker loads ParkedCalls and follows
ParkedCall/UnParkedCall/ParkedCallTimeOut/ParkedCallGiveUp; everyone
gets parked.updated/parked.removed. Who parked comes from
ParkerDialString.
A blind transfer to 700 parks without running Park() in the dialplan,
so the live call's "parked" state now comes from those events by
ParkeeLinkedid; the picking-up phone runs ParkedCall() while talking,
which no longer counts as parked.
Web: "Parked calls" on the Dashboard and on Home, where "Pick up 701"
calls the slot like Call back (softphone, or the desk phone first).
CDR fixture park-pickup (recorded: 101 parks an inbound call, 103 picks
it up); the call counts as answered by 101 with 103 in rang. e2e m8-t2
with real phones: park by blind transfer, hint InUse, both lists, pick
up from Home, a second park on 702 (findslot = next) picked up by
dialing it from another phone. Specs 01/04/05 note what was verified.
Task: M8-T2
services/cdr.ts stores every AMI Cdr event in cdr and, 5 s after a
call's last event, builds its calls row (direction, status, from, to,
DID, answered by, talk time) and call_extensions (caller, rang,
answered) per 04 §5.4; linkedids without a calls row are caught up on
AMI connect. Aggregation is idempotent.
test/asterisk/cdr-record.ts records 8 scenarios with our config, the
fake voip.ms (now shared in provider.ts) and baresip phones; each has a
fixture and a test with the expected calls row. Queue abandon and park
come with M8.
Found while recording: Asterisk 24's Cdr event has no LinkedID unless
cdr_manager maps it, its times carry no zone (now usegmtime), and the
mappings read CDR variables, so the dialplan sets CDR(SP_DID) and
CDR(SP_DIRECTION) next to the channel variables. The Asterisk image
needs a rebuild for the cdr_manager.conf change.
Task: M7-T1
Migration 0000 enables citext; 0001 creates all 39 tables. DB tests use a
throwaway database per file (TEST_DATABASE_URL, derived from .env in dev,
a postgres service in CI). Decision 0002: pg driver and @fastify/cookie.
Task: M1-T1
Adds stub configs and noloads so a clean boot logs no ERROR lines,
ships stock indications.conf, seeds default MOH from the entrypoint.
Spec 01 synced with the real files.
Task: M0-T5