Changelog
A running list of what's new, changed, and fixed in Ascent. The most recent release is at the top. Entries are grouped under the version they shipped in, and new changes are added to the current version as they land.
Versions follow a date-based format, M.YYM.DDP — major (0 while
pre-release), a two-digit year plus month, and a two-digit day plus patch. For
example, 0.267.220 is the pre-release build for the July 2026 cycle, cut on
the 22nd as patch 0.
Looking for how a feature works? Browse the documentation by module in the left sidebar. This page only tracks what changed and when.
0.267.220 — 2026-07-22
Changed
- New version-numbering scheme. Ascent version numbers now follow a
date-based format,
M.YYM.DDP— major, a two-digit year plus month, and a two-digit day plus patch. This release,0.267.220, is the pre-release (0) build for the July 2026 (267) cycle, cut on the 22nd as patch 0 (220). Earlier releases used the sequential0.6.xpatch series.
0.6.242 — 2026-07-22
Security
- Dependency security patches. Updated a set of third-party packages to
clear all known security advisories reported by our dependency audit — seven
high-severity and four moderate-severity findings, now down to zero. The
affected libraries (
hono,@hono/node-server,fast-uri,js-yaml,shell-quote,brace-expansion,linkify-it, andmailparser) were each moved to a fixed release within the same major version, so there are no behavioral or API changes — this is a maintenance-only update with no impact on how Ascent works.
0.6.241 — 2026-07-22
Added
- Rate limiting on sign-in, password reset, and other sensitive endpoints.
Ascent now throttles repeated requests to protect your account from
password-guessing (brute-force / credential-stuffing) attacks. Sign-in,
multi-factor verification, and password-reset requests across the admin,
technician, and client-portal logins are limited per source and per account;
public webhook endpoints (Level RMM, inbound email, Stripe) and general API
traffic have their own generous ceilings. When a limit is hit, the request
gets a clear "too many requests" response with a
Retry-Afterhint telling the client when to try again, and the event is recorded in the audit log. Limits are configurable per environment and are off during automated tests. (#982)
0.6.239 — 2026-07-12
Added
- Clients now sign quotes when they accept them in the portal. When a Primary or Billing portal contact accepts a quote, they first draw or type a signature and click Accept & Sign Quote — the same way they already sign contracts. Ascent records who signed, along with the signing date, and shows the captured signature on the quote and on the quote PDF, giving you a clear proof-of-approval before billable work begins. A signature is now required to accept a quote from the portal. (#981)
Fixed
- @mentions in project comments now notify the people you mention. Typing
@namein a PSA → Projects → Discussion comment now sends the mentioned teammate a notification and drops a Mentioned item in their inbox that links straight to the project — the same way mentions already work in ticket replies. Previously these mentions were silently dropped and never reached anyone. (#969)
0.6.238 — 2026-07-03
Added
- The projects list now shows completion progress at a glance. Each row on the PSA → Projects list has a new Progress column with a bar and percentage showing how many of the project's tasks are Done (for example 75% · 3/4 done), so you can gauge where every project stands without opening it — the same at-a-glance progress your clients already see in the customer portal. Projects with no tasks show "No tasks". This completes the projects gap-analysis review. (#811)
0.6.237 — 2026-07-02
Added
-
Projects now support task dependencies and a timeline view. On a task's new Dependencies tab you can mark a task as depending on another task in the same project — for example Deploy depends on QA sign-off. A task shows as blocked while any task it depends on isn't Done, and the flag clears automatically once they're finished. Ascent refuses dependencies that don't make sense (a task on itself, across projects, duplicates, or anything that would create a loop). Tasks also gain an optional start date alongside their due date, and the project detail page has a new Timeline tab — a read-only Gantt-lite that lays each scheduled task out across the project's date range, coloured by status, with blocked tasks highlighted and undated tasks listed separately. (#962)
-
ITFlow migration can now import your file attachments. ITFlow keeps uploaded files on the server's filesystem, so they aren't in the database (or a backup) the importer reads. You can now bring them across by uploading an attachments archive — a
.zipor.tar.gzof your ITFlowuploads/folder — in the new optional field on the migration screen. Ascent matches each archived file to its record and re-hosts it: files attached to an asset, document, or quote are imported and linked, while contact-only or client-only files (which have no place to attach in Ascent) and any file missing from your archive are skipped and noted in the run log. The archive is stored encrypted, used only during the run, and removed when it finishes. Leave the field blank to skip attachments — everything else still imports. (#959) -
ITFlow migration can now import your password vault. When you migrate from ITFlow over a live database connection, you can now paste your ITFlow master encryption key (from ITFlow's Admin → Backup) to bring your credential/password vault across. Each entry's username, password, and one-time-password secret are decrypted with your key and re-encrypted under Ascent's own per-organization key — the master key is stored encrypted, used only during the run, and never shown or logged. Leave the field blank (or use a backup-file import) to skip the vault; entries that can't be decrypted are skipped and noted in the run log instead of failing the import. (#958)
-
"Catch me up" — a quick summary of what you missed. The notification bell now has a Catch me up button that shows an at-a-glance rollup of your unread notifications: the total, a breakdown by category (tickets, invoices, mentions, and so on), how long the oldest one has been waiting, and a preview of the most recent items — with a one-click Mark all read. It's handy when you come back to Ascent after being away and don't want to scroll the whole list. (#687)
-
Admins can now set org-wide notification defaults and enforce key alerts. A new Settings → Organization → Notification Policy page lets an Owner or Admin choose the default in-app/email behavior for each notification type — applied to any team member who hasn't customized that type — and mark a type Enforced so it applies to everyone (e.g. always email on SLA breach). Members see enforced types as locked in their own notification preferences and can't opt out. Defaults members haven't overridden simply follow the org's choice. (#942)
Fixed
- Project progress API now publishes its real shape. The
GET /api/projects/:projectId/progressendpoint's documented contract was stale — it described an obsolete set of fields the endpoint hasn't returned in a long time, so the generated API types fell back to an untyped payload and the project detail page had to cast the response by hand. The OpenAPI contract now matches exactly what the endpoint returns (task, time, cost, profitability, and ticket metrics), and the project detail page consumes that generated type directly. This is a type-safety and documentation fix only — the endpoint's actual response is unchanged. (#954)
0.6.236 — 2026-07-01
Added
-
Get desktop notifications even when Ascent isn't open. You can now turn on Browser Push Notifications from your profile's notification settings to receive OS-level desktop notifications on that device — so you're paged about a new ticket, an SLA breach, or a mention even when the Ascent tab is backgrounded or closed. It's per-browser and strictly opt-in (Ascent never prompts on its own; you enable it and your browser asks permission). Push follows your existing choices: a notification type you've muted in-app won't push, and your quiet-hours window holds non-urgent pushes just like it holds email. You can turn it off from the same toggle at any time, and the notification history shows whether each push was sent, skipped, or failed. Requires your Ascent operator to configure Web Push keys; the toggle simply doesn't appear when it isn't available. (#950)
-
ConnectWise migration can now bring your ticket attachments across. When you start a ConnectWise PSA migration you can tick Import ticket attachments to also download each ticket's documents from ConnectWise and re-host them in Ascent, attached to the matching ticket. It's off by default (downloading files is slower than the record import), and it's safe to run later — re-running only adds the files that aren't already in Ascent, without duplicating or re-downloading anything. Files on skipped tickets are skipped, and any empty download is noted in the run report. This completes the ConnectWise migration suite alongside the existing delta cut-over (changed-since) option. (#948)
-
See how each of your notifications was delivered. A new History button on the Notifications page opens a read-only Notification history that shows, per notification, whether each channel delivered it: in-app (always sent) and email (sent, failed, or skipped — with the reason, such as your quiet-hours window, an unconfigured mailer, or being held for your digest). It's the place to check when you expected an email about a notification and it never arrived. You can search the history by text and filter by type and date, and it only ever shows your own notifications. (#951)
0.6.235 — 2026-06-29
Added
-
Urgent items now stand out — and can chime. When a high- or urgent-priority inbox item arrives in real time (for example an SLA breach), Ascent now shows a distinct, longer-lived toast — red for Urgent, amber for High — instead of only bumping the badge silently. You can also turn on an optional Urgent alert sound under Settings → Profile → Notifications to hear a short chime for urgent items; it's off by default and saved per browser. Routine (normal/low) items are unchanged and stay quiet. (#946)
-
Clients can now see their projects in the portal. A new Projects section in the Client Portal lets clients follow the projects you're running for them — a read-only list and detail view showing each project's status, key dates, and task-completion progress. It's deliberately free of internal numbers: budgets, cost, profitability, rates, and the project-manager assignment are never shown, and client-facing progress is based on task completion only. Visibility follows the portal contact-type matrix (Primary, Billing, and Technical contacts see projects), and clients only ever see their own organization's projects. (#944)
-
You can now snooze your whole inbox at once. A new Snooze all button in the Inbox header snoozes every active item (unread and read) until a time you pick — 1 hour, 4 hours, or until tomorrow — clearing the active list for heads-down focus time. Snoozed items resurface automatically as unread when their time passes, and stay visible under the Snoozed filter in the meantime. This complements the existing per-item snooze and the Mark all read / Archive read bulk actions. (#687)
-
Notifications can now be sent to a generic webhook. Alongside Slack and Microsoft Teams, you can now point a notification channel at any HTTPS endpoint of your own — a custom service or an automation platform (n8n, Make, Zapier). Configure it under Settings → Integrations → Chat & Webhooks: paste the receiving URL, pick which notification types route to it, and Ascent POSTs a small, stable JSON payload (
source,title,body,type,url,entityType,entityId) for each matching event so your automation can react programmatically. The URL is stored encrypted and never shown again, internal/ loopback addresses are rejected, and delivery is best-effort so a failing webhook never blocks the action that triggered it. (#939) -
Notification emails can now be batched into a daily or weekly digest. From Settings → Profile → Notifications you can turn on an Email Digest and pick a daily or weekly cadence, the local send time, timezone, and (for weekly) the day of week. While it's on, your non-urgent notification emails are collected and delivered together in one rollup instead of one email per event — in-app notifications, the inbox, and Slack/Teams channels still update instantly, and urgent alerts (security alerts, on-call escalation pages) still email immediately. Turning the digest off sends any collected items in one final email and resumes per-event emails. (#937)
-
Projects now show their profitability. The project detail page has a new Profitability panel that puts invoiced revenue next to the cost of the time logged on the project and shows the profit and margin. Revenue is the total of the project's billable invoices (drafts, cancelled, and void invoices are excluded); cost is the same logged-time value the cost burn-down already reports. The panel appears whenever a project has any revenue or cost — no budget required — and a losing project is flagged red with an Unprofitable badge so it stands out at a glance. (#935)
-
Projects now alert you when they go over their cost budget. Projects already warned the manager and admins once when logged time crossed the hours budget; now they do the same when the logged cost (time valued at each entry's rate, falling back to the client's default rate) crosses the project's amount budget. The two budgets are tracked independently, so a project can alert on hours and on cost separately, and — like the hours alert — each one fires once per crossing and re-arms if spend later drops back under budget. You can toggle the new "Project Over Amount Budget" alert in your notification preferences. (#933)
-
ITFlow migration now imports your documents and knowledge base. Building on the CRM, assets, PSA and billing phases, the ITFlow importer now brings across your documentation — which in ITFlow doubles as the knowledge base, so runbooks, SOPs and client-facing articles all come over. Document content (rich text) is preserved; a document tied to a client links to that imported client, while a company-wide document imports with no client, and the "visible in client portal" setting carries over. A document whose client wasn't imported still comes across (flagged in the report) rather than being dropped, and re-running a migration updates existing documents instead of duplicating them. Two pieces are not yet imported because they don't live in the ITFlow database the importer reads — the encrypted password vault (its master key lives on the ITFlow server, not in the database) and file attachments (stored on the ITFlow server's filesystem); both are planned follow-ups and are called out in the migration screen and docs. (#783)
-
Hudu migration now imports your custom asset layouts and assets. The Hudu importer previously brought over companies, folders, articles, passwords, websites, and networks but stopped short of Hudu's flagship data — your custom asset types (Asset Layouts) and the records that fill them (Flexible Assets). It now imports both: each layout and its fields come over with the Hudu field type mapped to the matching Ascent field type (text, rich text, checkbox, website, list select, password, date, number, asset link, …), and every asset is linked to its layout and company with all of its field values carried across. Anything that can't be mapped cleanly — an unfamiliar field type, or a cross-asset link field (which comes over as text for now) — is noted in the run report rather than dropped. Re-running a migration updates existing layouts and assets instead of duplicating them. (#914)
-
Merge duplicate clients into one. When the same customer ends up as two separate client records — most often after importing from more than one system (for example a Hudu and an ITFlow migration that both create "Acme Corp") — you can now combine them. Open the client you want to keep, click Merge, pick the duplicate, and confirm: every contact, location, asset, ticket, project, quote, invoice, contract, document, credential, tag, and the rest is re-pointed to the surviving client, and the duplicate is deleted. Tags, access groups, and one-per-client settings are de-duplicated; the duplicate's migration links are updated to follow the survivor so re-running a migration won't recreate it. The merge is gated by a new clients.merge permission (Owners and Admins by default), is fully audit-logged, and refuses to touch the locked "Unknown (Email)" system record. Destructive and irreversible. (#911)
-
Hudu migration: rehost embedded article images & attachments. The Include attachments option on a Hudu migration now actually does something. When it's on, Ascent downloads the images and files embedded in your Hudu articles — anything hosted on your Hudu tenant — stores them in Ascent, and rewrites each article to point at the Ascent copy. Without it, embedded images keep pointing at Hudu and break the moment you shut your Hudu tenant down. The option is off by default, safe to re-run (already-rehosted files aren't fetched again), skips files over 50 MB, and notes any download that fails in the run report without stopping the migration. (#915)
-
Change or remove a client's Level RMM group mapping after setup. A client's Level RMM group binding used to be effectively permanent once set — the client detail page showed it as read-only and the setup wizard hid any already-mapped client. The client detail page now has a Level RMM card where you can re-point a client to a different Level group or Unlink it entirely. Moving a group that's already mapped to another client asks you to confirm first and then unlinks the other client, so a group never ends up mapped to two clients. The setup wizard no longer hides already-mapped clients (they're flagged instead) so you can intentionally re-assign during setup. Every link, relink, and unlink is audit-logged with the old and new group. (#912)
Changed
- Unmatched inbound email is now a locked "Unknown" system record with a triage flow. When an email arrives that can't be matched to a contact, a domain, or a configured default client, it still lands on the per-org Unknown (Email) client — but that record is now a clearly-marked, locked system record: it can't be renamed, edited, archived, or deleted, and it no longer appears in client lists, pickers, customer counts, or reports, so it can never be mistaken for (or billed as) a real customer. To work these tickets, open the new Needs triage filter on the Tickets page (or the link shown on the Unknown client), then use Reassign to client on a ticket to move it onto the right client — optionally adding the original sender as a contact in one step. Existing "Unknown (Email)" clients are migrated to the locked system record automatically. (#907)
Fixed
- Hudu migration no longer silently drops company, folder, article, password, website, and network fields. A company's country, website, and (recognized) company type now import to the matching client fields. Anything Ascent has no place for yet — a company's parent company, a folder's description/icon and its company scoping, an article's permalink, a password's type, and a website's DNS/WHOIS monitoring toggles — is now recorded as an unmapped entry in the run report for that record instead of vanishing, so you can see exactly what wasn't carried over. (#916)
0.6.234 — 2026-06-28
Changed
-
Reorganized Settings and Admin into a clearer, consistent layout. All org configuration now lives in one Settings area with a categorized left-hand menu — Organization, Users & Access, Ticketing, Security & API, Email, AI, and Assets — so related options sit together instead of being scattered between two different menus. The Admin menu is now reserved for operational tools (Audit Logs, AI Chat Logs, Integrations, and Migrations). Pages that previously lived in inconsistent places were moved to where they belong: Roles & Permissions, Client Portal, and Time Off now sit under Settings ▸ Users & Access; Customer Feedback under Settings ▸ Ticketing; Email Templates and the Email Queue under Settings ▸ Email; and Holidays & Closures under Settings ▸ Organization. Integration setup pages and data Migrations are grouped under Admin ▸ Integrations and Admin ▸ Migrations. Existing bookmarks to the old locations should be updated to the new menu paths.
-
The organization default SLA is now a first-class "Default" policy. The org-wide default SLA targets used to live in a separate place and a different format than your named SLA policies. They now appear as a single, pinned Default policy in Settings → Ticketing → SLA → Policies, edited the same way as any other policy — one consistent place and format for every SLA target. The Default policy is always active and can't be deleted (it's the fallback applied when no contract or named policy supplies a target). This is purely an organization/clarity change: no ticket's SLA due dates change, and you don't need to do anything — your existing defaults carry over automatically.
0.6.233 — 2026-06-28
Fixed
- ITFlow migration runs now show live status, progress and errors. Starting
an import previously gave almost no feedback — you had to refresh the page to
see whether anything happened, and there was no way to tell what was skipped
or why a run failed. The migration page now:
- auto-updates while a run is in progress (no manual refresh) and stops polling once the run finishes, fails or is cancelled, with a live indicator while it's tracked;
- shows a copyable run reference id that matches the background worker's logs, so a run can be correlated for support;
- shows a progress bar and live counts (pulled / loaded / skipped / failed) per section of data, plus start time, finish time and elapsed duration;
- surfaces a failure's error immediately, and adds a View details breakdown of every skipped, unmapped or errored record with the reason for each. Connection passwords and the uploaded backup are never displayed.
0.6.232 — 2026-06-28
Added
- One-switch Free-Plan deployment profile for the AWS stack. A new
DeploymentTierparameter (free|paid, defaultpaid) selects Free-Plan-safe RDS values (backup retention0, Performance Insights off, single-AZ) in one place instead of hand-editing several parameters. The default stays production-correct (paid: retention7, Performance Insights on), so a normal deploy is never silently degraded — you opt into the limits explicitly, and switch back topaidonce the account is upgraded. Per-parameter overrides (DBBackupRetentionDays,DBPerformanceInsights,DBMultiAZ) still win when set. - Read-only deploy preflight checks. A new
preflight.shvalidates the limits that most commonly cause a slow first-deploy rollback before the stack is created — the PostgreSQL engine version is offered in the region, there's Elastic IP quota headroom for the NAT gateway, and the RDS instance class is orderable — and fails fast with a clear summary.deploy-infra.shruns it automatically (bypass withSKIP_PREFLIGHT=true); run it standalone before a Git-sync deploy.
Fixed
- AWS CloudFormation redeploys are now self-healing. Two things could make a
redeploy of the self-hosted AWS stack fail or silently do nothing, and both
are fixed:
- The SES domain identity was the last fixed-name resource that could
collide on a redeploy (it is the domain, so it can't be auto-named like the
bucket and secrets). A new
ManageSesIdentityparameter (defaulttrue) lets you deploy withfalseto adopt an identity the account already owns instead of failing with already exists — no manual identity deletion required. - A stack left in
ROLLBACK_COMPLETE(or another dead state) cannot be updated, so a merged fix would redeploy as a no-op.deploy-infra.shnow runs a newpreflight-stack.shfirst, which deletes a stack only when it is in a known-dead state and waits for the delete before deploying. Active and in-progress stacks are left untouched, and theRetain/Snapshotresources (uploads bucket, RDS) survive the cleanup by design.
- The SES domain identity was the last fixed-name resource that could
collide on a redeploy (it is the domain, so it can't be auto-named like the
bucket and secrets). A new
0.6.231 — 2026-06-28
Fixed
- ITFlow migrations from an uploaded backup file now run successfully.
Importing from an uploaded ITFlow
.sql/.sql.gzbackup failed immediately: the upload was saved by the web server, but the background worker that runs the import couldn't see it, so the run crashed within milliseconds and imported nothing — with no error surfaced on the run. The uploaded backup is now stored (still encrypted) in the database, which both the server and the worker can always read, so backup imports work in every deployment without any extra shared storage. If a dump from an older run ever can't be reached, the run now fails with a clear, actionable message on the run itself instead of an opaque file-not-found error. Live-MySQL ITFlow migrations are unchanged.
0.6.230 — 2026-06-28
Fixed
- Client-portal SSO sign-in now completes when two-factor (MFA) is enabled. Portal users who signed in with SSO and had MFA enabled were bounced back to the plain login form instead of being shown the verification step, leaving them unable to finish logging in. The portal login page now reads the MFA challenge handed back by SSO and shows the right prompt — landing WebAuthn / passkey users directly on the security-key prompt, authenticator-app users on the code prompt, and offering a chooser (plus recovery codes) when more than one method is available. The short-lived MFA token is also stripped from the address bar once the challenge appears. Password (non-SSO) portal login is unchanged. (This brings the portal in line with the same fix already shipped for the technician dashboard.)
0.6.229 — 2026-06-28
Fixed
- Hudu migration no longer aborts when Networks isn't available. Some Hudu tenants return an HTTP 400 (not a 404) on the optional Networks / IP Address Manager resource when that module isn't provisioned or is excluded by the API plan. The importer now treats a 400 on Networks the same as a 404 — it skips Networks, notes it in the run report, and lets the rest of the migration complete. A 4xx on any required entity (Companies, Folders, Articles, Asset Passwords, Websites) still fails the run, so there's no silent data loss.
0.6.228 — 2026-06-28
Fixed
- Slack & Teams and Google Workspace now appear in the Integrations catalog. Both integrations were available but had no card on the Integrations page, so there was no way to reach their setup screens from the catalog. They now appear alongside the other integrations with their current connection status (Connected / Not Connected) and link through to their configuration pages.
0.6.227 — 2026-06-26
Changed
- Unified SLA admin hub. Default SLA targets, named SLA Policies, and
SLA Escalation Policies are now configured together under a single
Admin → SLA page (
/admin/sla) with Defaults, Policies, and Escalations tabs, instead of being split across Ticket Customization and two separate Settings screens. Each tab keeps its existing permission gate, and the old links (/settings/sla-policies,/settings/sla-escalation-policies) redirect to the matching tab so existing bookmarks keep working. Ticket Customization now links to the hub. SLA calculation and precedence are unchanged — this is a navigation/organization improvement only.
Added
-
Project comments / discussion thread. Project detail pages now have a Comments tab — a free-form discussion thread for the project. Post a comment, edit your own (marked (edited)), and delete your own; deleting someone else's comment requires delete permission on Projects. Posting/editing requires update permission on Projects, read-only users see the thread, and every change is audit-logged.
-
Attach documents to a project. Project detail pages now have a Documents tab where you can attach existing documents (SOWs, network diagrams, quotes, runbooks) from the Documents module to the project they relate to, follow each one through to the Documents module, and detach it. Attaching/detaching requires update permission on Projects and is audit-logged; detaching only removes the link, never the document itself.
-
Per-priority targets in SLA Policies. A named SLA Policy can now define distinct response/resolution times per ticket priority (Critical, High, Medium, Low) — matching what the org Defaults already support — instead of one flat target for all priorities. Enable Per-priority targets in the policy editor (Admin → SLA → Policies); a blank field falls back to the policy's flat target, then to the org per-priority default, and a policy can consist solely of per-priority targets. Fully backwards-compatible: existing flat-target policies compute identical due dates as before.
-
Stop-the-clock SLA pause. Ticket statuses can now be flagged Pauses SLA in Admin → Ticket Customization. While a ticket sits in a pausing status (e.g. "Waiting on Customer" or "On Hold"), its resolution SLA timer stops: the resolution due date is pushed out by the business-hours time spent paused, and that time is excluded from breach/at-risk detection and the SLA dashboard, so technicians aren't penalized for customer delays. Pausing and resuming are recorded on the ticket's history timeline; tickets can pause and resume any number of times. The response SLA never pauses. Backwards-compatible — orgs that flag no statuses see identical SLA behavior to before.
-
Project milestones. Projects now have a Milestones tab on the detail page for breaking a project into dated phases / checkpoints. Each milestone has a name, an optional description, an optional due date, and a status (Pending, In Progress, Completed); marking one Completed stamps its completion date automatically (and clears it if reverted). Add, edit, re-status, and delete milestones inline. Managing milestones requires update permission on Projects and is audit-logged; deleting a project removes its milestones. Additive and backwards-compatible.
-
Project notes. Projects now have a Notes tab on the detail page for collaboration notes — context, decisions, risks, and running status updates that belong to the project itself rather than a single ticket or task. Notes carry an optional importance (General, Important, Warning, Alert), show their author and timestamp, and are listed newest first. Adding and deleting notes requires update permission on Projects and is audit-logged; deleting a project removes its notes. Additive and backwards-compatible.
-
Project dollar (cost) budget burn-down. Projects with a Budget Amount now show a cost burn-down — the value of time logged against the dollar budget, the percentage consumed, the amount remaining, and an Over budget badge once spend passes the budget — on both the project detail page and the projects list, alongside the existing hours burn-down. Each time entry is valued the same way Ascent values it for invoicing (the entry's own rate, else the client's default rate, else zero), counting all time logged on the project's tickets and tasks. Display-only and additive; projects with no amount budget are unaffected.
-
Project over-budget notifications. When time logged against a project (on its tasks or its tickets) first pushes it past its hours budget, Ascent now sends an alert to the project manager and your org admins (respecting each person's notification preferences). It fires once per crossing — logging more time while already over budget won't re-notify — and resets if logged time later drops back under budget, so a re-crossing alerts again. Projects with no hours budget are unaffected.
-
Quiet hours / Do-Not-Disturb for notifications. Each user can now set a daily quiet-hours window (in their own timezone) on the profile Notifications card, during which non-urgent notification emails are paused. It's a lossless pause — in-app notifications and inbox items still arrive, so nothing is missed; only the emails are held back until the window ends. The window can cross midnight, and an Allow urgent alerts to override option keeps important emails (security alerts, on-call escalation pages) flowing through quiet hours. Per-user and additive — no change to anyone who leaves it off.
-
Slack & Microsoft Teams notifications. Ascent can now post notifications to a shared Slack or Microsoft Teams channel via an incoming webhook, in addition to the in‑app bell and email. An admin connects a channel under Settings → Integrations → Slack & Teams, chooses which notification types route to it, and can send a test message. The webhook URL is stored encrypted and never shown again; each event posts once to the shared channel, and a delivery failure is surfaced on the channel without ever blocking the action that triggered it. See Slack & Teams notifications.
-
ITFlow migration — billing import (Phase 4). The ITFlow importer now brings over your billing records alongside CRM, infrastructure and PSA: products/services, recurring invoices, quotes and invoices (with their line items), and payments. Invoice and quote totals are recalculated from the line items rather than trusting the source aggregates, and an invoice's status is derived from its imported payments (fully paid → Paid, partially paid → Partial). Like every other entity the import is idempotent and resumable, and anything it can't attribute (an orphan line item or payment, a recurring schedule with no next-run date) is surfaced in the run report instead of being dropped. No new permissions or database changes.
-
Migrate from ITFlow using a database backup file. The ITFlow migration can now import from an uploaded ITFlow backup (
.sqlor.sql.gz) — not just a live read-only MySQL connection. This is the easiest option and works even when the ITFlow database can't be reached directly (behind a firewall/NAT, or managed by someone who won't open the DB port), so it's now the default choice in the migration screen. Upload the backup; Ascent validates it, shows the detected ITFlow version and table counts, stores the file encrypted at rest, and runs the same import — clients, contacts, locations, assets, tickets and more — with the same resume/idempotency guarantees as the live connection. Note: ITFlow's password vault is protected by a separate master key that isn't part of a database backup, so vault secrets can't be imported from a backup. -
External anchoring of the audit trail ("genesis trust"). The org audit trail's tamper-evidence hash chain can now be externally anchored: a daily job publishes each organization's current chain head to an append-only, write-once store, and the integrity check (
GET /api/audit/verify-integrity) cross-checks those anchors — flagging a distinctanchor-mismatchif a previously anchored head has vanished, the signature of a wholesale log rewrite that an internally consistent chain alone can't catch. It's defense-in-depth and disabled by default (the existing append-only database protections already mitigate the underlying threat); operators opt in withAUDIT_ANCHOR_SINK=database, which needs no extra infrastructure. Anchoring is fully compatible with audit retention — a routine purge never raises a false alarm. -
Multi-channel on-call escalation steps. Each step of an escalation policy can now choose its own delivery channels — in-app, email, and webhook — instead of always paging in-app + email. Webhook steps fire one or more of your configured outbound webhooks through the same signed, retried delivery pipeline (a new
oncall.escalatedevent), so a page can reach a Slack-compatible or custom receiver without a separate integration. A step can also be set to notify until acknowledged, re-paging on a chosen interval until someone acknowledges the alert or the next step takes over. When a step sets channels explicitly they are honored even if a recipient muted that notification type — an escalation page isn't opt-out per step (the member-level "Receive notifications" toggle and disabled accounts are still respected). Configure all of this under On-Call → Escalation. -
Reusable SLA policies. Define named SLA targets once — "Gold", "1-Hour Response", and so on — and assign them to clients (and contracts) without authoring a billing contract per combination. A policy carries a response time, a resolution time, optional business hours/support days, and an optional timezone; anything you leave blank falls back to your organization's per-priority defaults. Manage them under Settings → Ticketing → SLA Policies, and assign one to a client from the client's Edit page. Existing contract SLAs are unchanged — when a ticket's targets are calculated, a contract's own SLA always wins, and a policy only fills the gap where no contract supplies targets.
-
Ticket templates can now carry default assignee, status, and custom-field values. Beyond subject, description, priority, and category, a template can pre-fill the technician a ticket is assigned to, the status it starts in, and values for your ticket custom fields. Those defaults are applied automatically when a ticket is generated from the template (including by recurring schedules), and duplicating a template copies them. References degrade gracefully — a later-deleted status, assignee, or custom field is simply skipped rather than blocking ticket creation.
Changed
-
Clearer ticket "CC Recipients" vs. "Watchers". The two cards on the ticket detail page now each carry a one-line description explaining what they do and how they differ — CC recipients are people copied on ticket emails (team members also see internal notes), while watchers are email addresses notified of selected events (reply / status / resolved) that never see internal notes. The ticket documentation gains a side-by-side comparison and a when-to-use-each guide. No change to behavior, data, or permissions.
-
Consistent toast feedback across the app. Transient feedback from saving, creating, updating, and deleting on full-page forms and actions — including form validation and API errors — now appears as a standardized status toast instead of an inline banner pinned to the page. Persistent, contextual notices (setup-incomplete and "not configured" banners, deliverability warnings, page-load failures, and messages shown inside dialogs) intentionally remain inline where they belong. This completes the app-wide inline-alert → toast conversion so action results behave the same way everywhere.
Fixed
- Audit-log integrity check no longer raises false "tamper" alarms. The tamper-evidence hash chain could report a recurring critical integrity alert ("the hash chain is broken … content-mismatch") on perfectly legitimate audit rows. The cause was a serialization mismatch: rows whose change snapshot contained a date, a decimal amount, or an omitted field were hashed one way when written and a different way when verified. The hash is now computed identically on both sides, so genuine records validate cleanly and the alert is once again a trustworthy signal.
- Integrity alerts now link straight to the flagged record and no longer re-notify every cycle for the same unresolved break — the alert opens the exact audit-log entry and pages once per distinct break instead of repeatedly.
- Operator remediation to re-anchor the audit trail. For trails that already recorded entries under the old hashing, an operator can attest the existing chain. It verifies the chain's structure is intact, then trusts those earlier rows going forward while continuing to fully verify everything newer. It refuses to run if the chain's structure is actually broken (a real tampering signal), and it never rewrites any stored record.
0.6.226 — 2026-06-25
Added
- Canned responses for the ticket reply composer. A reusable reply-snippet library so your team stops retyping common answers. The reply composer gains a Canned responses picker (next to Suggest reply) that inserts a saved snippet into the draft; manage the library from Settings → Ticketing → Canned Responses. Each snippet has a name, an optional category, and a rich-text body, and is either private to its author or shared org-wide. It's distinct from full-ticket templates and from AI-suggested replies. (#838)
- ConnectWise migration now imports agreements, configurations, projects, and opportunities. The ConnectWise PSA importer (Settings → Migrations → ConnectWise) gained its Phase 3 entities: agreements come across as contracts, configurations as assets (with the configuration type matched to the closest Ascent asset type), projects as projects (with the manager linked to the imported technician), and opportunities as opportunities (with company, contact, and sales rep linked). Each is matched to its company through the same idempotent id map, so re-running a migration updates rather than duplicates, and any record whose company didn't import is skipped and listed in the run report. (#851)
- Ticket watchers now get notified. Watchers (the email-only followers on a ticket's new Watchers sidebar card) previously received no emails at all. They now receive a notification when a ticket gets a public reply, changes status, or is resolved — and each watcher has independent On reply, On status, and On resolve toggles to tune which events email them (all on by default). Internal notes are never sent to watchers. Adding, removing, and editing watchers requires the tickets · update permission and is audit-logged. (#836)
Fixed
- SLA due dates now respect your organization's timezone and holidays. Ticket SLA response/resolution due dates were calculated as if every organization ran on UTC, so a ticket opened at 4:59pm in a non-UTC timezone (for example a "09:00–17:00" SLA in US Central time) got a due date that was an hour's worth of business time off, and full-day holiday closures were not skipped when counting business minutes. The SLA clock now evaluates business days and hours in your organization's timezone (from Settings → Organization) and skips US Federal holidays and your configured all-day closures, matching the timezone-aware behavior already used by on-call rollover. (#839)
0.6.225 — 2026-06-25
Added
- Configurable SLA escalation policies. Admins can now define named,
multi-step escalation chains for ticket SLAs under Settings → Ticketing
→ SLA Escalation Policies. Map a policy to tickets by priority, client,
and/or category (the most specific active policy wins), then add ordered
steps that fire automatically at a configured offset after at-risk or
after breach — each step can reassign the ticket, bump its priority,
notify a specific user, or notify a whole role group. The SLA check job
runs each step exactly once per ticket and writes every action to the audit log.
When no policy matches a ticket, the previous default still applies (a breached
critical ticket is reassigned to the first admin). Managing policies requires the
new
sla_escalation_policiespermission; all members can view them. (#833) - Saved ticket views. You can now save the current ticket-list filters and sort as a named view (e.g. "My open P1s", "Unassigned today") and re-apply it in one click from the new Saved Views menu in the ticket list header. Views are private by default (visible only to you) or can be shared with your whole organization. Saving requires the ticket create permission and deleting requires the ticket delete permission; only a view's creator can edit or delete it, and every change is written to the audit log. (#834)
- Log time directly from a project. The Add Time button on a project's Time Entries tab and the Log Time quick action are now wired up. They open a dialog that lets you pick one of the project's tickets or tasks, enter minutes, an optional description, a date (for tickets), and whether the time is billable. The entry is recorded on the chosen ticket or task and immediately rolls up into the project's hours and burn-down. The buttons are shown only to users who can log time (create on Ticket Time, or update on Tasks), and every entry is written to the audit log. This completes the project time-tracking work started in #842. (#843)
0.6.224 — 2026-06-25
Fixed
- Project hours now include time logged on the project's tickets. Previously a project's hours and burn-down only counted time logged on its tasks, so a project whose tickets had time attached still showed 0 hours used. Time logged on any ticket linked to a project now rolls up into the project's hours — in both the project list budget column and the project detail burn-down — alongside task time, with no double counting. The burn-down also shows a breakdown of hours on tasks vs. hours on tickets. (#842)
Added
- Project time-entry breakdown. The Time Entries tab on a project now shows a read-only, combined list of all time logged against the project — both ticket time and task time, newest first — with a link back to the originating ticket or task. (#842)
0.6.223 — 2026-06-24
Added
- ITFlow migration tool (Phase 1). A new guided, read-only importer
brings your data from ITFlow into Ascent. Because ITFlow has no full-export
API, you connect a read-only MySQL connection to your ITFlow database; this
first phase imports your core CRM records — clients, contacts, and
locations — and is idempotent (re-runs update rather than duplicate),
resumable, and rate-limited so it won't overload your ITFlow server.
Credentials are stored encrypted at rest and never written back. Find it under
Admin → ITFlow Migration (requires the
migrationspermission). (#779) - ITFlow migration — Assets & Infrastructure (Phase 2). The ITFlow importer now also brings over your vendors, assets, software, licenses, domains, certificates, and networks. Assets keep their make/model/serial/OS, purchase and warranty dates, and link to the imported client and location; an unrecognized asset type imports as Other and is flagged in the run report. Standalone licenses import with their seat counts and an encrypted license key, and certificates/domains/networks link to their imported client. Like Phase 1 it is idempotent, resumable, and surfaces anything it can't attribute in the run report. (#780)
- ITFlow migration — PSA: tickets & time (Phase 3). The ITFlow importer now also brings over your technicians, tickets, ticket replies, and time entries. Each technician imports as a disabled placeholder user (or links to an existing org member with the same email) so their tickets and time stay attributed. Tickets link to their imported client, contact, assignee and creator; priority and source map to Ascent's values, and the ticket status is matched to one of your statuses by name (an unmatched status is flagged in the run report). Replies import as internal notes (unless ITFlow marked them public), and time entries carry their minutes and billable flag — a time entry whose technician wasn't imported is skipped and logged. Like the earlier phases it is idempotent, resumable, and surfaces anything it can't attribute. (#781)
- Project hours-budget burn-down and over-budget alerts. Projects with a budget in hours now show how much of that budget has been consumed. The project detail page's Budget card adds a burn-down bar with hours used vs. budgeted, the percentage consumed, and hours remaining — turning red and showing an Over budget badge once logged time passes the budget. The Projects list now shows the percentage used in the Budget column and flags over-budget projects at a glance. Projects with no hours budget are unchanged. (#827)
- Dispatch board capacity heatmap and overbooking / skill warnings. Each technician/day cell on the Dispatch Board is now shaded by how full it is — booked time (calendar events plus scheduled tickets) against the technician's working hours — with a small utilization percentage, deepening to red as a day reaches and passes capacity. When you assign work onto an already-full day, or onto a technician who lacks a skill the ticket is tagged with, an advisory warning appears in the confirmation — the assignment still completes, so you stay in control. Tag tickets with a skill and assign matching skills to technicians to enable the skill check; orgs that don't use skills never see it. (#661)
- Link an invoice to a project. A project's Create Invoice quick action now attaches the new invoice to that project. The New Invoice form shows the linked project read-only (with the project's client pre-selected) when you arrive from a project, and sends the link when you save. Changing the client removes the link so an invoice can't be attached to a project that belongs to a different client. Invoices created without a project are unaffected. (#817)
- Security alerts for high-risk audit events. Ascent now watches your audit trail and notifies admins when something looks anomalous: a burst of deletions by one user, a flurry of permission/role changes, repeated failed sign-ins for a member, or an audit-log integrity failure. Each signal has a conservative, configurable threshold on the Audit Logs admin page (under High-risk event alerts), and repeat alerts are throttled so an ongoing condition pages once per cooldown rather than every few minutes. Alerts arrive as a new Security notification type and deep-link to the audit log for investigation. (#727)
Fixed
- Link a ticket to a project from the New and Edit ticket forms. Previously the only way to attach a ticket to a project was to start from a project's page — the standalone New Ticket form showed the project as a read-only badge (only when arrived at via a project link) and the Edit Ticket form had no project field at all, so a ticket could never be re-linked or unlinked afterwards. Both forms now have an editable Project picker: pick a project on create, change or remove the project when editing, and choose No project to unlink. Selecting a project keeps the ticket's client consistent with the project's client so a mismatched client/project can't be saved. (#820)
0.6.222 — 2026-06-24
Fixed
- Ticket attachments no longer 404 when previewing or downloading. Viewing or downloading any ticket (or reply) attachment was returning 404 Not Found for every file — a regression from the move to cookie-based authentication, which left attachment retrieval depending on a query-string token the app no longer sends. Attachments now load directly using your signed-in session: images, PDFs, video, audio, and text preview inline, and the Download button saves the file. Files were never lost — only retrieval was broken. (#819)
0.6.221 — 2026-06-24
Added
- Client portal: shared credentials and a richer asset view. MSPs can now opt individual credentials in to the client portal (per credential, off by default) from the credential New/Edit forms. Portal users who are Primary or Technical contacts get a new Credentials page where they can view shared logins and reveal a password on demand — every reveal is audit-logged. Portal assets now have a detail view showing specifications, warranty, and location, along with the client-visible documents and shared credentials related to that asset. RMM- and network-internal fields are never exposed to the portal. (#778)
- Rich text and attachments when creating a ticket. Both the technician New Ticket form and the client-portal New Ticket form now use the same rich-text editor as the reply composer for the description (bold, italic, lists, links, code, and more) and let you attach files directly on the create form. Files added during creation are attached to the new ticket and appear on its detail page. Existing plain-text descriptions continue to display unchanged, and submitted HTML is sanitized to prevent script injection.
Fixed
- Tickets created from a project are now linked to it. Using Create Ticket from a project page now attaches the new ticket to that project: the project is shown (read-only) on the new-ticket form with its client pre-selected, the created ticket appears under the project's Tickets tab and in its ticket counts, and the ticket detail page links back to the project. Previously the project was silently dropped and the ticket was left unlinked.
- Create Invoice from a project no longer loses context. The project's Create Invoice quick action now pre-selects the project's client instead of passing a project reference the invoice form couldn't use. (Linking an invoice directly to a project is tracked as a follow-up, since invoices don't yet carry a project association.)
0.6.220 — 2026-06-23
Added
- Reveal a credential with your passkey. When your organization requires re-authentication before revealing a credential, you can now confirm with your passkey (security key or biometric) — the strongest factor — with a single Verify with passkey button, instead of being limited to a password or an authenticator code. If you have a passkey registered, it's offered first.
Fixed
- Step-up to reveal a credential no longer dead-ends passkey users. Users who sign in with single sign-on and have a passkey (but no authenticator app) were previously sent to set up an authenticator and could get stuck. A passkey now satisfies the re-authentication requirement directly, so there's no need to enroll a weaker factor.
- Enrolling an authenticator app no longer dead-ends for users who already have a passkey. If you had a security key or passkey registered (but no authenticator app) and tried to set one up — for example when prompted to add a second factor to reveal a credential — the Set up authenticator app button failed with a generic "Failed to start MFA setup" error and left you with no way forward. You can now add an authenticator app alongside an existing passkey, and if setup ever does fail the page shows the actual reason instead of a placeholder.
0.6.219 — 2026-06-23
Added
- Hudu migration (Phase 1). A new guided, resumable, read-only importer brings your IT documentation across from Hudu — companies, knowledge-base folders and articles, passwords, websites (domains, with SSL certificates) and networks — into Ascent. Source credentials and imported passwords are stored encrypted at rest, the import is idempotent (re-running updates rather than duplicates) and throttled so it never trips Hudu's rate limit, and every run produces a per-entity report of what loaded, skipped, or failed. Find it under Admin → Hudu Migration. (Hudu's custom Flexible Assets arrive in a later phase.)
- Related Items: see and manage everything linked to a record in one place. Asset, credential, document, contact, software, vendor, domain, and certificate detail pages now show a unified Related Items panel that groups every linked record by type and lets you link or unlink records inline — search for what you want to link, click to add it, or remove a link with one click. You only ever see links to records you're allowed to view, and adding or removing a link requires edit access to both records (and is recorded in the audit log).
Fixed
- The AI suggestion banner no longer flickers back after you act on it. When you accepted or dismissed a ticket's AI categorization suggestion, a slow, already-superseded background request could occasionally re-display the banner a moment later. The banner now stays gone once you accept or dismiss it.
0.6.218 — 2026-06-23
Fixed
- Revealing a credential now works for SSO sign-in. When your organization requires re-authentication before a stored secret is shown, users who sign in with single sign-on (Microsoft, Google, Okta, and others) can now complete the check with their authenticator app instead of being bounced to the login page and dropped on the dashboard. The confirmation dialog adapts to how you sign in: password users still see the password field, while SSO users are asked only for a current 2FA code. If an SSO user has no authenticator set up yet, the dialog explains why the reveal can't proceed and links straight to Profile → Two-Factor Authentication to enrol one. Failed re-authentication attempts are now recorded in the credential's history alongside successful reveals.
Added
- ConnectWise migration now brings over your tickets (Phase 2). The ConnectWise importer extends past companies and contacts to the core PSA data: your technicians (imported as non-login placeholder users, or linked to an existing teammate by email), tickets (with company, contact, owner, priority and source, and board/status matched by name to your Ascent categories and statuses), ticket notes (as internal notes), and time entries (hours, billable status, date, and rate). Records that can't be matched — an unrecognized priority, a board with no Ascent equivalent, a ticket whose company didn't import — are surfaced in the run report instead of being silently dropped, and re-running a migration updates existing records rather than duplicating them. See ConnectWise PSA Migration.
- Request an on-call shift swap with a teammate. On-call members can now ask another member to cover — or trade — one of their shifts instead of waiting for an admin to apply an override. The teammate gets a notification and an action-required inbox item; when they accept, the coverage updates automatically (a trade updates both shifts), and the requester is notified. Requests can be declined or cancelled while pending, expire once the shift begins, and show an advisory warning if the covering member is already on call during the window. See On-Call → Request a shift swap.
0.6.217 — 2026-06-23
Fixed
- Viewing a credential is audited again. Opening a credential record now records an Accessed event in its history, restoring the "who looked at this credential" trail that briefly went missing when revealing a secret became a separate, explicit action. Revealing the secret is still logged as its own distinct Revealed event, so you can tell apart who simply viewed a credential from who actually exposed its password or 2FA code. Access events are recorded only when opening an individual credential — not when browsing the credential list.
0.6.216 — 2026-06-23
Added
- ConnectWise PSA migration (Phase 1). A new guided, resumable, read-only importer brings your Companies (as clients) and Contacts across from ConnectWise Manage into Ascent — joining the existing Autotask and SyncroMSP migrations. Connect with an API member's keys and your client id under Admin → ConnectWise Migration; credentials are stored encrypted and never written back. Imports are idempotent (re-runs update rather than duplicate), resumable after interruption, throttled to respect ConnectWise's rate limits, and produce a per-run report flagging any unmapped values. An optional "changed since" date runs a delta cut-over. More entities (technicians, tickets, notes, time entries) will follow in a later phase.
Fixed
- The "Require re-authentication to reveal" credential setting is now visible and usable. The Credential Vault step-up control shipped in 0.6.214 lived in a Settings → Security screen that was never actually rendered, so admins had no way to turn it on even though the backend already enforced it. The toggle now appears in the live Settings → Security tab, reflects the saved value, and persists across save and reload. Enabling it prompts users to re-enter their account password or a current 2FA code before any stored credential secret is revealed; disabling it restores one-click reveals.
0.6.215 — 2026-06-23
Fixed
- Notifications no longer reach deactivated users. In-app notifications and notification emails were still being delivered to users whose org membership had been disabled (often former employees) or whose account was globally deactivated. Delivery now excludes any recipient whose membership is disabled or whose account is inactive — across every notification trigger, including ones that target a user directly (such as a ticket assignee or the on-call agent), and the email path enforces the same rule independently. Re-enabling a member restores delivery automatically. Active members are unaffected.
0.6.214 — 2026-06-22
Changed
- Tidier navigation sidebar with collapsible Admin sub-groups. The Admin section no longer scrolls forever — its AI, Ticketing, and Migrations tools are now bucketed into collapsible sub-groups. Click a sub-group header to expand or collapse it; your choice is remembered per-user, and the sub-group containing the page you're on opens automatically so the active item is never hidden. Credentials also moved from Assets to Knowledge base, where reference/secret documentation belongs. Every item keeps its existing permission, role, and feature gating — nothing changed about who can see what.
Added
- Autotask migration now imports assets, contracts, projects and tasks (Phase 3). The Autotask PSA importer extends beyond ticketing to your configuration items (→ assets), contracts and their services (→ contract line items), and projects and tasks — each linked to the client, contract, project, technician or assignee it belongs to, and skipped with a clear log entry when its parent was not imported. Every imported record also carries its Autotask user-defined fields, so none of your custom data is lost, and the original contract type (Block Hours, Time & Materials, …) is preserved as a label. Re-running a migration updates these records instead of duplicating them, exactly like the earlier phases.
- Autotask migration is ready for a real go-live cut-over (Phase 4). The importer adds the pieces you need to switch off Autotask for good: an opt-in ticket attachments import (run as a final, slower pass so it can't trip your Autotask API limits); a dry run that previews exactly what a migration would import — counts and any unmapped picklist values — without writing anything; a delta cut-over that re-imports only the records changed in Autotask since a chosen date (updating what you already brought across); and a one-click CSV / JSON export of any run's report.
- Secure share links for credentials and documents. You can now hand a
single credential or document to someone outside Ascent with a Share link
instead of emailing a password in plaintext. Set an optional expiry,
max views, and a link password; the link is shown once and the raw
token is never stored. Recipients open the link with no Ascent account and see
only that one item; every time a link is opened it is recorded as an
ACCESSaudit event (with the viewer's IP) so you can see who viewed it. Active links can be listed and revoked from the item's detail page, and expired or used-up links are cleaned up automatically. Creating links is gated by a newcredentials.share/documents.sharepermission, separate from viewing the item. - Credential reveals are now logged, gated, and optionally re-authenticated.
Opening a credential no longer shows its password or 2FA secret automatically —
you now click Reveal to see them, and revealing (along with generating a
live 2FA code or viewing a credential's history) requires the
credentials.revealpermission, separate from being able to read the credential. Every reveal is recorded as a distinct Reveal event in the audit log — who revealed what, and when — so you can answer "who has seen this password?". For higher-assurance environments, admins can turn on Require re-authentication to reveal under Settings → Security, which prompts the user for their account password or a current 2FA code before any secret is shown. - Credential rotation tracking. Each credential can now carry an optional rotation interval; the vault records when its password was last changed and flags it as overdue once the interval passes, so stale passwords stand out. A credential's detail page also shows an access & rotation history — every reveal and password change — without ever exposing the secret itself.
- Unified Expirations dashboard & configurable proactive alerts. A new
Expirations page (and dashboard widget) brings every expiry date in one
place — domain registrations, SSL certificates, software & license keys, asset
warranties and contracts — with overdue/upcoming counts, time-window (30–365
day) and per-type filters, the global client filter, and deep links to each
record. The daily expiration check that emails admins is now configurable per
organization under Settings → Expiration Alerts: a master on/off switch,
the lead time (how far ahead to warn), a re-notify window so a daily
run no longer re-alerts about the same item every day, and per-category opt-in.
Viewing the dashboard is gated by a new
expirations.readpermission; changing the alert settings byexpirations.manage.
Fixed
- Client detail tabs no longer wrap into a broken, centered second row. On narrower screens the client detail page's tab strip wrapped any overflow tab (such as Portal) onto a second row and floated it in the middle of the strip instead of left-aligning it. The wrapped rows are now left-aligned and the strip grows in height cleanly. The standalone Credits tab has also been folded into the Overview tab — the account-credits card now appears alongside the client's financial settings — trimming the tab count and keeping related financial information together. Issuing, viewing, and deleting credits works exactly as before, behind the same permission checks.
0.6.213 — 2026-06-22
Added
- Flexible Asset Layouts — document any kind of client infrastructure. Administrators can now define their own reusable asset types ("layouts") such as Wireless Networks, SSL Certificates, or Vendor Portals, each with its own ordered set of typed fields (text, number, date, dropdowns, checkboxes, URLs, passwords, section headings, and links to assets/credentials/documents/ contacts), an icon, and a color. Build a layout in Admin → Asset Layouts with drag-to-reorder fields, then create records against it under Assets → Flexible Assets using a form rendered automatically from the layout. Flexible assets are searchable from the global search bar and respect existing role-based permissions, and are kept separate from RMM-synced hardware assets so your hardware inventory stays clean.
Fixed
- Domain WHOIS refresh no longer reports as failed when WHOIS is blocked. The background WHOIS lookup that enriches domain records (registrar, registration/ expiry dates, nameservers) opens an outbound connection to each registry's WHOIS service. In environments where that outbound traffic is blocked, every lookup failed and the job was recorded as a failed run (a 100% failure rate), even though nothing was actually broken. The job now treats an unreachable WHOIS service as a graceful skip: it still refreshes DNS records and records when the check ran, notes the connectivity error on the domain so stale WHOIS data is explained, and completes successfully. A genuine WHOIS lookup recovers and clears that note automatically. Unexpected (non-connectivity) errors still surface as failures so real bugs aren't hidden.
0.6.212 — 2026-06-22
Fixed
- Connecting a client's own Microsoft 365 tenant no longer dead-ends. Previously, the per-client Connect Microsoft 365 button could fail with "Microsoft 365 app credentials are not configured for this organization" with no way to recover. The client's Microsoft 365 card now lets you connect with a dedicated app registered for that client (the default — paste its Application ID and client secret, plus a Tenant ID for single-tenant apps), or toggle Reuse organization's Microsoft 365 app to use your org-level app instead. If you choose to reuse the org app but it isn't set up yet, the card explains why and links you straight to Admin → Integrations → Microsoft 365 to configure it.
0.6.211 — 2026-06-22
Fixed
- Scheduled jobs now run reliably again. Four background jobs — recurring invoices, recurring tickets, the daily expiration/overdue check, and client health snapshots — were failing on every run and silently doing no work, so recurring invoices weren't generated, recurring/maintenance tickets weren't created, and expiry/overdue notifications weren't sent. The shared cause was an internal scheduling bug that rejected the per-organization work these jobs fan out; it has been fixed and the jobs now complete normally. As part of the fix, the daily expiration check is now correctly scoped to each organization, so it no longer scans other tenants' contracts on every run.
0.6.210 — 2026-06-21
Added
- Audit logs now have a configurable retention policy. Admins can set how long audit-log entries are kept (default 365 days, or 0 to keep them forever) from the Audit Logs admin page. A daily background job moves entries older than the window into a separate cold-storage archive and removes them from the live trail — keeping the log manageable and satisfying storage-limitation requirements without losing the evidence. The archived entries retain their tamper-evidence hash, so a retention purge can never be used to quietly drop history: the audit-integrity check still flags any deletion that wasn't a recorded retention purge, and the purge itself is recorded in the log.
Internal
- Dependency maintenance sweep. Updated a batch of dependencies to their
latest patch/minor releases to stay current and keep the vulnerability surface
clear. No source advisories were outstanding (
bun auditclean before and after). Updated:@aws-sdk/client-s3and@aws-sdk/s3-request-presigner(3.1072.0 → 3.1073.0),@sentry/bunand@sentry/react(10.58.0 → 10.59.0),@anthropic-ai/sdk(0.104.2 → 0.105.0),cron-parser(5.5.0 → 5.6.0),imapflow(1.4.1 → 1.4.2),mailparser(3.9.10 → 3.9.11), andpg-boss(12.19.1 → 12.20.0). No application behavior changed.
0.6.201 — 2026-06-21
Added
- On-call coverage conflicts are now surfaced when requesting and approving
time off. When you request time off that overlaps a shift you are on call
for, a heads-up now appears so you and your approver can arrange coverage. In
the manager approval queue, requests that collide with the requester's on-call
shifts are flagged, and approving a request that would leave an on-call window
with no other coverage is now blocked — a dialog lists the uncovered
windows and lets a manager Approve anyway with an explicit acknowledgement.
The check is enforced server-side, so the same gate applies to API approvals
(a plain approval that would create a gap is rejected with
COVERAGE_GAPuntil resubmitted with the acknowledgement flag). Denials are never gated.
0.6.200 — 2026-06-20
Added
-
Autotask migration now imports tickets, time, and technicians. The Autotask PSA importer goes beyond companies and contacts: it now brings in your technicians, tickets, ticket notes, and time entries. Tickets keep their client, contact, and assigned-technician links, and your Autotask priority / status / queue / source picklists are translated to Ascent (matching statuses and categories by name). Imported technicians become disabled, login-less accounts that just own the imported history — or link to a matching existing user — so nothing is duplicated. Anything that can't be mapped is listed in the run report for you to review. See Autotask PSA Migration.
-
AI Chat Assistant — export a conversation. You can now save the current Jasper conversation from the download icon in the chat panel header: Download as Markdown (a readable transcript), Download as JSON (a structured file), or Copy as Markdown. The transcript includes each message's role, text, and timestamp, and shows any proposed or confirmed actions as readable lines. Exporting happens entirely in your browser — it only saves what you already see in your session.
-
On-call schedule layers — run primary and backup coverage at the same time. A rotation now sits on a coverage layer, so you can have a Primary rotation and one or more Backup rotations on-call for the same window instead of being limited to a single person. Every existing rotation stays Primary, so nothing changes unless you add a backup. Coverage is always resolved primary-first: the On-Call Now widget lists the primary member first and then each backup, the schedule calendar tags backup shifts so layered coverage is visible at a glance, and new-ticket notifications and alert routing page the primary member. See On-Call → Schedule layers.
Maintenance
- Dependency updates. Routine maintenance sweep bringing eight packages up
to their latest non-breaking releases — the Anthropic SDK, the AWS S3 client
and presigner, the Sentry error-tracking SDKs, the IMAP and email-parsing
libraries, and the background-job queue. These are patch/minor updates with no
user-facing behavior changes;
bun auditreports no known vulnerabilities before or after.
Security
- The audit trail is now tamper-evident and append-only. Audit log entries can no longer be edited or deleted once written — the database itself rejects any such attempt — and every entry is cryptographically chained to the one before it, so a silent change or deletion (for example, by someone with direct database access) is detectable. Admins can run an integrity check that confirms the trail is intact and pinpoints the first altered entry if it isn't. Deleting an organization or user still works and does not falsely trip the check. This supports ISO 27001 / SOC 2 logging requirements.
0.6.194 — 2026-06-20
Fixed
- CI: the
codecov/patchcheck no longer blocks pull requests whose changed lines are genuinely covered. The patch gate kept flapping red on fully-tested PRs because of a documented coverage-attribution artifact in the sharded, isolated test run (a shared source file exercised 100% by its dedicated test could lose hits when consuming tests re-imported it in the same shard, before the per-shard coverage reports were merged). The patch status is now advisory: Codecov still computes and posts patch coverage for reviewers, but it can no longer block a merge. The hard enforcement of record stays the 95% project coverage gate, which still blocks any PR that genuinely drops coverage.
0.6.193 — 2026-06-20
Added
- Jasper can now answer from your live data. The AI Chat Assistant can look up your clients, tickets, and projects — and score a client's health — to answer questions like "how are my clients' health looking?" or "how many open tickets does Acme have?" These lookups happen automatically while it replies (nothing to confirm), and every lookup runs as you: it only ever reads the data your role and client access already allow, and it's only offered the lookups your permissions grant. See AI Chat Assistant → Answering from your data.
- SLA awareness on the Dispatch Board. Tickets on the board now show whether they're breaching, due soon (within 4 hours), or on track against their SLA — a coloured badge on each unassigned queue card and an urgency dot on at-risk scheduled chips. A new Sort: SLA / Priority toggle lets you order the unassigned queue by SLA urgency (the default) so the most time-critical work to dispatch surfaces first.
- Subscribe to your schedule from any calendar app. You can now generate a personal iCal (ICS) subscription URL from Team Management → Schedule → My Schedule and add it to Google, Outlook, or Apple Calendar. The feed shows your on-call shifts and approved time off and refreshes automatically. Each URL is shown once, can include on-call and/or time off, and is revocable at any time — treat it like a password, since anyone with the link can read your schedule.
- New scheduling reminders keep time off and on-call coverage from slipping through the cracks. Ascent now sends proactive reminders for the scheduling module: approvers get a nudge when a time-off request has been waiting more than a day for a decision, team members are reminded shortly before their approved time off begins, and whoever is up next on call gets a heads-up before their shift starts. Reminders arrive in-app and by email according to your notification preferences, link straight to the relevant view, and are sent at most once per request or shift. You can turn each of them on or off from Profile → Notifications — the Time Off category gains Approval Reminder and Time Off Starting Soon toggles, and a new On-Call category adds an On-Call Shift Starting toggle.
Fixed
-
Jasper now finds clients and tickets by name — no more asking for IDs. When you asked the assistant to create a ticket (or act on a record) for a client by name, it would ask you to supply the client's internal ID. Jasper now looks the record up by name itself, asks you to choose by name when more than one matches, and shows the resolved name on the confirmation card so you never have to see or enter a raw ID. Lookups stay scoped to what your role and client access allow. See AI Chat Assistant → Actions the assistant can take.
-
Online (Stripe) payments are now always written to the audit log. When a client paid an invoice online — through the public payment page or via a Stripe webhook — the recorded payment was not captured in the organization's audit trail (only manually-entered in-app payments were). Every Stripe-recorded payment now writes a
Payment"create" entry to the audit log, regardless of which path recorded it, so the financial trail is complete. Payment is also now selectable in the audit log's entity-type filter.
Internal
- Added a regression guard that fails the build if a new organization-scoped mutating API route is added without an audit-log write (or an explicit, documented exemption), keeping audit coverage from silently regressing.
0.6.192 — 2026-06-19
Fixed
- The AI Chat Assistant (Jasper) no longer loses your conversation when you move around the app. Previously, opening a ticket — or anything that briefly closed the chat panel — could wipe the open conversation, and pressing Esc to dismiss a dialog, popover, or dropdown on a busy page could close the chat along with it. The conversation now stays put as you navigate and when you close and reopen the panel, and Esc only closes the chat when the chat itself is in focus, so it no longer disappears unexpectedly.
0.6.191 — 2026-06-19
Added
- AI Chat Assistant — more confirm-first actions. Beyond opening tickets, replying, and logging ticket time, the assistant can now also propose creating a project, adding a task to a project, creating a contact, and creating an asset for a client. As before, the assistant only proposes — nothing runs until you click Confirm, each action runs as you with your own permissions and client access (re-checked at confirm time), it is only offered actions your role allows, and every confirmed action is recorded in the audit log. These are all create actions; updating and deleting remain things you do yourself in the app.
Changed
- Notification bell is now a management panel. Opening the bell shows a richer panel where you can switch between All and Unread, Mark all read or Clear all in one click (with the badge updating immediately), and mark an individual notification read without leaving the page. It also has proper loading and empty states and is keyboard- and screen-reader-friendly (the bell and inbox icons announce their unread counts).
Security
- Audit log "user activity" view is now strictly scoped to your organization. When an org admin viewed a specific user's activity on the audit log, the underlying query could fetch that user's audit rows from other organizations they also belong to before filtering them out, and the displayed entry count could be wrong. The organization filter is now applied in the database query itself, so only your own organization's events are ever retrieved and the totals shown always reflect your organization alone.
0.6.190 — 2026-06-19
Added
-
AI Chat Assistant — confirm-first actions (early access). The assistant can now propose a few actions in addition to answering questions, and run one only after you click Confirm. To start, it can open a ticket, add a reply or internal note to a ticket, and log time against a ticket. Every proposed action shows a card describing exactly what it will do; nothing happens until you confirm it. A confirmed action runs as you, with your own permissions — if your role doesn't allow it (or you don't have access to that client), it's refused even if the assistant suggested it — and each one is recorded in the audit log against the record it changed. The assistant is only offered the actions your role allows. Off by default and only available on plans that include it.
-
AI Chat Assistant — AI Chat Logs (early access). Admins get a new AI Chat Logs view (under Admin) that records the conversations where the assistant proposed or ran an action, so there's an auditable trail of what the assistant was asked to do and what happened. Pure question-and-answer chats are never stored — only conversations that involved an action are kept — and the stored messages are encrypted at rest. The view shows the acting user, the actions proposed/executed and their outcome, and the conversation. It's gated by a dedicated AI Chat Logs permission (owners and admins by default) and is strictly scoped to your own organization.
Security
- Patched a high-severity dependency vulnerability. Updated the bundled
email library (
nodemailer) across the whole dependency tree to a fixed release, closing an advisory that could have allowed crafted messages to read local files or reach internal services. No action is required on your part.
Changed
-
Scheduling tools grouped under "Team Management." Schedule, Time Off, On-Call, and Holidays & Closures now live together in a new Team Management section of the left sidebar instead of being scattered across the PSA group and settings. The duplicate Time Off Requests nav entry is gone; owners and admins now open the team approval queue from a Manage requests button on the Time Off tab. All existing links (including
/settings/time-offand/scheduledeep links) continue to work. -
Routine dependency maintenance. Refreshed several third-party libraries (rich-text editor, AWS S3 client, Stripe, and others) to their latest compatible versions. No user-facing behavior changes.
-
The AI Chat Assistant now goes by Jasper. The in-app chat helper your technicians see in the chat bubble now introduces itself as Jasper, giving the assistant a friendly, consistent persona across its greeting and replies. Nothing about how it works changes, and the settings page and navigation stay labeled AI Chat Assistant so they remain easy to find.
0.6.186 — 2026-06-19
Fixed
- Past-dated time-off requests no longer linger as pending. A time-off request whose dates fully passed without anyone approving or denying it used to stay Pending forever and keep an action-required approval prompt in managers' inboxes. An hourly background job now automatically closes such requests as Expired and clears the stale inbox and notification items. Expired requests remain visible in history.
0.6.185 — 2026-06-19
Added
- AI Chat Assistant — permission-aware answers (early access). Building on the configuration released earlier, the assistant can now answer your technicians' questions about using Ascent, streaming replies from the AI provider you chose. It is permission-aware: it tailors its guidance to what each person is allowed to do — and points them to an administrator for anything outside their permissions — and links to the documentation for step-by-step help. For now it stays Q&A only (it can't change any data on your behalf), and the in-app chat bubble and keyboard shortcut are still rolling out. Off by default and only available on plans that include it.
Fixed
- SyncroMSP migration page no longer fails to load. Opening Migrations →
SyncroMSP previously showed a
Route GET /api/migrations/syncro/ not founderror and never listed your migrations, because the page requested the list with a trailing slash that the server doesn't match. The list now loads correctly, and creating a new SyncroMSP migration works again.
0.6.184 — 2026-06-18
Added
- Dispatch Board — readable dense boards. Technician/day cells now stay compact when a technician has many tickets: the most urgent few show with a +N more expander to reveal the rest. A new Comfortable / Compact toggle controls how much each ticket chip shows, and the Unassigned queue shows the first batch with a Show all control while the count badge always reflects the true total.
- Dispatch board — drag tickets between technicians and back to the queue. You can now rebalance scheduled work without leaving the board. Drag a ticket that's already on a technician's row onto a different technician's day cell to reassign it (it's scheduled for the day you drop on, the new technician is notified, and a time-off conflict is flagged just like a fresh assignment), or drag it onto the Unassigned panel to send it back to the queue — which clears its assignee and schedule and notifies the technician it was taken from. A "Drop here to return to the queue" hint appears while you drag an assigned ticket. Requires the Dispatch assign permission.
- Schedule dispatch work to a specific time with the new Timeline view. The Dispatch Board now has a Timeline view alongside Day and Week: a single-day, hour-by-hour grid with your technicians as columns. Drag an unassigned ticket onto a 30-minute time slot to schedule it for that exact time (the confirmation names the slot, e.g. "Scheduled for Wed Jun 17, 10:00 AM"). Each technician's working hours are shaded, time off is highlighted, and scheduled tickets, calendar events and on-call windows render as blocks that sit side by side when they overlap — so a double-booking is obvious at a glance. Times use your browser's local timezone.
- Manager / direct-report visibility for schedules, time-off & availability. Each team member can now have a manager (set by an admin/owner on the Settings → Users page). Schedule, time-off, and Team Availability views are now scoped by that hierarchy: a regular member sees only their own, a manager additionally sees their direct reports, and admins/owners still see the whole organization. Time-off approvals are routed to the requester's manager (with admins/owners as a fallback), and a member can no longer approve their own request. Enforcement is server-side. (#676)
Fixed
- Dispatch Board tickets are now clickable. Scheduled-ticket chips and unassigned-queue cards on the Dispatch Board now link to the ticket's detail page, so you can open a ticket straight from the board. Cmd/Ctrl/middle-click opens it in a new tab and the links are keyboard-accessible; dragging an unassigned card to assign it still works and never accidentally navigates.
0.6.183 — 2026-06-18
Fixed
- Dispatch board assignments now notify the technician. Assigning a ticket to another technician from the Dispatch board sends that technician an in-app notification and an inbox item, exactly like assigning from the ticket detail screen. (This already worked under the hood; we confirmed it and added test coverage so it can't silently regress.) Assigning a ticket to yourself intentionally sends no notification — the board's success message now says so clearly instead of implying a teammate was alerted.
0.6.182 — 2026-06-18
Fixed
- Autotask Migration page now loads its run history and can create runs.
Opening Administration → Autotask Migration no longer shows a
Route GET /api/migrations/autotask/ not founderror. The page was requesting the migration list — and creating new migrations — with a stray trailing slash that didn't match the server route; both now hit the correct path, so existing runs (or the empty state) render and creating a migration works. Testing a connection and starting, cancelling, or deleting a run already used the correct paths and are unchanged.
0.6.181 — 2026-06-18
Added
- Filter & search the Dispatch Board. A filter bar above the board now lets dispatchers narrow it by free text (ticket number or subject), client, priority, status, and technician. The filters apply live to both the technician rows and the Unassigned queue, the active filter is saved in the page URL (so a filtered board is shareable and restored on reload), and a Clear button resets everything. Part of the ongoing Dispatch Board revamp.
Fixed
- Dispatch board — drag-to-assign now schedules the day you dropped on. In Week view, dragging an unassigned ticket onto a technician's day cell previously scheduled it for the first day of the week (Sunday) instead of the day you dropped on. Drops now schedule for the correct day (at the technician's work-start time, or 9:00 AM when no schedule is set), Day view is unchanged, and the inline "Assign to…" picker uses a clear default (today when it's in the visible window, otherwise the start of the window). The success message now tells you which day the ticket was scheduled for.
0.6.180 — 2026-06-18
Changed
- Dependency maintenance. Routine dependency refresh bringing packages up to
their latest compatible releases, with no functional changes. Updated the
rich-text editor (
@tiptap/*to 3.27.0), AWS S3 SDK (@aws-sdk/*to 3.1071.0), the web framework (honoto 4.12.26), email transport (nodemailerto 9.0.1), the API reference UI (@scalar/hono-api-referenceto 0.11.4), and test tooling (happy-domto 20.10.6).bun auditreports no known vulnerabilities.
0.6.175 — 2026-06-18
Added
-
SyncroMSP Migration. Import your data from SyncroMSP into Ascent under Administration → SyncroMSP Migration — customers, leads, products, contacts, assets, tickets, estimates, invoices and appointments. Connect with your tenant subdomain and an API key (validated and stored encrypted at rest), then run a read-only, resumable, idempotent import — re-running updates existing records instead of duplicating them, and each run reports per-entity counts plus a log of anything skipped or flagged for review. Nothing is ever written back to SyncroMSP. Gated on the
migrationspermission (Owner and Admins by default). Mirrors the existing Autotask PSA migration. -
AI Chat Assistant — configuration (early access). Organization admins can now enable and configure an AI chat assistant under Administration → AI Chat Assistant. Choose an AI provider (Anthropic, OpenAI, OpenRouter, or a local/custom OpenAI-compatible endpoint) and either supply the provider details directly or reuse your existing AI Ticketing configuration. It is off by default and only available on plans that include it. The in-app chat experience is rolling out in stages — this first release covers enabling and configuring the assistant.
Changed
- The Dispatch Board is now a manager-level tool. Access is governed by a dedicated Dispatch permission (view and assign) instead of generic ticket permissions. Owners, Admins, and the built-in Help Desk Manager role keep full access by default; standard technicians no longer see the Dispatch nav item or reassign other technicians' work from the board. Administrators can grant the Dispatch permission to any custom role that needs it.
Fixed
- Scheduled report deliveries now appear in the Email Queue log. Running a scheduled report (either via Run now or on its recurring schedule) now routes the email through the normal outbound queue, so it shows up in Admin → Email Queue alongside every other message, with the report CSV attached and a real sent/failed status from the worker. Previously these sends bypassed the queue entirely and never appeared in the log.
- No more misleading "Report sent" when email isn't configured. If your organization has no email provider set up (no platform email and no SMTP/Microsoft 365 connection), Run now now reports the run as skipped / not sent instead of showing a green success toast for a delivery that never happened.
0.6.174 — 2026-06-18
Fixed
- Logged calls now appear in ticket history. When you log a call against a ticket, it is recorded on the ticket's Complete History timeline alongside replies and other changes, and shows up immediately without a page refresh. Previously the call was saved but never surfaced on the ticket.
- Tickets can be set back to Unassigned. Choosing "Unassigned" when editing a ticket now actually clears the assignee instead of silently keeping the previous one.
- SLA breaches are logged once, not repeatedly. A ticket that stays past its SLA no longer adds a duplicate "SLA breach" entry to its history on an ongoing basis — each breach type is recorded a single time.
0.6.173 — 2026-06-17
Fixed
- Custom dashboard layouts now match the built-in dashboard's styling. Widgets on a customized dashboard previously looked washed out compared to the default view. They now use the same card styling — a header icon, colored up/down trend indicators, and colored ticket priority badges — so a custom layout looks consistent with the default dashboard.
- Saving a custom dashboard no longer needs a page refresh. After saving a custom layout for the first time, the dashboard would briefly revert to the built-in view until you reloaded the page. Your saved layout (and a reset back to default) now takes effect immediately.
0.6.172 — 2026-06-17
Changed
- Admins can now run Autotask migrations. Importing data from Autotask was previously limited to the organization Owner, which left the importer hidden for everyone else. Admins now see the Autotask Migration tool and can run migrations by default. If you'd rather keep it tightly controlled, you can create a custom role that grants migration access to specific people and withhold it from other admins.
0.6.171 — 2026-06-17
Fixed
- View and restore previous Knowledge Base document versions. The document version history now lets you preview the content of any earlier version and restore the document to a previous version (restoring is available to users with edit access and is non-destructive — your current content is kept as a new version). Every version is listed, not just the five most recent.
- Health check reports the correct version. The
/api/healthendpoint previously returned a hardcoded version number that had drifted well behind the actual release. It now reports the running application version, so monitoring and uptime checks see the version that's actually deployed.
0.6.170 — 2026-06-17
Added
- Public changelog. This page now tracks what's new, changed, and fixed in Ascent. We'll keep it up to date as new versions ship so you can see what changed at a glance.