diff --git a/docs/PBS.md b/docs/PBS.md index a377d2c602..2c8affcab3 100644 --- a/docs/PBS.md +++ b/docs/PBS.md @@ -152,7 +152,7 @@ It does **not** allow: If you have multiple PBS servers, add each one separately in Settings. Pulse will: - Monitor each server independently -- Show backups from all servers in the unified Recovery view +- Show backups from all servers under **Proxmox → Backups** (`/proxmox/backups`) - Deduplicate if the same backup appears via both PVE passthrough and direct PBS --- @@ -301,7 +301,8 @@ or change retention to hide a display problem. ## Data Source Indicator -In the Recovery view, PBS backups show a data source indicator: +Under **Proxmox → Backups** (`/proxmox/backups`), PBS backups show a data source +indicator. There is no current top-level Recovery page: - **"PBS"** badge alone = Direct PBS connection (full data) - **"PBS via PVE"** = Passthrough via PVE storage (limited data) diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 9b11c341cd..f7f21b286a 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -413,7 +413,7 @@ consequential, manually redacted error. ### TrueNAS #### "TrueNAS service unavailable" -- Ensure TrueNAS was added in **Settings → TrueNAS** with a valid HTTPS URL, +- Ensure TrueNAS was added in **Settings → Infrastructure → Platform connections** with a valid HTTPS URL, API key, and the username that owns the key. - Check that the TrueNAS system is reachable from the Pulse server (default HTTPS port). @@ -424,7 +424,10 @@ consequential, manually redacted error. #### TrueNAS pools/datasets not appearing - TrueNAS data appears in the unified resource model and may take one configured polling cycle (60 seconds by default) to appear. -- Check **Infrastructure** (TrueNAS host), **Storage** (pools/datasets), and **Recovery** (snapshots/replication). +- Open **TrueNAS → Overview** for the appliance, **TrueNAS → Storage** + (`/truenas/storage`) for pools, datasets and disks, and **TrueNAS → Protection** + (`/truenas/protection`) for snapshots and replication. These are tabs within + TrueNAS, not separate top-level Storage or Recovery pages. - For data that stops refreshing, use the [TrueNAS polling checks](TRUENAS.md#stale-truenas-data) before testing or restarting. A stale badge is not proof of an invalid key, and a successful connection test is not proof that collection has recovered. @@ -432,8 +435,38 @@ consequential, manually redacted error. ### Navigation (v6) #### Old bookmarks don't work -- Legacy URLs (`/proxmox`, `/docker`, `/kubernetes`, `/hosts`, `/services`) are not supported in v6. -- Update bookmarks to canonical routes. See [Migration Guide](MIGRATION_UNIFIED_NAV.md). + +Current Pulse uses platform navigation. `/proxmox`, `/docker` and `/kubernetes` +are supported; do not replace them with the retired task-based routes. +Open Pulse at its base URL and use the menu to find the relevant page: + +| Menu | Entry route | +| --- | --- | +| Proxmox | `/proxmox/overview` | +| Docker | `/docker/overview` | +| Kubernetes | `/kubernetes/overview` | +| TrueNAS | `/truenas/overview` | +| vSphere | `/vmware/overview` | +| Machines | `/standalone/machines` | + +The short-lived top-level `/workloads`, `/storage` and `/recovery` layout is +retired. `/infrastructure` now opens the default workspace, not the former +unified host page. For old `/hosts` or `/services` bookmarks, select the current +platform or Machines page instead of assuming an automatic redirect. PBS +backups are under **Proxmox → Backups**, and TrueNAS snapshots and replication +are under **TrueNAS → Protection**. + +Platform-connected hosts can appear under their platform rather than Machines. +If a menu or expected resource is missing, check its saved connection and last +successful collection in **Settings → Infrastructure**; a missing page alone +does not prove a host was deleted. Do not delete connections or re-enrol agents +just to repair a bookmark. + +If menu navigation works but reloading the same URL returns a proxy 404, check +the proxy's route handling using [Reverse Proxy Configuration](REVERSE_PROXY.md). +For the current layout, see [FAQ](FAQ.md#how-is-navigation-organised-in-pulse-v6). +The [unified-navigation migration](MIGRATION_UNIFIED_NAV.md) is historical, +not a guide to the current menu. ### Relay / Mobile diff --git a/docs/TRUENAS.md b/docs/TRUENAS.md index ddd5ea8468..54dac2b6e6 100644 --- a/docs/TRUENAS.md +++ b/docs/TRUENAS.md @@ -4,8 +4,9 @@ Pulse v6 includes first-class monitoring for **TrueNAS SCALE** and **TrueNAS COR ## Quick Start -1. Go to **Settings → TrueNAS**. -2. Click **Add Connection**. +1. Go to **Settings → Infrastructure**. +2. Click **Add infrastructure** and choose **TrueNAS**. Existing connections + are listed under **Platform connections**. 3. Enter the TrueNAS URL (e.g., `https://truenas.local`), the API key, and the username that owns the key. 4. Click **Test Connection** → **Save**. @@ -28,27 +29,27 @@ On your TrueNAS system: ## What Gets Monitored -| Data | Unified Page | Details | +| Data | Pulse page / tab | Details | |---|---|---| -| System info (hostname, version, uptime) | Infrastructure | CPU, memory, health status | -| Virtual machines | TrueNAS Overview | State, CPU, memory, boot mode, devices, and security flags from the TrueNAS VM API | -| Apps | TrueNAS Overview | Native app state, image/version, ports, volumes, networks, and runtime container details | -| ZFS Pools | Storage | Total/used/free capacity, pool status (ONLINE/DEGRADED/FAULTED) | -| ZFS Datasets | Storage | Used/available space, mount status, read-only flag | -| Physical Disks | Storage | Model, serial, size, transport type, rotational flag, temperature, and native SMART failure/counter evidence when TrueNAS reports it | -| ZFS Snapshots | Recovery | Dataset, creation time, size, referenced data | -| Replication Tasks | Recovery | Source/target datasets, direction, last run status | +| System info (hostname, version, uptime) | TrueNAS → Overview | CPU, memory, health status | +| Virtual machines | TrueNAS → VMs | State, CPU, memory, boot mode, devices, and security flags from the TrueNAS VM API | +| Apps | TrueNAS → Apps | Native app state, image/version, ports, volumes, networks, and runtime container details | +| ZFS Pools | TrueNAS → Storage | Total/used/free capacity, pool status (ONLINE/DEGRADED/FAULTED) | +| ZFS Datasets | TrueNAS → Storage | Used/available space, mount status, read-only flag | +| Physical Disks | TrueNAS → Storage | Model, serial, size, transport type, rotational flag, temperature, and native SMART failure/counter evidence when TrueNAS reports it | +| ZFS Snapshots | TrueNAS → Protection | Dataset, creation time, size, referenced data | +| Replication Tasks | TrueNAS → Protection | Source/target datasets, direction, last run status | | TrueNAS Alerts | Alerts | Native TrueNAS alert messages and severity levels | ## Unified Resource Mapping TrueNAS resources are mapped into the unified resource model: -- **TrueNAS host** → appears as a resource with `source: truenas` on the **Infrastructure** page. -- **TrueNAS VMs** → appear as canonical `vm` workloads on the **TrueNAS** page. -- **TrueNAS apps** → appear as canonical `app-container` workloads on the **TrueNAS** page. -- **ZFS pools and datasets** → appear on the **Storage** page. -- **ZFS snapshots and replication** → appear on the **Recovery** page as recovery points. +- **TrueNAS host** → appears as a resource with `source: truenas` under **TrueNAS → Overview** (`/truenas/overview`). +- **TrueNAS VMs** → appear as canonical `vm` workloads under **TrueNAS → VMs** (`/truenas/vms`). +- **TrueNAS apps** → appear as canonical `app-container` workloads under **TrueNAS → Apps** (`/truenas/apps`). +- **ZFS pools, datasets and physical disks** → appear under **TrueNAS → Storage** (`/truenas/storage`). +- **ZFS snapshots and replication** → appear under **TrueNAS → Protection** (`/truenas/protection`) as recovery points. - **TrueNAS alerts** → surfaced on the **Alerts** page alongside Proxmox and other platform alerts. TrueNAS drive-health alerts that identify a specific disk remain disk-health @@ -60,7 +61,11 @@ typed uncorrectable-error or spare-reserve argument, Pulse also projects that value into the disk's SMART details. Pulse does not infer counters from alert text, and current TrueNAS APIs do not expose every raw SMART attribute. -Resources from TrueNAS can be filtered using the **source** filter on any page. +The unified resource model is a backend contract, not a top-level +Infrastructure, Storage or Recovery menu. TrueNAS tabs follow the inventory +Pulse has collected; an absent tab is not proof of successful collection. +For missing or stale data, use the [polling checks](#stale-truenas-data) before +testing the connection or restarting. ## Multiple TrueNAS Systems @@ -91,7 +96,7 @@ All endpoints require admin authentication. ### Testing and adding a connection (API) -The **Settings → TrueNAS** flow is the simplest option. For an API client, +The **Settings → Infrastructure → Platform connections** flow is the simplest option. For an API client, prepare the private Pulse header file as described in the [API authentication guide](API.md). The Pulse API token authenticates to Pulse; the separate TrueNAS API key belongs in the connection's JSON file. @@ -260,4 +265,4 @@ Set `PULSE_ENABLE_TRUENAS=false` and restart Pulse. Existing connection data is JSON-RPC transport, API-key, and TLS requirements - [Configuration Guide](CONFIGURATION.md#truenas) — environment variables and setup - [ZFS Monitoring](ZFS_MONITORING.md) — Proxmox-native ZFS pool monitoring -- [Recovery](RECOVERY.md) — TrueNAS snapshots in the recovery view +- [Recovery data](RECOVERY.md) — the snapshot and replication data shown under **TrueNAS → Protection** diff --git a/frontend-modern/browser-tests/navigation-help.cjs b/frontend-modern/browser-tests/navigation-help.cjs new file mode 100644 index 0000000000..91028e5879 --- /dev/null +++ b/frontend-modern/browser-tests/navigation-help.cjs @@ -0,0 +1,110 @@ +// Production Docs/router/styles with the actual shipped Markdown; no backend. +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); +const { chromium, webkit } = require('playwright'); + +(async () => { + const root = '/workspace/frontend-modern'; + const artifacts = path.join(root, 'node_modules', 'navigation-help-browser'); + fs.mkdirSync(artifacts, { recursive: true }); + const { createServer } = await import(path.join(root, 'node_modules/vite/dist/node/index.js')); + const server = await createServer({ + root, + configFile: path.join(root, 'vite.config.ts'), + cacheDir: path.join(root, 'node_modules', '.vite-navigation-help'), + server: { host: '127.0.0.1', port: 5247, strictPort: true }, + optimizeDeps: { noDiscovery: true, include: [] }, + }); + const results = []; + let browser; + try { + await server.listen(); + for (const [engine, width, tone] of [['chromium', 1280, 'light'], ['webkit', 390, 'dark']]) { + browser = await { chromium, webkit }[engine].launch( + engine === 'chromium' + ? { headless: true, channel: 'chromium', args: ['--no-sandbox'] } + : { headless: true }, + ); + const page = await browser.newPage({ + viewport: { width, height: 900 }, + ...(engine === 'webkit' ? { isMobile: true, hasTouch: true } : {}), + }); + const errors = []; + page.on('pageerror', (e) => errors.push(e.message)); + page.on('console', (m) => { if (m.type() === 'error') errors.push(m.text()); }); + await page.goto('http://127.0.0.1:5247/browser-tests/docs-fragment-navigation.html?scenario=troubleshooting', + { waitUntil: 'domcontentloaded', timeout: 60_000 }); + await page.getByRole('heading', { name: "Old bookmarks don't work", exact: true }).waitFor(); + if (tone === 'dark') await page.evaluate(() => document.documentElement.classList.add('dark')); + const routes = page.locator('article table').filter({ hasText: '/standalone/machines' }); + assert.equal(await routes.count(), 1); + assert.deepEqual(await routes.locator('tbody tr').allTextContents(), [ + 'Proxmox/proxmox/overview', 'Docker/docker/overview', 'Kubernetes/kubernetes/overview', + 'TrueNAS/truenas/overview', 'vSphere/vmware/overview', 'Machines/standalone/machines', + ]); + const article = await page.locator('article').innerText(); + assert.ok(article.includes('are supported; do not replace them with the retired task-based routes.')); + assert.ok(article.includes('Do not delete connections or re-enrol agents')); + await routes.scrollIntoViewIfNeeded(); + assert.ok(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth + 1)); + await page.screenshot({ path: path.join(artifacts, `${engine}-routes.png`) }); + + await page.getByRole('link', { name: 'FAQ', exact: true }).click(); + const faq = page.getByRole('heading', { name: 'How is navigation organised in Pulse v6?', exact: true }); + await faq.waitFor(); + await page.waitForFunction(() => { + const heading = document.getElementById('how-is-navigation-organised-in-pulse-v6'); + return heading && heading.getBoundingClientRect().top >= 0 && heading.getBoundingClientRect().top < innerHeight; + }); + assert.ok(page.url().endsWith('/docs/FAQ#how-is-navigation-organised-in-pulse-v6')); + + await page.getByRole('link', { name: '← All documentation' }).click(); + await page.getByRole('link', { name: 'TrueNAS SCALE and CORE', exact: true }).click(); + const inventory = page.locator('article table').filter({ hasText: 'Pulse page / tab' }); + await inventory.waitFor(); + const destinations = await inventory.locator('tbody tr td:nth-child(2)').allTextContents(); + assert.deepEqual(destinations, ['TrueNAS → Overview', 'TrueNAS → VMs', 'TrueNAS → Apps', + 'TrueNAS → Storage', 'TrueNAS → Storage', 'TrueNAS → Storage', + 'TrueNAS → Protection', 'TrueNAS → Protection', 'Alerts']); + const mapping = await page.locator('article').innerText(); + for (const route of ['/truenas/overview', '/truenas/vms', '/truenas/apps', '/truenas/storage', '/truenas/protection']) + assert.ok(mapping.includes(route)); + await inventory.scrollIntoViewIfNeeded(); + const geometry = await inventory.evaluate((table) => ({ + localScroll: table.parentElement.dataset.docTableScroll !== undefined, + viewport: innerWidth, + outer: document.documentElement.scrollWidth, + table: table.parentElement.scrollWidth, + wrapper: table.parentElement.clientWidth, + })); + assert.ok(geometry.localScroll); + assert.ok(geometry.outer <= geometry.viewport + 1); + if (width === 390) assert.ok(geometry.table > geometry.wrapper); + await page.screenshot({ path: path.join(artifacts, `${engine}-truenas.png`) }); + + await page.getByRole('link', { name: '← All documentation' }).click(); + await page.getByRole('link', { name: 'Proxmox Backup Server', exact: true }).click(); + const pbs = page.getByRole('heading', { name: 'Data Source Indicator', exact: true }); + await pbs.waitFor(); + const pbsText = await page.locator('article').innerText(); + assert.ok(pbsText.includes('Proxmox → Backups (/proxmox/backups)')); + assert.ok(pbsText.includes('There is no current top-level Recovery page')); + await pbs.scrollIntoViewIfNeeded(); + assert.ok(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 1)); + await page.screenshot({ path: path.join(artifacts, `${engine}-pbs.png`) }); + assert.deepEqual(errors, []); + results.push({ engine, version: browser.version(), width, tone, routes: 6, destinations, + geometry, faqFragment: true, pbsPlacement: true, errors }); + await browser.close(); + browser = undefined; + } + const result = { result: 'passed', playwright: require('playwright/package.json').version, + scope: 'shipped help rendering and navigation, not appliance collection', results }; + fs.writeFileSync(path.join(artifacts, 'result.json'), JSON.stringify(result, null, 2) + '\n'); + console.log(JSON.stringify(result)); + } finally { + if (browser) await browser.close(); + await server.close(); + } +})().catch((error) => { console.error(error); process.exitCode = 1; }); diff --git a/frontend-modern/public/docs/PBS.md b/frontend-modern/public/docs/PBS.md index a377d2c602..2c8affcab3 100644 --- a/frontend-modern/public/docs/PBS.md +++ b/frontend-modern/public/docs/PBS.md @@ -152,7 +152,7 @@ It does **not** allow: If you have multiple PBS servers, add each one separately in Settings. Pulse will: - Monitor each server independently -- Show backups from all servers in the unified Recovery view +- Show backups from all servers under **Proxmox → Backups** (`/proxmox/backups`) - Deduplicate if the same backup appears via both PVE passthrough and direct PBS --- @@ -301,7 +301,8 @@ or change retention to hide a display problem. ## Data Source Indicator -In the Recovery view, PBS backups show a data source indicator: +Under **Proxmox → Backups** (`/proxmox/backups`), PBS backups show a data source +indicator. There is no current top-level Recovery page: - **"PBS"** badge alone = Direct PBS connection (full data) - **"PBS via PVE"** = Passthrough via PVE storage (limited data) diff --git a/frontend-modern/public/docs/TROUBLESHOOTING.md b/frontend-modern/public/docs/TROUBLESHOOTING.md index 9b11c341cd..f7f21b286a 100644 --- a/frontend-modern/public/docs/TROUBLESHOOTING.md +++ b/frontend-modern/public/docs/TROUBLESHOOTING.md @@ -413,7 +413,7 @@ consequential, manually redacted error. ### TrueNAS #### "TrueNAS service unavailable" -- Ensure TrueNAS was added in **Settings → TrueNAS** with a valid HTTPS URL, +- Ensure TrueNAS was added in **Settings → Infrastructure → Platform connections** with a valid HTTPS URL, API key, and the username that owns the key. - Check that the TrueNAS system is reachable from the Pulse server (default HTTPS port). @@ -424,7 +424,10 @@ consequential, manually redacted error. #### TrueNAS pools/datasets not appearing - TrueNAS data appears in the unified resource model and may take one configured polling cycle (60 seconds by default) to appear. -- Check **Infrastructure** (TrueNAS host), **Storage** (pools/datasets), and **Recovery** (snapshots/replication). +- Open **TrueNAS → Overview** for the appliance, **TrueNAS → Storage** + (`/truenas/storage`) for pools, datasets and disks, and **TrueNAS → Protection** + (`/truenas/protection`) for snapshots and replication. These are tabs within + TrueNAS, not separate top-level Storage or Recovery pages. - For data that stops refreshing, use the [TrueNAS polling checks](TRUENAS.md#stale-truenas-data) before testing or restarting. A stale badge is not proof of an invalid key, and a successful connection test is not proof that collection has recovered. @@ -432,8 +435,38 @@ consequential, manually redacted error. ### Navigation (v6) #### Old bookmarks don't work -- Legacy URLs (`/proxmox`, `/docker`, `/kubernetes`, `/hosts`, `/services`) are not supported in v6. -- Update bookmarks to canonical routes. See [Migration Guide](MIGRATION_UNIFIED_NAV.md). + +Current Pulse uses platform navigation. `/proxmox`, `/docker` and `/kubernetes` +are supported; do not replace them with the retired task-based routes. +Open Pulse at its base URL and use the menu to find the relevant page: + +| Menu | Entry route | +| --- | --- | +| Proxmox | `/proxmox/overview` | +| Docker | `/docker/overview` | +| Kubernetes | `/kubernetes/overview` | +| TrueNAS | `/truenas/overview` | +| vSphere | `/vmware/overview` | +| Machines | `/standalone/machines` | + +The short-lived top-level `/workloads`, `/storage` and `/recovery` layout is +retired. `/infrastructure` now opens the default workspace, not the former +unified host page. For old `/hosts` or `/services` bookmarks, select the current +platform or Machines page instead of assuming an automatic redirect. PBS +backups are under **Proxmox → Backups**, and TrueNAS snapshots and replication +are under **TrueNAS → Protection**. + +Platform-connected hosts can appear under their platform rather than Machines. +If a menu or expected resource is missing, check its saved connection and last +successful collection in **Settings → Infrastructure**; a missing page alone +does not prove a host was deleted. Do not delete connections or re-enrol agents +just to repair a bookmark. + +If menu navigation works but reloading the same URL returns a proxy 404, check +the proxy's route handling using [Reverse Proxy Configuration](REVERSE_PROXY.md). +For the current layout, see [FAQ](FAQ.md#how-is-navigation-organised-in-pulse-v6). +The [unified-navigation migration](MIGRATION_UNIFIED_NAV.md) is historical, +not a guide to the current menu. ### Relay / Mobile diff --git a/frontend-modern/public/docs/TRUENAS.md b/frontend-modern/public/docs/TRUENAS.md index ddd5ea8468..54dac2b6e6 100644 --- a/frontend-modern/public/docs/TRUENAS.md +++ b/frontend-modern/public/docs/TRUENAS.md @@ -4,8 +4,9 @@ Pulse v6 includes first-class monitoring for **TrueNAS SCALE** and **TrueNAS COR ## Quick Start -1. Go to **Settings → TrueNAS**. -2. Click **Add Connection**. +1. Go to **Settings → Infrastructure**. +2. Click **Add infrastructure** and choose **TrueNAS**. Existing connections + are listed under **Platform connections**. 3. Enter the TrueNAS URL (e.g., `https://truenas.local`), the API key, and the username that owns the key. 4. Click **Test Connection** → **Save**. @@ -28,27 +29,27 @@ On your TrueNAS system: ## What Gets Monitored -| Data | Unified Page | Details | +| Data | Pulse page / tab | Details | |---|---|---| -| System info (hostname, version, uptime) | Infrastructure | CPU, memory, health status | -| Virtual machines | TrueNAS Overview | State, CPU, memory, boot mode, devices, and security flags from the TrueNAS VM API | -| Apps | TrueNAS Overview | Native app state, image/version, ports, volumes, networks, and runtime container details | -| ZFS Pools | Storage | Total/used/free capacity, pool status (ONLINE/DEGRADED/FAULTED) | -| ZFS Datasets | Storage | Used/available space, mount status, read-only flag | -| Physical Disks | Storage | Model, serial, size, transport type, rotational flag, temperature, and native SMART failure/counter evidence when TrueNAS reports it | -| ZFS Snapshots | Recovery | Dataset, creation time, size, referenced data | -| Replication Tasks | Recovery | Source/target datasets, direction, last run status | +| System info (hostname, version, uptime) | TrueNAS → Overview | CPU, memory, health status | +| Virtual machines | TrueNAS → VMs | State, CPU, memory, boot mode, devices, and security flags from the TrueNAS VM API | +| Apps | TrueNAS → Apps | Native app state, image/version, ports, volumes, networks, and runtime container details | +| ZFS Pools | TrueNAS → Storage | Total/used/free capacity, pool status (ONLINE/DEGRADED/FAULTED) | +| ZFS Datasets | TrueNAS → Storage | Used/available space, mount status, read-only flag | +| Physical Disks | TrueNAS → Storage | Model, serial, size, transport type, rotational flag, temperature, and native SMART failure/counter evidence when TrueNAS reports it | +| ZFS Snapshots | TrueNAS → Protection | Dataset, creation time, size, referenced data | +| Replication Tasks | TrueNAS → Protection | Source/target datasets, direction, last run status | | TrueNAS Alerts | Alerts | Native TrueNAS alert messages and severity levels | ## Unified Resource Mapping TrueNAS resources are mapped into the unified resource model: -- **TrueNAS host** → appears as a resource with `source: truenas` on the **Infrastructure** page. -- **TrueNAS VMs** → appear as canonical `vm` workloads on the **TrueNAS** page. -- **TrueNAS apps** → appear as canonical `app-container` workloads on the **TrueNAS** page. -- **ZFS pools and datasets** → appear on the **Storage** page. -- **ZFS snapshots and replication** → appear on the **Recovery** page as recovery points. +- **TrueNAS host** → appears as a resource with `source: truenas` under **TrueNAS → Overview** (`/truenas/overview`). +- **TrueNAS VMs** → appear as canonical `vm` workloads under **TrueNAS → VMs** (`/truenas/vms`). +- **TrueNAS apps** → appear as canonical `app-container` workloads under **TrueNAS → Apps** (`/truenas/apps`). +- **ZFS pools, datasets and physical disks** → appear under **TrueNAS → Storage** (`/truenas/storage`). +- **ZFS snapshots and replication** → appear under **TrueNAS → Protection** (`/truenas/protection`) as recovery points. - **TrueNAS alerts** → surfaced on the **Alerts** page alongside Proxmox and other platform alerts. TrueNAS drive-health alerts that identify a specific disk remain disk-health @@ -60,7 +61,11 @@ typed uncorrectable-error or spare-reserve argument, Pulse also projects that value into the disk's SMART details. Pulse does not infer counters from alert text, and current TrueNAS APIs do not expose every raw SMART attribute. -Resources from TrueNAS can be filtered using the **source** filter on any page. +The unified resource model is a backend contract, not a top-level +Infrastructure, Storage or Recovery menu. TrueNAS tabs follow the inventory +Pulse has collected; an absent tab is not proof of successful collection. +For missing or stale data, use the [polling checks](#stale-truenas-data) before +testing the connection or restarting. ## Multiple TrueNAS Systems @@ -91,7 +96,7 @@ All endpoints require admin authentication. ### Testing and adding a connection (API) -The **Settings → TrueNAS** flow is the simplest option. For an API client, +The **Settings → Infrastructure → Platform connections** flow is the simplest option. For an API client, prepare the private Pulse header file as described in the [API authentication guide](API.md). The Pulse API token authenticates to Pulse; the separate TrueNAS API key belongs in the connection's JSON file. @@ -260,4 +265,4 @@ Set `PULSE_ENABLE_TRUENAS=false` and restart Pulse. Existing connection data is JSON-RPC transport, API-key, and TLS requirements - [Configuration Guide](CONFIGURATION.md#truenas) — environment variables and setup - [ZFS Monitoring](ZFS_MONITORING.md) — Proxmox-native ZFS pool monitoring -- [Recovery](RECOVERY.md) — TrueNAS snapshots in the recovery view +- [Recovery data](RECOVERY.md) — the snapshot and replication data shown under **TrueNAS → Protection** diff --git a/scripts/tests/test_navigation_help_docs.py b/scripts/tests/test_navigation_help_docs.py new file mode 100644 index 0000000000..3008fe45ee --- /dev/null +++ b/scripts/tests/test_navigation_help_docs.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +"""Keep operator navigation guidance tied to the shipped routes and tab labels. + +These checks cover documentation accuracy, not collection or appliance health. +""" + +from pathlib import Path +import re +import unittest + + +ROOT = Path(__file__).resolve().parents[2] + + +def doc_text(name: str) -> str: + return (ROOT / "docs" / name).read_text(encoding="utf-8") + + +def source(name: str) -> str: + return (ROOT / "frontend-modern/src" / name).read_text(encoding="utf-8") + + +class NavigationHelpDocsTest(unittest.TestCase): + def test_entry_routes_match_the_registered_platform_routes(self): + guide = doc_text("TROUBLESHOOTING.md").split("#### Old bookmarks don't work", 1)[1] + guide = guide.split("### Relay / Mobile", 1)[0] + links = source("routing/resourceLinks.ts") + app = source("App.tsx") + for label, prefix in (("Proxmox", "PROXMOX"), ("Docker", "DOCKER"), + ("Kubernetes", "KUBERNETES"), ("TrueNAS", "TRUENAS"), + ("vSphere", "VMWARE"), ("Machines", "STANDALONE")): + with self.subTest(platform=label): + path = re.search(rf"export const {prefix}_PATH = '([^']+)';", links).group(1) + tab = re.search(rf"export const {prefix}_DEFAULT_TAB = '([^']+)';", links).group(1) + self.assertIn(f"| {label} | `{path}/{tab}` |", guide) + self.assertIn(f'