provisioning: phones, /prov with Basic auth, rate limit and IP block
ci / check (push) Successful in 52s
ci / images (push) Successful in 1m44s

/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
This commit is contained in:
iamdoubz committed 2026-10-19 13:38:18 -05:00
1 parent dc79120de0
commit fa63908261
22 files changed
+1266 -43

No files matched your search

+15
View File
@@ -46,6 +46,21 @@ Rules:
- On success: update `last_provisioned_at`, `last_provisioned_ip`. Set `Cache-Control: no-store`.
- Never serve over plain HTTP. The reverse proxy only listens on 443. (Old phones that can't do modern TLS are not supported.)
As built (M10-T1), `routes/provisioning.ts` + `provisioning/limiter.ts`:
- A request **without** an `Authorization` header gets the 401 but isn't a failure: phones ask without
credentials first and retry after the challenge. Failures are unknown MACs (or a file for another
vendor) and wrong credentials; 10 within an hour block the IP for an hour (429).
- The 20 requests / 10 min limit applies to clients **outside** `network.localNets`: an office's
phones rebooting together behind one address would pass it in a minute. Failures count for all.
- The Basic auth user name is the 12-hex MAC (either case); it can't carry colons (Basic auth splits
at the first one). The Yealink common file `y0000000000xx.cfg` is served without auth (it's empty).
- Unrecognized file names (phones ask for several) are a plain 404 and not a failure.
- Desk phones are provisioned for UDP on `sip.udpPort`. Templates in M10-T1 hold the account,
voicemail, pickup codes and the provisioning settings; BLF keys, time zone and the phonebook come
with M10-T2. `scripts/e2e/m10-t1.mjs` registers a baresip phone with only the account from the
served file.
- Vendors offered: Yealink, Grandstream, generic (Polycom stays a stretch goal).
## 3. Templates
The key names below come from vendor documentation. Each one is marked