- Database: 7 Veeam tables + backup_type_udf column on configuration_items - API Client: VSPC REST API v3 client with pagination, rate limiting, Bearer auth - Sync Service: full/incremental sync for orgs, servers, repos, jobs, agent jobs, workloads - Scheduler: veeam-incremental (30min) and veeam-full (daily 2AM) schedules - Compliance Engine: cross-references Autotask config items vs Veeam workloads - API Endpoints: backup-status, companies, workloads, jobs, repos, compliance, sync - UI: Backup Status page with Overview + Contract Compliance tabs - Navigation: added Backup Status link with HardDrive icon - Docker: added VEEAM_VSPC_URL and VEEAM_VSPC_API_KEY env vars to compose
33 KiB
PRD: Veeam Service Provider Console (VSPC) Backup Integration
Introduction/Overview
This feature adds Veeam Service Provider Console (VSPC) as a connected vendor in Pulse, providing visibility into backup job status, protected workloads, backup repositories, and restore point data across all managed clients. Data will be synced on a schedule to PostgreSQL (following the same pattern as the Autotask sync) and displayed on a dedicated Backup Status page.
Additionally, this integration includes a Contract Compliance audit that cross-references Autotask configuration items (which have a backup-type UDF and are associated with active contracts) against actual Veeam backup data. This ensures every contracted backup is actually running, and every active Veeam backup is covered by a contract.
Problem Statement: MSP technicians and administrators currently have no visibility into backup health within Pulse. They must log into the Veeam Service Provider Console separately to check backup job statuses, identify failed backups, verify protected machines, and assess repository capacity. This context-switching slows response times and makes it easy to miss backup failures. Furthermore, there is no automated way to verify that devices under an active backup contract are actually being backed up, or that Veeam is not backing up devices that aren't under contract — leading to revenue leakage and compliance gaps.
Goal: Provide a centralized Backup Status page within Pulse that surfaces all critical Veeam backup data — job statuses, protected/unprotected machines, repository usage, restore point history, and RPO/SLA compliance — synced on a configurable schedule and linked to Autotask companies via the Company ID field in VSPC. Additionally, provide a Contract Compliance view that flags mismatches between contracted backup services and actual Veeam protection.
Goals
- Visibility Goal: Surface backup job status (success/failure/warning) for all managed clients in a single page
- Coverage Goal: Identify protected vs unprotected machines per company to highlight backup gaps
- Capacity Goal: Display backup repository usage and capacity to enable proactive storage management
- Compliance Goal: Show RPO/SLA compliance status per company and per protected workload
- Contract Compliance Goal: Cross-reference Autotask config items with backup UDFs on active contracts against Veeam protected workloads to identify: (a) contracted devices not being backed up, and (b) devices being backed up without a contract
- Sync Goal: Reliably sync Veeam data to PostgreSQL on a configurable schedule, following the existing Autotask sync pattern
- Matching Goal: Automatically associate VSPC organizations with Autotask companies using the Company ID field stored in VSPC
- UDF Sync Goal: Sync the backup-type UDF (ID:
29693319) from Autotask configuration items to PostgreSQL to enable contract compliance analysis
User Stories
-
As an MSP administrator, I want to see a summary of all backup job statuses across all clients on a single page, so that I can quickly identify which clients have failing backups without logging into VSPC.
-
As an MSP technician, I want to view detailed backup information for a specific company — including last backup time, job status, and protected machines — so that I can troubleshoot backup issues efficiently.
-
As an MSP administrator, I want to see which machines are not protected by any backup job, so that I can ensure complete backup coverage for all clients.
-
As an MSP administrator, I want to monitor backup repository usage and capacity, so that I can proactively provision additional storage before repositories fill up.
-
As an MSP administrator, I want to see restore point history for protected machines, so that I can verify data recoverability and RPO compliance.
-
As an MSP administrator, I want backup data to sync automatically on a schedule, so that the Backup Status page always shows recent data without manual intervention.
-
As an MSP administrator, I want to configure the Veeam sync schedule from the admin panel, so that I can control how frequently data is refreshed.
-
As an MSP administrator, I want to see which configuration items have a backup UDF set (Server Image, Workstation Image, Workstation File Based, etc.) and are on an active contract but are NOT being backed up in Veeam, so that I can identify contracted services that aren't being delivered.
-
As an MSP administrator, I want to see which machines are being backed up in Veeam but do NOT have a corresponding configuration item with a backup UDF on an active contract, so that I can identify unbilled backup services and potential revenue leakage.
-
As an MSP administrator, I want a summary card showing the total number of contract compliance mismatches, so that I can quickly assess the overall health of backup contract alignment.
Functional Requirements
FR1: Veeam VSPC API Client
1.1. Create a Veeam VSPC API client service (/lib/services/veeam-client.ts) that handles authentication and API requests
1.2. Use credentials from environment variables: VEEAM_VSPC_URL, VEEAM_VSPC_API_KEY
1.3. Implement API Key-based authorization using the Authorization: Bearer <API-Key> header
1.4. Base URL format: https://<hostname>:1280/api/v3
1.5. Support pagination using offset and limit query parameters
1.6. Support filtering using the VSPC filter query parameter syntax
1.7. Include proper error handling and logging for all API calls
1.8. Implement rate limiting to respect VSPC throttling settings
1.9. Handle token refresh if using OAuth 2.0 as a fallback authentication method
FR2: VSPC Data Fetching
Fetch the following data from the VSPC REST API v3:
2.1. Organizations — /organizations — Company/tenant data including instanceUid, name, companyId (maps to Autotask Company ID)
2.2. Backup Servers — /infrastructure/backupServers — Server name, version, status, role type
2.3. Backup Jobs — Backup job definitions including name, type, schedule, target repository, associated organization
2.4. Backup Job Sessions — Recent job session results including status (Success/Warning/Failed), start time, end time, duration, transferred data size, bottleneck info
2.5. Protected Workloads — Protected virtual machines and physical servers including name, platform, protection status, last restore point date
2.6. Backup Repositories — Repository name, capacity, free space, used space, associated backup server
2.7. Restore Points — Restore point data per protected workload including creation date, size, type (full/incremental)
FR3: Company Matching
3.1. Match VSPC organizations to Autotask companies using the companyId field in VSPC, which contains the Autotask Company ID
3.2. Store the mapping in the veeam_organizations database table
3.3. Handle cases where companyId is not set in VSPC (log warning, skip matching)
3.4. Support manual mapping override via admin UI for edge cases
FR4: PostgreSQL Database Schema
Create the following tables for synced Veeam data:
4.1. veeam_organizations — VSPC organization data
instance_uid(VARCHAR, PK) — VSPC organization UIDname(VARCHAR) — Organization namecompany_id(INTEGER) — Autotask Company ID (FK reference)status(VARCHAR) — Organization statussynced_at(TIMESTAMP)
4.2. veeam_backup_servers — Backup server infrastructure
instance_uid(VARCHAR, PK)name(VARCHAR)organization_uid(VARCHAR, FK → veeam_organizations)version(VARCHAR)display_version(VARCHAR)status(VARCHAR) — Healthy/Warning/Errorrole_type(VARCHAR) — CloudConnect/Hosted/etc.synced_at(TIMESTAMP)
4.3. veeam_backup_jobs — Backup job definitions
instance_uid(VARCHAR, PK)name(VARCHAR)organization_uid(VARCHAR, FK → veeam_organizations)backup_server_uid(VARCHAR, FK → veeam_backup_servers)job_type(VARCHAR) — Backup/Replication/Copy/etc.status(VARCHAR) — Running/Idle/Disabledlast_run(TIMESTAMP)last_result(VARCHAR) — Success/Warning/Failedschedule_enabled(BOOLEAN)repository_uid(VARCHAR)synced_at(TIMESTAMP)
4.4. veeam_job_sessions — Recent backup job session results
instance_uid(VARCHAR, PK)job_uid(VARCHAR, FK → veeam_backup_jobs)organization_uid(VARCHAR, FK → veeam_organizations)status(VARCHAR) — Success/Warning/Failedstart_time(TIMESTAMP)end_time(TIMESTAMP)duration_seconds(INTEGER)transferred_bytes(BIGINT)processed_bytes(BIGINT)bottleneck(VARCHAR)error_message(TEXT)synced_at(TIMESTAMP)
4.5. veeam_protected_workloads — Protected VMs and physical servers
instance_uid(VARCHAR, PK)name(VARCHAR)organization_uid(VARCHAR, FK → veeam_organizations)platform(VARCHAR) — VMware/Hyper-V/Physical/etc.protection_status(VARCHAR) — Protected/Unprotected/Partiallast_restore_point(TIMESTAMP)restore_point_count(INTEGER)total_backup_size_bytes(BIGINT)synced_at(TIMESTAMP)
4.6. veeam_repositories — Backup repository capacity
instance_uid(VARCHAR, PK)name(VARCHAR)backup_server_uid(VARCHAR, FK → veeam_backup_servers)capacity_bytes(BIGINT)free_space_bytes(BIGINT)used_space_bytes(BIGINT)repository_type(VARCHAR)synced_at(TIMESTAMP)
4.7. veeam_restore_points — Restore point history
instance_uid(VARCHAR, PK)workload_uid(VARCHAR, FK → veeam_protected_workloads)organization_uid(VARCHAR, FK → veeam_organizations)creation_date(TIMESTAMP)type(VARCHAR) — Full/Incrementalsize_bytes(BIGINT)synced_at(TIMESTAMP)
FR5: Veeam Sync Service
5.1. Create a Veeam sync service (/lib/services/veeam-sync-service.ts) following the pattern of the existing Autotask SyncService
5.2. Support full sync (all data) and incremental sync (changed data since last sync)
5.3. Sync entities in dependency order: organizations → backup servers → repositories → backup jobs → job sessions → protected workloads → restore points
5.4. Record sync history in the existing sync_history table with sync_source: 'veeam'
5.5. Log sync progress and errors using the existing SyncLogger pattern
5.6. Handle API pagination automatically (fetch all pages per entity)
FR6: Sync Scheduler Integration
6.1. Add Veeam sync schedules to the existing sync scheduler (/lib/services/sync-scheduler.ts)
6.2. Default schedule: incremental sync every 30 minutes, full sync daily at 2:00 AM
6.3. Allow schedule configuration from the Admin → Sync page
6.4. Display Veeam sync status and history alongside Autotask sync data in the admin UI
FR7: Backup Status Page
7.1. Create a new page at /backup-status accessible from the main navigation
7.2. Page layout sections:
Summary Cards (top row):
- Total protected workloads count
- Unprotected workloads count (with warning color if > 0)
- Last 24h job success rate (percentage)
- Failed jobs in last 24h (count, red if > 0)
- Total repository usage (used/total with percentage bar)
Company Backup Overview (main table):
- Company name (linked to Autotask company)
- Protected workload count
- Unprotected workload count
- Last backup job status (color-coded badge: green/yellow/red)
- Last successful backup timestamp
- Oldest restore point age
- Repository usage for company (if applicable)
- Expandable row to show individual workloads and jobs
Filters:
- Filter by company
- Filter by backup status (Success/Warning/Failed/All)
- Filter by protection status (Protected/Unprotected/All)
- Search by workload name
FR8: Company Backup Detail View
8.1. Clicking a company row expands to show:
- List of all protected workloads with last restore point date and status
- List of all backup jobs with last run time and result
- Recent job session history (last 7 days) with status timeline
- Unprotected machines highlighted in red/warning
FR9: API Endpoints
9.1. GET /api/veeam/backup-status — Summary statistics for dashboard cards
9.2. GET /api/veeam/companies — Company-level backup overview with aggregated stats
9.3. GET /api/veeam/companies/[companyId]/workloads — Protected workloads for a specific company
9.4. GET /api/veeam/companies/[companyId]/jobs — Backup jobs for a specific company
9.5. GET /api/veeam/companies/[companyId]/sessions — Recent job sessions for a specific company
9.6. GET /api/veeam/repositories — Repository capacity overview
9.7. GET /api/veeam/sync — Trigger manual Veeam sync (POST)
9.8. GET /api/veeam/compliance — Contract compliance summary and mismatch list
9.9. GET /api/veeam/compliance/[companyId] — Compliance details for a specific company
9.10. All endpoints read from PostgreSQL (synced data), not directly from VSPC API
FR10: TypeScript Types
10.1. Create Veeam type definitions in /lib/types/veeam.ts:
VeeamOrganizationinterfaceVeeamBackupServerinterfaceVeeamBackupJobinterfaceVeeamJobSessioninterfaceVeeamProtectedWorkloadinterfaceVeeamRepositoryinterfaceVeeamRestorePointinterfaceVeeamBackupStatusSummaryinterface (for dashboard cards)VeeamCompanyBackupOverviewinterface (for company table)VeeamComplianceResultinterface (for compliance mismatch records)VeeamComplianceSummaryinterface (for compliance summary cards) 10.2. Export types for use across the application
FR11: Error Handling & Logging
11.1. Log all VSPC API errors to console with descriptive messages 11.2. Log sync progress (entities synced, records created/updated/skipped) 11.3. Never throw errors that would break the Backup Status page — show "Data unavailable" gracefully 11.4. Display last successful sync timestamp on the Backup Status page 11.5. Show warning banner if last sync is older than 2 hours
FR12: Navigation Integration
12.1. Add "Backup Status" link to the main sidebar navigation
12.2. Use an appropriate Lucide icon (e.g., HardDrive, Shield, Database)
12.3. Position after existing navigation items
FR13: Autotask Backup UDF Sync
Note: Autotask configuration item UDFs are NOT currently synced to PostgreSQL. The mapConfigurationItem function in /lib/utils/entity-mapper.ts does not include userDefinedFields. This must be addressed.
13.1. Add a backup_type_udf column (VARCHAR, nullable) to the configuration_items table via migration
13.2. During Autotask config item sync, extract the backup-type UDF (ID: 29693319) from the userDefinedFields array and store its value in the backup_type_udf column
13.3. Update mapConfigurationItem() in /lib/utils/entity-mapper.ts to map the UDF value
13.4. Known UDF values to support:
Server ImageWorkstation ImageWorkstation File Based- Any other non-null/non-empty value should also be stored as-is
13.5. Add an index on
backup_type_udffor efficient compliance queries 13.6. Ensure the Autotask API query for configuration items includesuserDefinedFieldsin the response (verify the existingqueryEntitycall returns UDFs)
FR14: Contract Compliance Logic
14.1. Define a config item as "contracted for backup" when ALL of the following are true:
backup_type_udfis NOT NULL and NOT emptycontract_idis NOT NULL- The associated contract has
status= active (numeric value TBD — verify from Autotask picklist) is_active= true 14.2. Match contracted config items to Veeam protected workloads using:- Primary: hostname match (config item
reference_titleor RMM hostname vs Veeam workloadname) - Secondary: company match + name similarity (fuzzy) 14.3. Produce two mismatch lists per company:
- Contracted but NOT backed up: Config items meeting 14.1 criteria with no matching Veeam protected workload
- Backed up but NOT contracted: Veeam protected workloads with no matching config item that meets 14.1 criteria
14.4. Store compliance results in a
veeam_compliance_resultstable: id(SERIAL, PK)company_id(INTEGER, FK → companies)configuration_item_id(INTEGER, nullable, FK → configuration_items)veeam_workload_uid(VARCHAR, nullable, FK → veeam_protected_workloads)mismatch_type(VARCHAR) —contracted_not_backed_uporbacked_up_not_contractedbackup_type_udf(VARCHAR, nullable) — The UDF value from the config itemdevice_name(VARCHAR) — Name of the device for displaycomputed_at(TIMESTAMP) — When this compliance check was run 14.5. Recompute compliance results after each Veeam sync completes 14.6. Log compliance computation results (total matched, total mismatches per type)
FR15: Contract Compliance UI
15.1. Add a "Contract Compliance" tab to the Backup Status page (alongside the main backup overview) 15.2. Compliance Summary Cards:
- Total contracted backup devices (config items with backup UDF + active contract)
- Matched (contracted AND backed up in Veeam)
- Contracted but NOT backed up (red/warning count)
- Backed up but NOT contracted (amber/warning count) 15.3. Compliance Detail Table:
- Company name
- Device name
- Mismatch type (visual badge: "Missing Backup" in red, "No Contract" in amber)
- Backup type UDF value (Server Image, Workstation Image, etc.)
- Contract name (if applicable)
- Veeam workload name (if applicable)
- Filterable by company, mismatch type 15.4. Company Backup Detail (FR8) should also show compliance status:
- In the expanded company row, show a "Compliance" section listing any mismatches for that company
Non-Goals (Out of Scope)
- Kiosk/Ticker Integration: Backup data will NOT appear in the kiosk ticker or dashboard
- Backup Triggering: Will NOT allow starting/stopping backup jobs from Pulse
- Restore Operations: Will NOT support initiating restores from Pulse
- Auto-Remediation: Will NOT automatically create contracts or backup jobs to fix compliance mismatches
- Alerting/Notifications: Will NOT send email or other notifications for backup failures
- Veeam Cloud Connect: Will NOT integrate with Cloud Connect tenant data specifically
- Real-Time Data: All data is synced on schedule; no real-time/on-demand VSPC API calls from the UI
- Multi-Instance: Will NOT support multiple VSPC instances (single instance only)
Design Considerations
UI Components
- Follow existing Pulse design patterns (dark theme, shadcn/ui components)
- Use same Card, Badge, Table, and Button components from shadcn/ui
- Maintain consistent spacing, typography, and color scheme
- Use Lucide icons for backup-related visuals
Status Color Coding
- Success: Green badge/indicator
- Warning: Yellow/amber badge/indicator
- Failed: Red badge/indicator
- Running: Blue badge/indicator with spinner
- Disabled: Gray badge/indicator
Page Layout
┌──────────────────────────────────────────────────────────────┐
│ Backup Status Last sync: 5m ago │
├──────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────┐│
│ │Protected │ │Unprotect.│ │Success % │ │ Failed │ │Repo ││
│ │ 142 │ │ 3 ⚠ │ │ 96.2% │ │ 4 🔴 │ │ 72% ││
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └─────┘│
├──────────────────────────────────────────────────────────────┤
│ [Filter: Company ▼] [Status ▼] [Protection ▼] [Search...] │
├──────────────────────────────────────────────────────────────┤
│ Company │ Protected │ Unprotected │ Status │ Last OK │
│────────────────┼───────────┼─────────────┼────────┼──────────│
│ Acme Corp │ 12 │ 0 │ ✅ │ 2h ago │
│ └─ [Expand to show workloads and jobs] │
│ Beta LLC │ 8 │ 1 │ ⚠️ │ 5h ago │
│ Gamma Inc │ 5 │ 0 │ 🔴 │ 26h ago │
└──────────────────────────────────────────────────────────────┘
Repository Capacity Visualization
- Use progress bars showing used/total capacity
- Color-code: green (< 70%), yellow (70-85%), red (> 85%)
Contract Compliance Tab Layout
┌──────────────────────────────────────────────────────────────┐
│ [Backup Overview] [Contract Compliance] │
├──────────────────────────────────────────────────────────────┤
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ Contracted │ │ Matched │ │ Missing │ │ No │ │
│ │ Backups │ │ │ │ Backup │ │ Contract │ │
│ │ 87 │ │ 82 ✅ │ │ 3 🔴 │ │ 2 🟠 │ │
│ └────────────┘ └────────────┘ └────────────┘ └────────────┘ │
├──────────────────────────────────────────────────────────────┤
│ [Filter: Company ▼] [Mismatch Type ▼] [Search...] │
├──────────────────────────────────────────────────────────────┤
│ Company │ Device │ Type │ Backup UDF │Issue │
│─────────────┼────────────────┼──────────┼─────────────┼──────│
│ Acme Corp │ ACME-FS01 │ 🔴 Miss. │ Server Image│ No │
│ │ │ Backup │ │Veeam │
│ Beta LLC │ BETA-PC-042 │ 🟠 No │ │ No │
│ │ │ Contract │ │ UDF │
└──────────────────────────────────────────────────────────────┘
Compliance Status Badges
- Matched: Green badge — contracted and backed up
- Missing Backup: Red badge — contracted but not found in Veeam
- No Contract: Amber badge — backed up in Veeam but no matching contract
Technical Considerations
VSPC API Integration
- API Version: REST API v3 (3.6.1)
- Base URL:
https://<hostname>:1280/api/v3 - Authentication: API Key-based (
Authorization: Bearer <API-Key>) - Pagination: Offset-based with
offsetandlimitquery parameters - Filtering: VSPC filter syntax (e.g.,
filter=status eq "Failed") - Rate Limiting: Respect VSPC throttling settings; implement exponential backoff
- SSL: VSPC may use self-signed certificates; support
NODE_TLS_REJECT_UNAUTHORIZEDenv var for development
Company Matching Logic
// VSPC organizations have a companyId field that maps to Autotask Company ID
async function matchOrganizations(
vspcOrgs: VeeamOrganization[],
autotaskCompanies: Company[]
): Map<string, number> {
const mapping = new Map<string, number>(); // vspcOrgUid → autotaskCompanyId
for (const org of vspcOrgs) {
if (org.companyId) {
const match = autotaskCompanies.find(c => c.id === parseInt(org.companyId));
if (match) {
mapping.set(org.instanceUid, match.id);
}
}
}
return mapping;
}
Dependencies
- No new npm packages required (use built-in fetch)
- Leverage existing service patterns (
autotask-client.ts,sync-service.ts,entity-sync.ts) - Use existing UI components from shadcn/ui
- Use existing PostgreSQL client (
postgres-client.ts) - Use existing sync scheduler infrastructure
File Structure
/lib/services/veeam-client.ts # VSPC API client
/lib/services/veeam-factory.ts # Singleton factory for client
/lib/services/veeam-sync-service.ts # Sync orchestration service
/lib/services/veeam-compliance-service.ts # Contract compliance computation
/lib/types/veeam.ts # TypeScript types
/app/api/veeam/backup-status/route.ts # Summary stats endpoint
/app/api/veeam/companies/route.ts # Company backup overview
/app/api/veeam/companies/[companyId]/workloads/route.ts
/app/api/veeam/companies/[companyId]/jobs/route.ts
/app/api/veeam/companies/[companyId]/sessions/route.ts
/app/api/veeam/repositories/route.ts # Repository capacity
/app/api/veeam/sync/route.ts # Manual sync trigger
/app/api/veeam/compliance/route.ts # Compliance summary + list
/app/api/veeam/compliance/[companyId]/route.ts # Per-company compliance
/app/backup-status/page.tsx # Main Backup Status page
/components/backup/backup-summary-cards.tsx # Summary KPI cards
/components/backup/company-backup-table.tsx # Company overview table
/components/backup/company-backup-detail.tsx # Expanded company detail
/components/backup/repository-overview.tsx # Repository capacity view
/components/backup/compliance-summary-cards.tsx # Compliance KPI cards
/components/backup/compliance-detail-table.tsx # Compliance mismatch table
/migrations/023_create_veeam_tables.sql # Veeam tables + compliance results
/migrations/024_add_backup_type_udf.sql # Add backup_type_udf to configuration_items
Environment Variables
VEEAM_VSPC_URL=https://vac.wulfconsulting.com:1280
VEEAM_VSPC_API_KEY=your-api-key-here
# Optional: set to '0' if VSPC uses self-signed certs (dev only)
# NODE_TLS_REJECT_UNAUTHORIZED=0
Database Migration
- Migration file:
023_create_veeam_tables.sql- Creates all 7 Veeam tables with appropriate indexes
- Creates
veeam_compliance_resultstable - Add indexes on
organization_uid,company_id,status,synced_atcolumns for query performance - Add index on
veeam_job_sessions.start_timefor time-range queries - Add index on
veeam_compliance_results.company_idandmismatch_type
- Migration file:
024_add_backup_type_udf.sql- Adds
backup_type_udf(VARCHAR, nullable) column toconfiguration_itemstable - Adds index on
backup_type_udffor compliance queries - Note: Existing config items will have NULL for this column until the next Autotask sync runs
- Adds
Success Metrics
- Sync Reliability: 99%+ of scheduled syncs complete successfully
- Data Freshness: Backup status data is never more than 1 hour old during business hours
- Company Match Rate: 95%+ of VSPC organizations are matched to Autotask companies via Company ID
- Page Load Performance: Backup Status page loads within 2 seconds for typical MSP (< 50 companies)
- Coverage Visibility: 100% of VSPC-managed workloads are visible in the Backup Status page
- Adoption: Administrators check the Backup Status page at least once daily within the first month
- Compliance Accuracy: 95%+ of contracted backup devices are correctly matched to Veeam workloads (hostname matching)
- Revenue Protection: Identify 100% of Veeam-backed workloads that lack a corresponding active contract
Open Questions
-
VSPC API Key Permissions: What permission level is needed for the API key? Read-only access to all organizations?
- Recommendation: Create an API key with
restscope andisReadAccessOnly: true
- Recommendation: Create an API key with
-
Session History Depth: How many days of job session history should we sync and retain?
- Recommendation: Sync last 30 days, retain 90 days, purge older records
-
Self-Signed Certificates: Does the VSPC instance use a self-signed SSL certificate?
- Recommendation: Support
NODE_TLS_REJECT_UNAUTHORIZEDenv var; document in setup guide
- Recommendation: Support
-
VSPC Version Compatibility: Is the VSPC instance running v9.1 (REST API 3.6.1) or a different version?
- Recommendation: Target v3 API which is stable across recent VSPC versions
-
Unprotected Machine Detection: How should "unprotected" be defined — machines with no backup job, or machines whose last backup is older than X hours?
- Recommendation: Both — flag machines with no job AND machines with stale backups (configurable threshold, default 24h)
-
Repository Scope: Should we show all repositories or only those relevant to managed clients?
- Recommendation: Show all repositories with filtering by backup server
-
UDF Field ID Verification: The backup-type UDF is believed to be ID
29693319. This needs to be verified against the Autotask API by querying the UDF field definitions for ConfigurationItems.- Action: Query
GET /atservicesrest/v1.0/ConfigurationItemUserDefinedFieldsor inspect a config item with a known backup UDF value to confirm the field ID and name
- Action: Query
-
Contract Active Status Value: What is the numeric value for "Active" contract status in Autotask?
- Action: Query the Autotask picklist for contract statuses to determine the correct numeric value
-
Hostname Matching Accuracy: Config item
reference_titlemay not always match the Veeam workloadnameexactly. What fallback matching strategies should be used?- Recommendation: Try
reference_title, thenrmmDeviceAuditHostname, thenserial_number. Allow manual override mapping in a future iteration
- Recommendation: Try
-
UDF Values Completeness: Are "Server Image", "Workstation Image", and "Workstation File Based" the only backup UDF values, or are there others?
- Action: Query Autotask for the UDF picklist values to get the complete list
Implementation Notes for Developers
Getting Started
- Review existing Autotask sync service (
sync-service.ts,entity-sync.ts) as the primary reference pattern - Review VSPC REST API documentation: https://helpcenter.veeam.com/references/vac/9.1/rest/3.6.1/tag/SectionAbout
- Set up VSPC API key with read-only REST access
- Test API connectivity using curl or Postman before coding
- Run the database migration to create Veeam tables
Sync Implementation Order
- Implement
veeam-client.tswith authentication and basic GET requests - Implement organization sync first (simplest entity, needed for FK references)
- Add backup servers and repositories
- Add backup jobs and job sessions
- Add protected workloads and restore points
- Wire up to sync scheduler
- Add
backup_type_udfcolumn migration and updatemapConfigurationItem()in entity-mapper - Run an Autotask sync to populate
backup_type_udfvalues - Implement
veeam-compliance-service.ts(depends on both Veeam and Autotask data being synced) - Build the Contract Compliance UI tab
Testing Checklist
- Verify API key authentication works
- Test organization fetch and company matching
- Test full sync of all entities
- Test incremental sync (only changed records)
- Test with VSPC API unavailable (graceful failure)
- Test pagination with large datasets (100+ workloads)
- Verify Backup Status page renders correctly with real data
- Verify Backup Status page renders gracefully with no data
- Test company filter and status filter on Backup Status page
- Check database migration runs cleanly on existing schema
- Verify sync scheduler runs Veeam sync on configured schedule
- Verify
backup_type_udfis populated after Autotask sync - Test compliance computation with known contracted devices
- Verify "contracted but not backed up" mismatches are correctly identified
- Verify "backed up but not contracted" mismatches are correctly identified
- Test compliance UI tab renders correctly with mismatch data
- Test compliance UI with zero mismatches (all green)
- Verify compliance recomputes after each Veeam sync
Code Review Focus Areas
- Error handling completeness (VSPC API can be unreliable)
- TypeScript type safety for all VSPC API responses
- Consistent code style with existing services
- Proper logging for debugging sync issues
- Performance (batch inserts, avoid N+1 queries)
- Database index usage for Backup Status page queries