Commit Graph
11 Commits
Author SHA1 Message Date
iamdoubz 19610777a4 auth: directory leavers check, dashboard warning, Samba AD check (S5)
ci / check (push) Successful in 1m22s
ci / images (push) Successful in 22s
Spec 12 S5: job directoryCheck (hourly) looks up every active user with a directory account;
one deleted, disabled there or no longer matched by the user filter is disabled here, sessions
ended. Nothing changes when the directory is unreachable or a run would disable most people;
the last admin with a password is kept; nobody is re-enabled. Dashboard warning
directory_check (system.directoryWarning). The by-id search is a filter object: ldapts string
filters send bytes >= 0x80 as UTF-8, so AD's objectGUID never matched. Live test against a
Samba 4 AD DC: nested-group admin, the disabled bit, objectGUID, a deleted user disabled.
2026-10-26 07:47:12 -05:00
iamdoubz 73963ee3a3 auth: OpenID session check, live Keycloak test, sign-in guide (S3)
Spec 12 S3: job oidcCheck refreshes every OpenID session at the provider every 15 minutes and
applies groups and role again; invalid_grant ends the session, an outage doesn't. A live test
makes a throwaway Keycloak realm and signs in through its login form (passed against 26.8.1).
NODE_EXTRA_CA_CERTS for a private CA. Admin guide: docs/admin-guide/sign-in.md.
2026-10-25 15:14:59 -05:00
iamdoubz e6a1373f36 contacts: calls on the Contrack timeline, summaries opt-in (C5)
ci / check (push) Successful in 1m7s
ci / images (push) Successful in 20s
Spec 11 §4.4: the contrackLog job puts each connected person's calls with their Contrack
contacts on that contact's timeline once (contrack_call_log, migration 0011), from when they
connected. With summaries on (My settings → Contacts, needs call summaries), the escaped summary
and action items go in, and the first action item becomes a follow-up due the next day. Waits up
to 30 min for a summary; Contrack down is retried, refusals noted once. Tested against a fake and
a real Contrack 2.0.2.
2026-10-23 15:59:53 -05:00
iamdoubz b05361e840 contacts: caller names on desk phones while they ring (C4)
ci / check (push) Successful in 1m2s
ci / images (push) Successful in 22s
Spec 11 §6.1: sp-sub-dial-user asks /api/internal/caller-name (func_curl, 2 s at most; this
machine only, with an APP_SECRET-derived key, not logged) for the ringing user's name for the
caller, and sets it on each ringing leg (pre-dial handler, CONNECTEDLINE), never on the call, so
forwards and other members don't see someone else's contacts. Ring group/queue/number prefixes
kept. Contrack lookups never wait (cache, contactsWarm every 5 min). Proven on real Asterisk
with baresip: apps/api/test/asterisk/cnam-test.ts.
2026-10-23 15:45:36 -05:00
iamdoubz a754974a90 contacts: my book, the company book, vCard/CSV import, sharing with Accept/Deny
C1 (spec 11): /api/me/contacts and /api/contacts (admin), our own vCard 2.1/3.0/4.0 and CSV
readers with a preview, contact_shares (migration 0009) for offers, and contact names in call
history, voicemail, Home, the softphone and the call report email. Admin → Contacts.
2026-10-23 14:53:21 -05:00
iamdoubz 4c006f2388 me: call report email (hourly, daily, weekly), with call summaries
ci / check (push) Successful in 1m14s
ci / images (push) Successful in 40s
ci / check (pull_request) Successful in 59s
ci / images (pull_request) Successful in 4s
My settings → Call report: each user's calls of the last hour, day (at a time) or week (on a
day at a time), company time zone: numbers, status, talk time, recorded, and optionally each
recorded call's summary (10 §3). No calls, no email. Job callReports every minute, 5 min after
the period ends; periods computed in PostgreSQL (DST-safe). Migration 0008_call_reports.
2026-10-23 13:55:47 -05:00
iamdoubz 4d331fb70e ai: call transcripts (each side recorded, merged by time) and summaries; search on Recordings
ci / check (push) Successful in 1m22s
ci / images (push) Successful in 27s
2026-10-21 19:10:02 -05:00
iamdoubz 0ff0f9292b system: information panel and event log; about: download this build's source
ci / check (push) Successful in 1m20s
ci / images (push) Successful in 20s
System page laid out after 3CX's admin dashboard: a System information panel (version,
host name, company, public IP, LAN IPs, ports, telephony, restart needed, copy buttons,
how to restart) and an Event log panel (system_events, 90 days: trunk down/up, Asterisk
down/up, restart needed, config failed, 911, public IP changed, backups, disk) with Load
more and a CSV download.

About (/about, no sign-in, linked from the login page, My phone and System): AGPL-3.0
notice, credits, the repository link, and "Code v<version>", which downloads
selfphone.tar.gz: the api image now tars its own build context (no .env, data,
node_modules, build output or .git) before installing anything.

Task: M11-T7
2026-10-20 11:26:34 -05:00
iamdoubz a1525088dc admin: System page with restart steps, Record calls on the Calling tab
ci / check (push) Successful in 55s
ci / images (push) Successful in 23s
System shows whether telephony runs and needs a restart, and how to restart it
(docker compose restart asterisk); the dashboard's restart warning, the Network hint and
the public IP email point there. The user drawer's Calling tab gets the Record calls
select the spec listed (recordMode, already in the dialplan). e2e m11-system.mjs.

Task: M11-T7
2026-10-20 09:58:11 -05:00
iamdoubz 60846afddd integrations: webhooks and API tokens
ci / check (push) Successful in 54s
ci / images (push) Successful in 21s
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
2026-10-19 19:40:47 -05:00
iamdoubz d229ed2c45 jobs: public IP, trunk and disk watches, retention
ci / check (push) Successful in 57s
ci / images (push) Successful in 25s
apps/api/src/jobs.ts takes over the once-a-minute timer from index.ts
(no croner: every schedule in 04 §8 is whole minutes). Each job has a
running flag; errors are logged.

- Retention (at start and when the date changes, once AMI is up):
  recordings, voicemail past voicemail.retentionDays (VoicemailRemove, so
  Asterisk renumbers and updates MWI), expired sessions, webhook
  deliveries older than 30 days.
- publicIpWatch (every 5 min, Settings -> Network): a changed IP is saved,
  audited, applied (restart required) and emailed to admins.
- trunkWatch: a registering trunk rejected/unregistered for 5 minutes ->
  one email per outage.
- diskWatch (hourly): under 10% free -> one email a day.
- A failed daily backup emails admins too.

Settings gets a Network tab (public IP, Detect, re-check) and voicemail
retention on the Recording tab.

Task: M11-T4
2026-10-19 18:37:08 -05:00