diff --git a/apps/docs/src/content/docs/deploy/environment.mdx b/apps/docs/src/content/docs/deploy/environment.mdx index 977d1996dd..2bfe101a46 100644 --- a/apps/docs/src/content/docs/deploy/environment.mdx +++ b/apps/docs/src/content/docs/deploy/environment.mdx @@ -262,6 +262,20 @@ Two rate-limit tiers protect the API. The generic per-user limit covers logged-i These variables are optional. When unset, the C2C connection wizard falls back to manual credential entry (Client ID, Secret, Tenant ID). Setting both enables a streamlined "Grant Access" button that redirects to Microsoft's admin consent flow. +## Ticket Mailbox (M365 email-to-ticket) + +These enable partners to connect a Microsoft 365 shared support mailbox so customer email becomes tickets and replies are sent from that mailbox. This is a **separate** Azure app registration from the Cloud-to-Cloud Backup app above. + +| Variable | Default | Description | +|---|---|---| +| `TICKET_MAILBOX_M365_CLIENT_ID` | — | Azure AD app (client) ID for the **Breeze Ticketing** app. When set with the secret, the Microsoft 365 mailbox card appears under Settings → Ticketing → Inbound Email. | +| `TICKET_MAILBOX_M365_CLIENT_SECRET` | — | Client secret for the Breeze Ticketing Azure app. | +| `PUBLIC_TICKET_MAILBOX_APP_ID` | — | Build-time, browser-exposed app id shown in the Application Access Policy PowerShell snippet on the settings card. Safe to publish -- it is the app's public client id. | + + + ## Docker Deployment | Variable | Default | Description | diff --git a/apps/docs/src/content/docs/features/configuration-policies.mdx b/apps/docs/src/content/docs/features/configuration-policies.mdx index fa93dbcfca..fdb7600afb 100644 --- a/apps/docs/src/content/docs/features/configuration-policies.mdx +++ b/apps/docs/src/content/docs/features/configuration-policies.mdx @@ -42,6 +42,7 @@ A policy can bundle multiple feature types: | **Monitoring** | Check configuration | | **Automation** | Event triggers, cron schedules, bulk actions | | **Privileged Access** | Windows UAC elevation prompt capture for [privileged access management](/features/pam/) | +| **Vulnerability Scanning** | Turns on daily CVE correlation for the scope (off by default) -- see [vulnerability management](/features/vulnerability-management/) | Each feature can be configured in one of two modes: @@ -154,6 +155,12 @@ When a backup feature is linked to a configuration policy, the schedule, retenti Configure security policy settings for **Security**; check intervals and targets for **Monitoring**; and event triggers, cron schedules, and action chains for **Automation**. +### Vulnerability Scanning + +The **Vulnerability** feature is a single on/off toggle that controls whether the devices in the policy's scope are scanned for CVEs. It is configured **inline** (the on/off state lives in the policy) and is **off by default** -- a device with no vulnerability policy is never scanned, and its Vulnerabilities tab stays empty. + +Open the policy's **Vulnerability** tab, switch **Enable vulnerability scanning** on, save, and assign the policy. Because resolution is closest-wins, a device- or group-level setting of *off* overrides an organization-wide *on*. Once a scope is enabled, Breeze correlates its software and OS inventory against the CVE feeds once a day. If a policy exists but no device resolves to *on*, the daily job is simply a no-op -- it never falls back to scanning everything. The findings themselves are reviewed and acted on in [Vulnerability Management](/features/vulnerability-management/), not on this tab. + ## Assigning a policy @@ -196,6 +203,7 @@ Examples of shipped defaults: |---------|---------------| | Remote Access | Active (on) | | PAM / UAC capture | Not enforced (off by default) | +| Vulnerability Scanning | Not enforced (off by default) | Each row on the Defaults page includes a **Create override policy** shortcut that opens the policy editor pre-configured for that feature, so you can add a partner- or org-level override without navigating away. @@ -279,7 +287,7 @@ All paths are relative to `/api/v1`. When creating a policy, set `ownerScope` to `organization` (the default) or `partner`. With `ownerScope: "partner"` the policy is owned partner-wide and any supplied `orgId` is ignored — the partner is always derived from the caller's own token, never trusted from the request body. Creating a partner-wide policy requires partner scope (a `403` is returned otherwise). When assigning a partner-wide policy, use `level: "partner"`; the target is resolved from the caller's own partner, so no `targetId` is required. -When calling the features endpoints, the `featureType` value must be one of: `patch`, `alert_rule`, `maintenance`, `compliance`, `backup`, `security`, `monitoring`, `automation`, `pam`. +When calling the features endpoints, the `featureType` value must be one of: `patch`, `alert_rule`, `maintenance`, `compliance`, `backup`, `security`, `monitoring`, `automation`, `pam`, `vulnerability`. ## Troubleshooting diff --git a/apps/docs/src/content/docs/features/integrations.mdx b/apps/docs/src/content/docs/features/integrations.mdx index 17181424cc..862bf72cde 100644 --- a/apps/docs/src/content/docs/features/integrations.mdx +++ b/apps/docs/src/content/docs/features/integrations.mdx @@ -24,6 +24,7 @@ Breeze supports three categories of integrations, each served by a dedicated set | **Monitoring** | External monitoring endpoints | Forward device telemetry and health data to third-party observability platforms | | **Accounting** | QuickBooks Online | Connect your accounting platform (see [Accounting](#accounting-integrations)) | | **Distributors** | Pax8, TD SYNNEX | Sync licenses and pull live distributor pricing into your [Product Catalog](/features/product-catalog/) | +| **Network** | UniFi (Ubiquiti Site Manager) | Discover UniFi fleet inventory and WAN health, with optional agent-collected deep telemetry (see [UniFi Network](#unifi-network)) | +### Connecting a Microsoft 365 support mailbox + +Instead of forwarding to your Breeze inbound address, you can connect a Microsoft 365 **shared support mailbox** (for example `support@yourmsp.com`) directly. Customer email to that mailbox becomes tickets, and your public replies are sent back **from that same mailbox** -- with no MX record or forwarding-rule changes. Breeze uses an app-only connection your Microsoft Global Administrator consents to once, so it survives staff turnover (there's no personal login tied to the mailbox). Set it up on the **Microsoft 365 support mailbox** card under **Settings → Ticketing → Inbound Email**. + + + +1. Enter the shared mailbox address and an optional display name, then click **Connect**. Breeze redirects you to Microsoft, where a **Global Administrator** grants one-time admin consent. +2. Scope Breeze's access to **only** this mailbox. The card shows an exact **Application Access Policy** snippet (a `New-DistributionGroup` plus `New-ApplicationAccessPolicy` pair) to run in Exchange Online PowerShell as a tenant admin. Until you do this, the connection shows **Needs attention**, because the underlying mail permission is tenant-wide by default. +3. Click **Re-test**. Once Breeze can read the mailbox, the status flips to **Connected**. + + + +Once connected, Breeze polls the mailbox every minute or two, turns new messages into tickets (threading and the review queue work exactly as above), and marks each handled message as read so your team can see what's been picked up. Only mail that arrives after you connect is ticketed -- existing inbox history is not imported. Public replies go out **from the support address** and thread natively in the customer's mailbox; internal notes and technician notifications are unaffected. You can connect more than one mailbox (for example `support@` and `billing@`). **Disconnect** stops polling immediately; to fully remove access, also revoke the app's consent in your Microsoft Entra admin center. + + + ## Categories and SLAs Go to **Settings > Ticketing** to manage ticket categories. diff --git a/apps/docs/src/content/docs/features/vulnerability-management.mdx b/apps/docs/src/content/docs/features/vulnerability-management.mdx index fc6863a124..ea591a0e32 100644 --- a/apps/docs/src/content/docs/features/vulnerability-management.mdx +++ b/apps/docs/src/content/docs/features/vulnerability-management.mdx @@ -7,12 +7,30 @@ sidebar: import { Aside, Steps } from '@astrojs/starlight/components'; -Vulnerability Management finds the known security flaws (CVEs) affecting the devices you manage, ranks them by how much they actually matter, and gives you a clear path to act on each one -- deploy a patch, formally accept the risk for a set period, or record a compensating control. It cross-references the software and operating-system versions Breeze already inventories against authoritative vulnerability feeds, so there is nothing to install or scan separately: enrolled devices start producing findings automatically. +Vulnerability Management finds the known security flaws (CVEs) affecting the devices you manage, ranks them by how much they actually matter, and gives you a clear path to act on each one -- deploy a patch, formally accept the risk for a set period, or record a compensating control. It cross-references the software and operating-system versions Breeze already inventories against authoritative vulnerability feeds, so there is nothing to install or scan separately -- but scanning is **opt-in per scope and off by default**, so you turn it on for the organizations you want covered (see [Enabling vulnerability scanning](#enabling-vulnerability-scanning)). This page is the operator's guide. Fixes are usually deployed through [Patch Management](/features/patch-management/), and vulnerability posture also feeds the [Security overview](/security/overview/) and the [AI agent](/features/ai/). Open **Vulnerabilities** from the Security section of the left sidebar for the fleet-wide view, or open any device and select its **Vulnerabilities** tab for a single machine. +## Enabling vulnerability scanning + +Vulnerability scanning is **off by default**. A device only produces findings once it's covered by a configuration policy that turns scanning on, so you can roll the feature out organization by organization instead of flooding every customer at once. + + + +1. Go to **Configuration → Policies** and open (or create) a policy. +2. On the **Vulnerability** feature tab, switch **Enable vulnerability scanning** on, and save. +3. Assign the policy to the scope you want covered -- a partner, organization, site, device group, or individual device. + + + +Coverage follows the same closest-wins inheritance as every other policy feature: a device- or group-level setting of *off* overrides an organization-wide *on*, so you can enable scanning broadly and carve out exceptions. Once a scope is enabled, Breeze correlates its inventory against the CVE feeds **once a day** (around 13:00 UTC, after the feeds refresh) and populates the findings below. Platform administrators can also trigger a correlation pass on demand. + + + ## What you can do - See every open CVE across your fleet, ranked by risk, with the number of affected devices. @@ -62,7 +80,7 @@ Both keep a finding off your open list, but they mean different things: ## Where the data comes from -Breeze pulls vulnerability intelligence from several authoritative feeds and refreshes them on a schedule -- no configuration required: +Breeze pulls vulnerability intelligence from several authoritative feeds and refreshes them on a schedule. The feeds themselves need no setup -- they are always kept current; you only choose which scopes to scan against them (see [Enabling vulnerability scanning](#enabling-vulnerability-scanning)). The sources: | Source | Used for | |---|---| diff --git a/scripts/docs-review/last-reviewed.json b/scripts/docs-review/last-reviewed.json index 780b860632..7933c9e817 100644 --- a/scripts/docs-review/last-reviewed.json +++ b/scripts/docs-review/last-reviewed.json @@ -1,5 +1,5 @@ { - "lastReviewedRef": "v0.86.0", - "reviewedAt": "2026-06-28", - "notes": "Bumped after v0.85.0..v0.86.0 sweep (release 0.86.0). Single doc edit: features/reliability.mdx — added v0.86.0 macOS/Linux server-side classification de-junk notes (isGenuineHardwareError gate + downweighted app_crash, #2005) to the macOS and Linux TabItems and extended the re-baseline Aside to note macOS/Linux scores shift on SERVER upgrade regardless of agent version. mapping.json +2 entries: agent/internal/collectors/reliability*.go -> reliability.mdx, DeviceEffectiveConfigTab.tsx -> configuration-policies.mdx. No-change (verified with reasoning): configuration-policies (Effective Config warranty/all-types fix #2003 already matches generic doc wording), deploy/production+upgrades+agents/building (Astro7/TW4/Vite8 frontend toolchain swap #2008/#1995/#1991 is GHCR-image-invisible; self-hosters pull prebuilt images), product-catalog/contracts (quotes/invoices computeQuoteTotals refactor #2011 no admin-visible change), organizations-and-sites (site address/contact persistence #2001 restores documented behavior), enrollment-keys/installation (Windows short-link 500 #2002 internal fix). No migrations, no new env vars, no breaking changes in 0.86.0. STILL DEFERRED from prior sweeps: PR #1725 Breeze Defaults baseline doc review; net-new features/quotes.mdx (quotes/proposals undocumented)." + "lastReviewedRef": "v0.87.0", + "reviewedAt": "2026-06-29", + "notes": "Bumped after v0.86.0..v0.87.0 sweep (release 0.87.0). NOTE: working tree was checked out behind the tag (at #2025/c29a228fb); fast-forwarded main to v0.87.0 (8b7a2e0d1) before editing so docs/source reflected the release. 7 doc files edited + mapping.json (+18 entries, 254 total). Edits: (1) features/integrations.mdx — new ## UniFi Network section (partner-scoped cloud Site Manager API-key connection + site mapping + sync history; optional per-console agent deep-telemetry collector, firmware >=9.3, read-only; #2040/#2051), Integration Types Network row, new #### Importing customers under QuickBooks (QB customers -> Orgs+default Sites, idempotent, partial-success; #2048) + rewrote stale 'later releases' Aside, Pax8 pointer to catalog import. (2) features/ticketing.mdx — new ### Connecting a Microsoft 365 support mailbox (app-only Graph admin-consent flow + ApplicationAccessPolicy least-privilege step, delta-poll, replies from mailbox; #2045). Editable inbound alias (#2060) was ALREADY documented at line 134 — left as-is. (3) deploy/environment.mdx — new ## Ticket Mailbox (M365 email-to-ticket): TICKET_MAILBOX_M365_CLIENT_ID/_SECRET + PUBLIC_TICKET_MAILBOX_APP_ID, redirect URI /api/v1/tickets/mailbox/callback, Graph Mail.ReadWrite+Mail.Send, separate Azure app from C2C. (4) features/reports.mdx — new security_compliance_posture type row + ## Security & Compliance Posture Report section (insurance/questionnaire evidence; created via report API today, builder UI entry point not yet wired — ReportTemplates unmounted + builder maps type down to compliance; documented honestly), FIXED stale async/polling generation prose+Steps (#2058 made generation synchronous w/ persisted snapshot), rewrote Downloading section to GET /reports/runs/:id/download?format=, added API table row, rewrote stale 'stuck in pending' troubleshooting. (5) features/vulnerability-management.mdx — corrected line 10 'findings automatically' (now opt-in OFF-by-default), new ## Enabling vulnerability scanning (per-scope config-policy gate, closest-wins, daily ~13:00 UTC correlation, [] deviceIds = no-op not all-devices; #2050), clarified feeds-need-no-config framing. (6) features/configuration-policies.mdx — Vulnerability Scanning feature row + ### Vulnerability Scanning subsection (inline on/off, DEFAULT OFF) + Breeze Defaults example row + featureType enum +vulnerability. (7) features/product-catalog.mdx — new ### Pax8 catalog-import subsection (search Pax8 catalog -> import as recurring item, MFA; distinct from subscription linking; #2025/#2048 Pax8 search). Skipped per audience filter: webhooks per-route auth (#2054 internal), MCP owning-partner resolution + SSE PUBLIC_API_URL (#2019 internal correctness; PUBLIC_API_URL pre-existing env var), reliability v0.86.0 notes (already in tree). No docsMapping.ts / docsIndex change (all edits were sections in existing pages, no new routes/pages). BUILD VERIFY: `astro build` content-collection step passes with edits (no MDX/frontmatter errors); full build FAILS at SSR bundling with @astrojs/mdx@7.0.0 vs astro@6.4.7 ('chunkToString not exported') — pre-existing v0.87.0 toolchain/lockfile breakage, REPRODUCED on pristine stashed docs, NOT caused by these edits (known Astro7/TW4 transition). STILL DEFERRED: PR #1725 Breeze Defaults baseline review; net-new features/quotes.mdx (quotes/proposals undocumented)." } diff --git a/scripts/docs-review/mapping.json b/scripts/docs-review/mapping.json index ad8e6e2b01..464a08cf38 100644 --- a/scripts/docs-review/mapping.json +++ b/scripts/docs-review/mapping.json @@ -1514,6 +1514,118 @@ "docs": [ "features/product-catalog.mdx" ] + }, + { + "pattern": "apps/api/src/services/unifi/**", + "docs": [ + "features/integrations.mdx" + ] + }, + { + "pattern": "apps/api/src/routes/unifi/**", + "docs": [ + "features/integrations.mdx" + ] + }, + { + "pattern": "apps/api/src/routes/agents/unifiTelemetry.ts", + "docs": [ + "features/integrations.mdx" + ] + }, + { + "pattern": "apps/web/src/components/integrations/UnifiIntegration.tsx", + "docs": [ + "features/integrations.mdx" + ] + }, + { + "pattern": "agent/internal/unifi/**", + "docs": [ + "features/integrations.mdx" + ] + }, + { + "pattern": "apps/api/src/services/ticketMailbox/**", + "docs": [ + "features/ticketing.mdx", + "deploy/environment.mdx" + ] + }, + { + "pattern": "apps/api/src/routes/tickets/mailboxConnect.ts", + "docs": [ + "features/ticketing.mdx", + "deploy/environment.mdx" + ] + }, + { + "pattern": "apps/web/src/components/settings/M365MailboxCard.tsx", + "docs": [ + "features/ticketing.mdx" + ] + }, + { + "pattern": "apps/api/src/services/securityComplianceReport.ts", + "docs": [ + "features/reports.mdx" + ] + }, + { + "pattern": "apps/api/src/services/reportGenerationService.ts", + "docs": [ + "features/reports.mdx" + ] + }, + { + "pattern": "apps/api/src/routes/reports/**", + "docs": [ + "features/reports.mdx" + ] + }, + { + "pattern": "apps/web/src/components/reports/reportPdf.ts", + "docs": [ + "features/reports.mdx" + ] + }, + { + "pattern": "apps/api/src/services/vulnerabilityCorrelation.ts", + "docs": [ + "features/vulnerability-management.mdx", + "features/configuration-policies.mdx" + ] + }, + { + "pattern": "apps/web/src/components/configurationPolicies/featureTabs/VulnerabilityTab.tsx", + "docs": [ + "features/configuration-policies.mdx", + "features/vulnerability-management.mdx" + ] + }, + { + "pattern": "apps/api/src/services/accounting/quickbooksCustomerImport.ts", + "docs": [ + "features/integrations.mdx" + ] + }, + { + "pattern": "apps/web/src/components/integrations/QuickbooksCustomerImport.tsx", + "docs": [ + "features/integrations.mdx" + ] + }, + { + "pattern": "apps/web/src/components/settings/Pax8CatalogDrawer.tsx", + "docs": [ + "features/product-catalog.mdx" + ] + }, + { + "pattern": "apps/api/src/services/pax8CatalogService.ts", + "docs": [ + "features/product-catalog.mdx" + ] } ] }