Breeze RMM v0.107.0 — the self-host fork release: BYO-signed agent packages that the server finally accepts, tenant variables, multi-currency billing, and a large correctness and security sweep.
This is the first public release since v0.105.1. v0.106.0 was tagged but never published as a GitHub Release (internal server-image build only), so everything below is the full
v0.105.1..v0.107.0delta for self-hosters.
Summary
- Self-host binaries work again — v0.105.x shipped unsigned (self-host edition) Windows agent binaries, but the API's trust allowlist only admitted the MSI, so boot-time binary sync aborted and every platform's agent download returned 404 for
BINARY_SOURCE=githubdeployments. Fixed (#3538), guarded against recurrence (#3761), and boot sync now pins to yourBREEZE_VERSIONinstead of/releases/latest(#3808 / #3742). - Tenant variables — define a value once (partner-wide or per org), reference it as
{{var.*}}in scripts, bind it to sourced script parameters, and have drift pinned into the approval digest. Secret delivery is built but still inert in this release (#3494, #3495, #3533, #3557, #3562, #3588). - Multi-currency waves 1–2 — curated 34-currency allowlist, per-org
currency_code, currency-aware rounding, and every invoice/quote/contract stamped from the org rather than defaulting to USD (#3794, #3804). - Customer self-service billing — public invoice pay link with Stripe checkout, quote accept lands on the invoice, quote decline with reason, and invoice re-send with a composer (#3790, #3805).
- Package-manager software library — winget and Homebrew install methods in the Software Library, with in-product search (#3587, #3611).
- Outlook technician persona — work tickets from the Outlook add-in: email context, link/create tickets, time logging, AI drafts (#3596).
- Breeze Workspace merged into the monorepo as a built-in extension under
ee/, off by default (#3455, #3479). - Security — two High fixes needing attention: the global patch catalog was writable by any enrolled agent, which could silently suppress patching in other tenants (#3556, #3645), and restricted partner users could mint partner-wide credentials or rotate another admin's API key (#3647). Plus Medium hardening across CIS scan authorization and inbound-email ticket matching (#3643), alert-template visibility (#3642), Go 1.26.6 and dependency CVE bumps. See Security below — all of it is live in v0.105.1.
- Fixed — SSO login could never complete in the web app (#3702), agent uninstall reported success without removing anything (#3670), EXE installers hung for 30 minutes (#3584), a deadlock on re-enrollment (#3739),
/sessions/livepool starvation (#3764), and Prometheus HTTP/heartbeat metrics that were never emitted (#3763).
Added
- Tenant variables (Settings → Variables) — partner-wide or org-scoped values, encrypted at rest, with
variables:read/variables:managepermissions; org > partner precedence (#3494). {{var.*}}in scripts — resolved per device at dispatch (#3495); sourced script parameters bound to tenant variables (#3533).- Secret delivery machinery for script variables — server-side sealing and a per-device
secretEnvcapability flag (#3557), agent-side decode/gate/redact (#3562). Secrets are still refused at script save and at dispatch in this release; activation is a follow-up. - Approval digest pins tenant-variable and parameter drift — an approved
run_scriptaction-intent now fails closed if a parameter is rebound or a referenced variable changes between approval and release (#3588). - Multi-currency foundations —
supported_currenciesallowlist,organizations.currency_code, shared minor-unit/rounding helpers, JPY/CLP-correct totals (#3794). - Document currency correctness — invoices, quotes and contracts stamp currency from the org; cross-org clone/retarget blocked on mismatch;
POST /{quotes,invoices,contracts}/:id/currencyto change a draft's currency; double-issue and over-payment races closed (#3804). - Public invoice pay link — opaque, hashed token; portal-hosted customer page with PDF and deposit-aware Stripe checkout; MSP copy/reset-link actions; "Pay online" CTA in email and PDF (#3805).
- Quote accept → invoice, quote decline with reason — accept lands on the durable invoice page and optionally auto-emails it (new partner toggle, default on); decline notifies the MSP and offers a revise path (#3805).
- Invoice re-send with composer —
POST /invoices/:id/resendplus a To/CC/subject/note/attach-PDF dialog mirroring the quote composer (#3790). Quote re-send, share-link copy, and "sent to" visibility (#3501). - Package-manager software library — winget / Homebrew install methods,
import-packageone-shot, manager-aware deployment wizard (Latest/Exact, OS-coverage split), agent ensure-present (#3587); winget index freshness signal and partner-erasure FK fixes (#3611). - Software deploy UX — explicit customer context in the wizard, partner-wide packages, version editing, MSI arg auto-fill, upload greyed out without S3 (#3575); installer type recorded for URL-created packages (#3571).
- Per-user winget updates — the agent runs a second best-effort
winget upgrade --scope userpass in the interactive user's session so Chrome/Zoom/Slack-style per-user installs finally show up; newdevice_patches.scope(#3558). - Outlook technician persona — email context card, link/create ticket from an email with AI prefill, time widget, technician bind flow; new
ticket_email_linksandoffice_addin_user_bindingstables (#3596). - Proposal presentation system — partner document themes and fonts, themed PDF renderer, table and callout blocks with edit-in-place, MCP contract (#3526, #3535, #3539, #3545, #3631).
- Script editor test loop — pin a test device, Save & Test Run, read output in the editor; new tier-1
get_script_executionAI tool (#3582). - Analytics page rebuilt on the dashboard design system with honest load failures (#3513).
- Regional setup-wizard step for language, currency and time zone (#3628).
- Turkish (tr-TR) localization (#3497).
showTrayIconsetting for Breeze Assist in the helper policy tab (#3629).- Breeze Workspace as a built-in
ee/extension, enabled withBREEZE_WORKSPACE_ENABLED=true(#3455, #3479); the two dead runtime-bundle delivery paths are retired (#3488). - Recidivist-endpoint abuse signal (
rmm.recidivist_endpoint) correlating ScreenConnect GUIDs, hostnames and egress IPs against a persistent corpus (#3567). - Pending-account booking link — optional
PENDING_ACCOUNT_MEETING_URL/PENDING_ACCOUNT_MEETING_LABELso the payment wall isn't a dead end (#3771). - Mobile — Tickets tab (queue, detail, comments, status changes) (#3716); browsable devices list (#3720); self-hosted builds can add their own associated domain for passkey/autofill (#3732); iOS app lock survives process death (#3746).
- Docs — macOS permissions (PPPC) page, fleet-hygiene page, self-hosted inbound email-to-ticket setup (#3586), switchable Windows signing documented (#3781).
Improved
- Boot-time binary sync pinned to the server's own version —
BINARY_SOURCE=githubno longer fetches/releases/latest, so a self-hoster's fleet moves when they upgrade, not when we publish (#3808, closes #3742). - Release trust allowlist guarded against pipeline drift — CI fails when the release workflow and the API's asset allowlist disagree (#3761).
- Agent-version registration fails loudly —
POST /agent-versionsreturns 422 andpromotereturns 409 for releases missing a signed manifest, instead of thousands of downstream 409s (#3661). - Prometheus metrics actually emitted —
metricsMiddlewarewas never mounted;http_requests_total,http_request_duration_secondsandagent_heartbeat_totalnow populate (#3763). - Inbound email-to-ticket toggle enforced server-side — the switch was display-only; it now gates ingestion, with a one-time repair for partners whose flag was falsely
falsebut who rely on inbound mail (#3606);TICKETS_INBOUND_DOMAINnamed in the settings hint (#3627). - Manual software remediation backed by a durable single-use authorization rather than a forgeable job flag (#3585); remediation authorization rows pruned (#3630).
- Agent inventory/heartbeat ingest body limit carved out at 5 MB (#3527); quote/catalog/avatar/contract uploads get their own limits (#3511); body-limit rejections now have server-side telemetry (#3660).
- HP/Lenovo warranty lookups rate-limited at the request boundary (#3576).
- Offset pagination gets a unique tiebreaker so rows written in one transaction no longer duplicate or vanish across pages (#3664).
- MCP output — truncated arrays marked in-band (#3580),
get_quoteblocks paginated (#3568). - Maintenance-window inert notify fields retired (#3668);
avProductspersisted onsecurity_status(#3669). - Partner admins can create and manage org-scoped roles (#3577); fleet (All-orgs) view can create DNS integrations and device groups (#3563).
- Web polish — static device-group membership editable again (#3626), device-group edit 404 (#3564), notification-channel test verdict in text (#3733), per-org device count on the org card (#3734), locale change no longer drops a live VNC session (#3736), bulk vulnerability actions batched to the server cap (#3709), What's New splash shows on the upgrade that introduces it (#3650), plus two pre-release polish batches (#3633, #3635).
- Dashboards stop claiming "all clear" with zero devices (#3536, #3651) and show "—" instead of fabricated zeros on a 500 (#3566).
- Self-host first-boot —
.env.exampleno longer pins a version whose images were never published,TURN_SECRETno longer blocks startup for deployments that don't use TURN (now a file-backed Compose secret that fails closed only when theturnprofile is on), placeholder key detection (#3717);.env.exampleno longer ships a localhostDATABASE_URL_APPthat crashed the initial seed (#3728). - Viewer AppImage names
libfuse2t64for Debian 13 / Ubuntu 24.04+ (#3512). MSI always writes an install log (#3634). - Go toolchain 1.26.6 (#3523); macOS TCC self-heal writes retired in favour of MDM PPPC guidance (#3463); Full Disk Access probed in-process (#3460).
Fixed
- SSO login could not complete — the web app never consumed the
#ssoCodefragment; also fixes the enforce-SSO lockout arrival state and a bootstrap hang on non-JSON/meresponses (#3702). - Agent uninstall reported success without removing anything (#3670). EXE installers hung until the 30-minute timeout — missing
WaitDelay(#3584). - Deadlock (40P01) between agent network inventory and re-enrollment — inverted lock ordering (#3739).
/sessions/liveheld a pooled connection across a 10 s agent round-trip, starving the pool (#3764).- Breeze Agent inventory version tracked the MSI, not the running agent (#3663). Defender claimed a third-party AV's real-time protection (#3662).
- AI-generated PowerShell failed with Unicode parse errors — status glyphs normalized (#3574, #3583).
- Script result arriving after the 60 s wait no longer loses the agent's real output (#3655); script executions page showed no output (#3582); script test-run recovery and stale device pin (#3605).
- Partner-wide config policies were invisible to org-scoped effective-config resolution (#3665).
- Patch version read through
device_patches.available_version, so per-device version pins and block rules use the tenant's own observation (#3656); winget-prefixed patch ids matched against the bare catalog id (#3565); "Installed (date unknown)" for nullinstalledAt(#3590). z.coerce.boolean()query-param footgun —?flag=falsewas read astrueat 8 sites / 9 params (#3528). Nullable monitoring watch fields acceptnull(#3509).- Rich text —
<table>survives the sanitizer (#3671); stripped markup is reported instead of a silent 200 (#3667). - Quote/proposal PDFs —
{{client.name}}on drafts and full-bleed cover background (#3489), table row-height measurement and header inline marks (#3555),send_email_reasonpersisted on the direct send path (#3507), new quotes default to the partner's currency rather than USD (#3572), "/ea" unit translated in tr-TR and es-419 (#3625). - Remediation target timeout cancels the queued command (#3570);
fleet_remediation_runsroll-up counts fresh at chunk end (#3657). - Network payload — one bad VPN entry no longer drops the whole payload (#3573); VPN on/off state and macOS multi-VPN attribution (#3549); SNMP octet strings that aren't safe text are hex-encoded (#3765); gopsutil darwin netstat panic survived (#3514).
- Inbound email reported as unconfigured on the M365-only path (#3652). Bundle import treats partner-wide name matches as conflicts (#3659).
- Backup — swallowed vault failures surfaced with real status (#3579); SSRF guard adopted on backup probes (#3645).
- Mobile — CSRF token echoed so the session can refresh (#3726); device walk uses a page size the server honours (#3757); Systems and Tickets no longer present partial state as complete (#3769, #3719); Expo SDK 57 dependency range (#3747).
- Workspace rejects
local_profilesources that carry a crawl device (#3686). - OneDrive Helper polish batch (#3636); billing punch-list a11y, toast anchor and PDF wordmark (#3638); i18n no longer ships API route paths as translatable values (#3666); device picker page cap and silent fleet-load failure (#3610); confirm-gated single-device reboot from the devices list (#3703, #3706).
Security
Every issue below was already present in v0.105.1, the last published release — so self-hosters running that version are affected until they upgrade. Severities are stated as verified against the shipped code, not as originally triaged.
Security — action required
Two High-severity authorization defects. Both cross a tenant boundary; neither is remotely exploitable without either an enrolled agent or an authenticated partner account.
- Any enrolled agent could overwrite the shared patch catalog that every tenant's approval logic reads (#3556, #3645). The
patchestable is global with no tenant column, and agent-reportedseverity,package_id,versionand display fields were written straight onto the shared row. Downgrading a critical patch's severity pushes it outside other tenants' auto-approval and ring policies, so it is silently never installed; overwritingpackage_idcorrupts the CVE-enrichment join and mis-attributes vulnerability findings. Reachable by anyone controlling one managed endpoint in any tenant — on hosted deployments with self-service signup, that includes a newly created trial tenant. This is the one issue here that crosses the partner boundary. We could not establish a path to arbitrary package installation:install_patchescarries only{id, source, externalId, title}and does not dispatch onpackage_id, so this is an integrity issue, not RCE. - Partner users with restricted org access could mint partner-wide credentials and rotate other admins' API keys (#3647). Six write sites gated on the caller's
scopebut never on the partner-wide capability. The severe case is partner-wide service principals: a durable machine credential with access to every org under the MSP, including orgs created later — a lasting privilege escalation for a user explicitly limited to selected orgs. Separately,POST /api-keys/:id/rotateresolved the key by id alone and returned the new plaintext, letting a lesser admin take over a more-privileged user's key. Org-boundary crossing within one partner; no cross-partner path.
Both are fixed in 0.107.0 with no workaround; upgrading is the remediation. Advisories will be published once hosted rollout completes, per our disclosure policy.
Security — hardening
- CIS scan fan-out and ticket-email injection (#3643) — Medium. Every authorization predicate on
POST /cis/scansat inside anif (deviceIds)branch, so omittingdeviceIdslet an org user withdevices:writedispatch a scan across sibling orgs under the same partner; scan results are stamped with the device's own org, so no data returned to the caller. Separately, the inbound-email subject token[T-YYYY-NNNN]was matched on partner + ticket number with no org or sender binding, so anyone emailing the MSP's support address could append a public comment to another org's ticket and reopen it — a write with no read-back, but a convincing phishing channel since the technician sees it as a genuine customer reply. Requires email-to-ticket to be configured. - Partner-wide alert-template predicate leaked cross-org templates to partner users with restricted org access (#3642) — Low/Medium. MSP-authored template names, descriptions and conditions only; the auto-created
is_built_inrows carry constant text, so no customer data is exposed.alert_templatesnow carry a one-owner constraint and partner index. - Enforcement-arming AI policy tools gated behind Tier 3 approval (#3561); AI software-policy writes audited and remediation gated on policy arming (#3548). Intra-tenant containment and audit, not a boundary break.
- SSRF guard adopted on backup storage probes (#3645) — an authenticated org admin could point an S3 endpoint at link-local or RFC1918 addresses.
- AI agent-version pins resolved in a real system context (#3532).
http/httpsallowlist for partner website URLs (#3518). - Dependencies — Go 1.26.6 clears six stdlib advisories (#3523);
nanoid >= 3.3.18for CVE-2026-67213 (#3510);deepmerge-ts8.0.1 for CVE-2026-40345 (#3718); Gox/net,x/text,x/mod, AWS SDK andgoogle.golang.org/apibumps. - Security policy — advisory publication and self-hoster disclosure guidance are now enforced in the release process (#3644).
- Windows signing provider is now switchable (Azure | SSL.com) with a shared verification step that validates signer, timestamp and publisher subject regardless of CA (#3762, #3781, #3807).
Self-Hosting / Upgrade Notes
Upgrade: bump BREEZE_VERSION to 0.107.0 in .env, then docker compose pull api web portal && docker compose up -d. Include portal — the public invoice page and quote accept/decline flows live there and an un-rolled portal will serve the old code while /health reports 0.107.0.
Database — 26 migrations, all idempotent and applied automatically by the API's autoMigrate at boot. None rewrite a hot table. Worth knowing:
2026-08-27-b-org-currency-and-fks.sqlbackfillsorganizations.currency_codefrom the partner (logged withRAISE WARNINGcounts) and upper-cases existingcurrency_codevalues onpartners/invoices/quotes/contracts;2026-08-28-…then drops the'USD'column default on those three tables. Normal-sized billing tables — seconds, not minutes.2026-08-14-device-patch-install-scope.sqladds a nullablescopecolumn and a small partial index (WHERE scope = 'user') todevice_patches. PlainCREATE INDEX, so it takes a brief share lock on the table; the partial predicate matches zero existing rows, so it is fast even on large fleets.2026-08-24-inbound-enabled-backfill.sqlrepairsticketing.inbound.enabledfrom a spuriousfalsetotrueonly for partners who have actually received inbound mail — see the behaviour note below.2026-08-25-alert-templates-one-owner.sqlbackfills owner columns onalert_templatesand adds the XOR constraint.2026-08-22-drop-extension-org-installs.sqldrops theextension_org_installstable (its only readers/writers were the retired delivery paths).2026-08-11-variables-permissions.sqlgrantsvariables:readandvariables:manageto every existing system Org Admin role.- The rest create new tables (
tenant_variables,supported_currencies,software_install_methods,winget_package_index,software_remediation_requests,ticket_email_links,office_addin_user_bindings,abuse_endpoint_fingerprints) or add nullable columns.
No new required environment variables. New optional ones:
BREEZE_WORKSPACE_ENABLED(defaultfalse) — loads the built-in Workspace extension (ee/, Breeze Commercial License).PENDING_ACCOUNT_MEETING_URL/PENDING_ACCOUNT_MEETING_LABEL— booking link on the pending-account screen. Map them explicitly in theapiserviceenvironment:block;.envalone is not interpolated (#3771).TICKETS_INBOUND_DOMAINandMAILGUN_INBOUND_SIGNING_KEYnow appear in.env.example— both existed before; only needed for inbound email-to-ticket.TRUST_CF_CONNECTING_IP,M365_GRAPH_ACTIONS_TOOLS_ENABLEDandAPP_ENCRYPTION_KEY_IDare now schema-declared and format-checked (a typo refuses boot instead of silently reading as off).APP_ENCRYPTION_KEY_IDis required only whenM365_GRAPH_ACTIONS_TOOLS_ENABLED=true, as before (#3515).
⚠️ Windows agent packages are unsigned in the public release — bring your own certificate. Since v0.105.0 the public pipeline builds the self-host edition of the agent family and does not Authenticode-sign breeze-agent-windows-amd64.exe, breeze-agent.msi, or the backup/watchdog/user-helper exes (the -unsigned assets are byte-for-byte copies published as signing inputs). Sign them with your own certificate using the breeze-selfhost-signing template — guide: https://docs.breezermm.com/deploy/sign-your-own-packages/ — and point BINARY_GITHUB_REPOSITORY at your signed re-release. Unsigned binaries install and run, but Windows will show SmartScreen warnings until you sign them. What is new in 0.107.0 for this path:
- The API now accepts the unsigned self-host exes. On v0.105.x the trust allowlist only admitted the MSI, so boot sync aborted and agent downloads returned 404 on every platform for
BINARY_SOURCE=githubdeployments (#3538). The allowlist is exact-filename and edition-gated: an unsigned asset labeledhosted, or with no edition claim, is still refused. A once-per-asset warning is logged when an unsigned binary is served. - A CI guard keeps the allowlist in lockstep with the release workflow (#3761), and registering a release that lacks a signed artifact manifest now fails with a clear 422/409 instead of a silent no-op (#3661).
- Boot-time binary sync is pinned to
releases/tags/v<BREEZE_VERSION>(orBINARY_VERSIONif set). WithAGENT_AUTO_PROMOTEleft at its defaulttrue, restarting the API after a newer GitHub release no longer promotes your fleet to a version the download redirect cannot serve (the #3742 checksum-mismatch loop). If your pinned release is not published on GitHub, boot sync logs a loud[binarySync]error telling you to setBINARY_VERSIONto the last published release — it does not fall back to/releases/latest, and ingithubmode the API still starts (#3808). - Viewer and Helper installers are still signed by LanternOps, now with an SSL.com OV certificate (
O=LANTERNOPS LLC) rather than Azure Artifact Signing (#3762, #3781). A new certificate means SmartScreen reputation starts from zero — expect "unrecognized app" prompts on the Viewer/Helper MSIs for a while after this release. - macOS agent
.pkgs and Linux binaries are unchanged.
Agent fleet: the agent binaries changed materially in this release (uninstall, EXE installer hang, per-user winget, VPN state, SNMP, PowerShell encoding, secret-variable gating). With AGENT_AUTO_PROMOTE=true (default) the server registers 0.107.0 as latest at boot and agents self-update; with it off, promote the version from the agent-versions admin UI once you have signed and re-released the Windows packages.
Behaviour and default changes:
- Inbound email-to-ticket toggle is now enforced. Previously display-only. The migration flips a stored
falsetotrueonly for partners who have actually received inbound mail; a partner withfalseand no observed mail keeps it and inbound mail is now ignored (statusignored). Check Settings → Ticketing if you rely on inbound mail (#3606). - Approved-but-unreleased
run_scriptaction-intents must be re-approved. The approval digest moved to av:2envelope that pins tenant-variable and parameter references; v1 digests failcontent_changedat release by design. Count them before upgrading:SELECT count(*) FROM action_intents WHERE status='approved' AND action_name='run_script';(#3588). - Billing documents stamp currency from the organization, not the partner, and a draft's currency cannot be edited via PATCH — use the new
/currencyendpoint. Existing documents keep their (now upper-cased) currency (#3804). New quotes default to the partner currency, not USD (#3572). - Secret tenant variables are not delivered yet. Variables marked secret are refused at script save/import (400) and at dispatch; activation lands in a follow-up release (#3557, #3562, #3588).
- Boolean query params are now honoured —
?x=falseused to be parsed astrueat 8 endpoints (#3528).GET /software/catalogversionCountwas silently 0 and now reports real counts (#3587). - Global patch-catalog rows are no longer writable by agent scans; severity/version observations live on the tenant row (#3645). Prometheus HTTP and heartbeat series start populating — alert rules that assumed their absence will now evaluate (#3763).
coturn(turnprofile only) readsTURN_SECRETfrom a Compose secret and refuses to start when it is empty; deployments without the profile are no longer blocked by the missing variable (#3717).- Workspace is compiled into the API image but dormant unless
BREEZE_WORKSPACE_ENABLED=true; the runtime-bundle and source-directory extension loaders are removed (#3455, #3488).
No breaking changes beyond the items above: no API routes removed, no required env vars added, no manual SQL. The one thing that requires action from a self-hoster with Windows endpoints is the BYO-signing step, and that has been the case since v0.105.0 — 0.107.0 is the release where it actually works end to end.
Full Changelog: v0.105.1...v0.107.0
What's Changed
- fix(deps): override deepmerge-ts to 8.0.1 for CVE-2026-40345 by @ToddHebebrand in #3718
- fix(selfhost): unbreak first-boot — stale image pin, TURN_SECRET gate, placeholder key by @ToddHebebrand in #3717
- ci: dispatch-only hosted server-image builds (hosted-images.yml) by @ToddHebebrand in #3741
- fix(mobile): make the iOS app lock survive process death by @ToddHebebrand in #3746
- fix(mobile): pull dependencies back into the Expo SDK 57 supported range by @ToddHebebrand in #3747
- chore(deps): bump golang.org/x/mod from 0.38.0 to 0.40.0 in /agent by @dependabot[bot] in #3714
- chore(deps): bump the aws-sdk group in /agent with 5 updates by @dependabot[bot] in #3711
- chore(deps): bump golang.org/x/text from 0.40.0 to 0.41.0 in /agent by @dependabot[bot] in #3712
- chore(deps): bump google.golang.org/api from 0.292.0 to 0.293.0 in /agent by @dependabot[bot] in #3715
- chore(deps): bump futures-util from 0.3.33 to 0.3.34 in /apps/helper/src-tauri by @dependabot[bot] in #3737
- chore(deps): bump whoami from 2.1.2 to 2.1.3 in /apps/helper/src-tauri by @dependabot[bot] in #3738
- chore(deps): bump swatinem/rust-cache from a45951ff880207c249adf57334cf2e9bd81d6e1e to f0d9c3887740aee45f6153b24b3a6b815192ec16 by @dependabot[bot] in #3722
- chore(deps): bump golang.org/x/net from 0.57.0 to 0.58.0 in /agent by @dependabot[bot] in #3713
- ci: build the validated commit in hosted-images, not the tag again by @bdunncompany in #3743
- refactor(web): hoist the #3698 confirm constants and cover the grid-card path by @bdunncompany in #3706
- fix(ci): stop main-red-alert turning a green CI run red on a transient API error by @bdunncompany in #3735
- fix(ci): give the Tauri apt step per-command deadlines so a stall can retry by @bdunncompany in #3731
- fix(web): state the notification channel test verdict in text, not just an icon by @bdunncompany in #3733
- fix(api,web): return a per-org device count so the org card stops rendering " devices" by @bdunncompany in #3734
- fix(web): a locale change no longer drops a live VNC session by @bdunncompany in #3736
- feat(mobile): Tickets tab — queue, detail, comment and status change (#3206) by @bdunncompany in #3716
- fix(mobile): surface real issues on Systems — active page, partial-failure tolerance, empty state by @bdunncompany in #3719
- feat(mobile): browsable devices list, and stop a slow acknowledge reading as failure by @bdunncompany in #3720
- fix(web): batch bulk vulnerability actions to the server's 200-id cap (#3694) by @bdunncompany in #3709
- feat(mobile): let a self-hosted build add its own associated domain by @bdunncompany in #3732
- docs(mobile): correct the associated-domains "returned verbatim" claim by @bdunncompany in #3751
- fix(ci): bound the Tauri apt step so it cannot relocate the job timeout by @bdunncompany in #3756
- fix(mobile): the device walk asks for a page size the server honours by @bdunncompany in #3757
- docs: v0.106.0 release sweep + 2026-08-17 UI QA log by @ToddHebebrand in #3707
- docs: retire the plans-folder work queue; wire feature-lifecycle tracking by @ToddHebebrand in #3745
- fix(api): deadlock on agent network inventory vs re-enrollment (40P01) by @ToddHebebrand in #3739
- fix(selfhost): stop .env.example shipping a localhost DATABASE_URL_APP by @ToddHebebrand in #3728
- fix(api): mount metricsMiddleware — http_requests_total and agent_heartbeat_total emit nothing in production by @ToddHebebrand in #3763
- fix(api): stop /sessions/live holding a pooled connection across a 10s agent round-trip by @ToddHebebrand in #3764
- ci: guard the release trust allowlist against pipeline drift (#3504) by @ToddHebebrand in #3761
- ci(release): make the Windows signing CA switchable (Azure | SSL.com) by @ToddHebebrand in #3762
- feat(web,api): booking link on the pending-account screen so the payment wall isn't a dead end by @ToddHebebrand in #3771
- docs(agents): fix AGENTS.md saying Codex orchestrates work Codex handles (#3498) by @ToddHebebrand in #3766
- docs: rescue 18 plan/spec docs that existed only in local worktrees by @ToddHebebrand in #3767
- fix(agent): hex-encode SNMP octet strings that aren't safe text; stop trim-order data loss by @ToddHebebrand in #3765
- fix(mobile): echo the server's CSRF token so the session can actually refresh (#3723) by @bdunncompany in #3726
- fix(mobile): stop Systems and Tickets presenting partial state as complete (#3753) by @bdunncompany in #3769
- feat: multi-currency wave 1 — currency foundations by @ToddHebebrand in #3794
- ci(release): add switchable SSL.com Windows signing by @ToddHebebrand in #3781
- feat: invoice re-send with customer-email composer (quote parity) by @ToddHebebrand in #3790
- feat(api,portal,web): public invoice pay link + quote accept/decline completion (waves 2-5 of #3784) by @ToddHebebrand in #3805
- ci(release): keep package-windows-updater alive when the non-selected signing provider job is skipped by @ToddHebebrand in #3807
- feat: multi-currency wave 2 — document correctness (#3774) by @ToddHebebrand in #3804
- fix(api): pin boot-time binary sync to the server's own release, not /releases/latest by @ToddHebebrand in #3808
Full Changelog: v0.106.0...v0.107.0