Release Notes — September 2026
Spans 2026-09-15 → 2026-10-05. 26 commits across five themes: sign-in (no more logout an hour after login), RBAC enforcement (module permissions and record access applied consistently, record-team access levels), scheduling and tasks (free/busy, schedule-aware task creation, task type durations, new filters), calendar coverage (admins see who has connected Google Calendar), and fixes across forms, email, contacts, dashboards and Customer 360.
Three tenant migrations ship in this period. Run them on every environment with:
npx ts-node apps/api/src/scripts/run-tenant-migrations.ts
| Migration | Adds |
|---|---|
| 085 | Gives every user who has dashboards the default tabs, and fills default-named tabs that are still completely empty. Customised tabs are untouched. |
| 086 | Adds the automation (Workflows) permission: full access for roles at level ≥ 90 or named Admin / Super Admin, explicitly off for every other role so it can be toggled in the Roles screen. |
| 087 | Seeds task type durations where blank — Call 30 min; Meeting, Demo, Onboarding 60 min — so schedule checks run. |
Migrations now run only from the command line; the admin-panel migration endpoints refuse.
Record-team members now get the access level they were added with. Existing memberships are read-only: collaborators who are outside the record owner's scope can still open and find the record, but can no longer edit it until someone switches them to Read/Write on the record's team panel.
Sign-in: No More Hourly Logouts
Users were being logged out an hour after signing in. The web app now uses one shared HTTP client with a single-flight token refresh: the 1-hour access token renews silently in the background, and the session lasts as long as the 7-day refresh token. A follow-up fixed screens that still loaded the old client.
See Logging In.
RBAC: Permissions and Record Access Enforced Everywhere
- Module permissions are now enforced on contacts, accounts, opportunities, projects, targets, gamification and workflows. Opportunities check the
opportunitiesmodule (notdeals). Admin settings writes and sensitive reads are admin-only. - Opening a record directly (
/leads/:id,/opportunities/:id, …) is checked against record access — users get a clear "no access" instead of seeing records outside their scope. - Record access now applies to lead, opportunity and task lists, Kanban, export and bulk select-all, and to global search and projects. Team scope uses team membership; reporting-line scope works in reports and dashboards; dashboard scope is clamped to the role.
- Record teams:
- Members can find records they collaborate on in list views.
- Each member has an access level — Read or Read/Write — enforced on edits.
- People added to a record team get a notification with the reason they were added, and the record's activity timeline shows it. The opportunity team panel gains role and access controls.
See Record Access and Roles & Permissions.
Scheduling, Tasks and Calendar
- Schedule-aware task creation — when you assign a task with a time to someone, the form shows their busy blocks, warns about clashes (without blocking the save), suggests free slots, and flags assignees who haven't connected a calendar.
- Internal free/busy across users powers this (
GET /scheduling/free-busy). - Task type durations — each task type has a default duration (editable in Task Settings) used when a task has no estimate.
- Record team prompt — assigning a task on a record to someone who can't see that record offers to add them to the record team (with role, access and reason) before saving.
- New task filters — Team, Department, and any active user as assignee.
- Calendar Connections — a new admin page shows which users have connected Google Calendar, who hasn't, and connections that haven't synced in 24 hours. Users without a connection see a Connect your Google Calendar banner on the Tasks page.
See Managing Tasks, Task Views, Scheduling, Task Settings and Calendar Connections.
Forms, Email, Contacts, Dashboards and Customer 360
- Forms — hidden-field defaults are applied to API submissions; booking pages honour field visibility and width; public form, landing and booking pages always render in light mode.
- Email — system emails no longer fail with "Greeting never received" (port 465 is treated as TLS, longer timeouts, quotes stripped from env values).
- Contacts — the main email, phone and mobile are derived from the contact's email and phone lists; save errors show the server's message.
- Dashboards — every user gets the default dashboard widgets.
- Imports — CSV files are parsed with a faster parser (large uploads no longer time out; leading zeros are kept). Opportunities imported straight into Won/Lost get their won/lost dates stamped.
- Customer 360 — account engagement counts activity on the account, its opportunities and its contacts, ignoring bookkeeping events; Recalculate reports failures.
- Smaller fixes — the convert modal shows the lead's owner; Opportunity Settings saves a pipeline rename on blur/Enter; the subscription product picker searches the whole catalogue; the record team prompt scrolls into view; the service worker no longer intercepts Google / Gmail / Xero OAuth callbacks.
Since the CSV parser change, legacy .xls (Excel 97–2003) uploads are not read correctly. Save the file as .xlsx or .csv before importing.
Index of changes
a6ab6b9parse CSV with fast-csv to stop upload 504s2b2cac8contacts: derive email/phone/mobile from emails[]/phones[]3e8178fopportunity settings: save pipeline rename on blur/Enter3766f8econtacts: show the server's error message on savebc515ddauth: stop logging users out an hour after login22d8c6dauth: repoint dynamic imports missed by the http client consolidationd1c81f8forms: apply hidden-field defaults to API submissions996e216leads: show the lead's owner in the convert modal3dc5cd4customer 360: meaningful account score recalculation93f7645migration 085 — default dashboard widgets; stamp won/lost on import64dafd8migration 086 — enforce module permissions and record access across modules232da87email: stop "Greeting never received"b7747f1forms: honour field visibility and width on booking pages2fdd86eforms: public pages always in light modeea67b0crbac: record team members find records in list views4a382abscheduling: internal free/busy across usersff9d1dbcalendar sync: connection coverage for adminsb02b6d7accounts: subscription product picker search7cb3755rbac: enforce record team access_level on writesc9d3ef8tasks: schedule-aware task creation and record team prompt4fd0869record team: notify collaborators when added, with a reason24876f1calendar sync: coverage page + connect promptabdbb1emigration 087 — task type durationse775ddatasks: scroll the record team prompt into view9e60dedtasks: filter by team, department and any assignee6e36926web: keep the service worker from intercepting /api OAuth callbacks