<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>PrintMaster Documentation on PrintMaster Docs</title><link>https://docs.printmaster.work/</link><description>Recent content in PrintMaster Documentation on PrintMaster Docs</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://docs.printmaster.work/index.xml" rel="self" type="application/rss+xml"/><item><title>Agent Module Documentation</title><link>https://docs.printmaster.work/components/agent/historical-overview/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/components/agent/historical-overview/</guid><description>&lt;p&gt;&lt;strong&gt;Location&lt;/strong&gt;: &lt;code&gt;agent/agent/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The agent module handles network discovery protocols, device detection, SNMP operations, and live discovery methods. It sits between the scanner (device querying) and storage (persistence) layers.&lt;/p&gt;
&lt;h2 id="architecture-overview"&gt;Architecture Overview&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;agent/
├── detect.go # Main Discover() function, IP enumeration, ARP/ICMP
├── probe.go # TCP port probing, connectivity checks
├── parse.go # SNMP PDU parsing, OID interpretation
├── snmp.go # Legacy SNMP operations (being phased out)
├── snmp_iface.go # SNMP interface definitions
├── mdns.go # mDNS/Bonjour discovery
├── ssdp.go # SSDP/UPnP discovery
├── wsdiscovery.go # WS-Discovery protocol
├── snmptraps.go # SNMP trap listener
├── llmnr.go # LLMNR name resolution
├── arp.go # ARP table reading
├── merge.go # Device data merging and deduplication
├── helpers.go # Utility functions
├── metrics.go # Performance metrics collection
├── report.go # Scan result reporting
├── types.go # Data structures (PrinterInfo, ScanMeta, etc.)
├── config.go # Configuration structures
├── diagnostics.go # Diagnostic logging and debugging
├── update.go # Device update and refresh logic
└── vendor_roots.go # Vendor OID root definitions
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="discovery-methods"&gt;Discovery Methods&lt;/h2&gt;
&lt;h3 id="1-active-network-scanning-detectgo"&gt;1. Active Network Scanning (&lt;code&gt;detect.go&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Enumerate IP addresses and perform liveness checks.&lt;/p&gt;</description></item><item><title>Auto-Update &amp; Installer Repackaging Plan</title><link>https://docs.printmaster.work/development/auto-update-plan/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/auto-update-plan/</guid><description>&lt;p&gt;This document captures the agreed strategy for server- and agent-driven updates, including manifest signing, installer repackaging, and rollout choreography. It serves as a checklist we can iterate through incrementally.&lt;/p&gt;
&lt;h2 id="goals"&gt;Goals&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Enable the PrintMaster &lt;strong&gt;server&lt;/strong&gt; to self-update without user intervention (non-Docker deployments).&lt;/li&gt;
&lt;li&gt;Allow the server to orchestrate &lt;strong&gt;agent&lt;/strong&gt; updates, including fully background installations triggered from the fleet UI.&lt;/li&gt;
&lt;li&gt;Provide &lt;strong&gt;customized installers&lt;/strong&gt; (per fleet/tenant) that embed configuration data and can be used for both onboarding and update flows.&lt;/li&gt;
&lt;li&gt;Maintain &lt;strong&gt;trust&lt;/strong&gt; without external code-signing certificates by using server-signed manifests and checksum validation.&lt;/li&gt;
&lt;li&gt;Keep Docker deployments opt-in / manual since they already rely on image pulls.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="high-level-architecture"&gt;High-Level Architecture&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Release Intake&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Build &amp; Release Workflow</title><link>https://docs.printmaster.work/development/build-workflow/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/build-workflow/</guid><description>&lt;h2 id="quick-start-development"&gt;Quick Start (Development)&lt;/h2&gt;
&lt;h3 id="windows-powershell-quick-launch"&gt;Windows PowerShell Quick Launch&lt;/h3&gt;
&lt;p&gt;Use the helper script to test, build, and launch the agent:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# From project root (where dev/ exists)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pwsh&lt;/span&gt; &lt;span class="n"&gt;-NoProfile&lt;/span&gt; &lt;span class="n"&gt;-ExecutionPolicy&lt;/span&gt; &lt;span class="n"&gt;Bypass&lt;/span&gt; &lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ps1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This script will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;go test ./...&lt;/code&gt; (exits if tests fail)&lt;/li&gt;
&lt;li&gt;Build agent into &lt;code&gt;./bin/printmaster-agent.exe&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Start the built binary&lt;/li&gt;
&lt;li&gt;Open browser to &lt;code&gt;http://localhost:8080&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="manual-development-workflow"&gt;Manual Development Workflow&lt;/h3&gt;
&lt;p&gt;If you prefer manual control:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Run tests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;go&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="p"&gt;./...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Build (from project root)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;go&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="n"&gt;-o&lt;/span&gt; &lt;span class="p"&gt;./&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;printmaster-agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;exe&lt;/span&gt; &lt;span class="p"&gt;./&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Run the agent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;./&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;printmaster-agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;exe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Open UI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Start-Process&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;http://localhost:8080&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The launch script is intentionally conservative - tests must pass before build and server start.&lt;/p&gt;</description></item><item><title>Configuration Guide</title><link>https://docs.printmaster.work/guides/configuration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/guides/configuration/</guid><description>&lt;p&gt;Complete reference for configuring PrintMaster agent and server.&lt;/p&gt;
&lt;h2 id="table-of-contents"&gt;Table of Contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#configuration-methods"&gt;Configuration Methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#agent-configuration"&gt;Agent Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#server-configuration"&gt;Server Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#environment-variables"&gt;Environment Variables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#command-line-options"&gt;Command Line Options&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="configuration-methods"&gt;Configuration Methods&lt;/h2&gt;
&lt;p&gt;PrintMaster supports multiple configuration methods, applied in this order (later overrides earlier):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Built-in defaults&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration file&lt;/strong&gt; (&lt;code&gt;config.toml&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment variables&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Database-stored settings&lt;/strong&gt; (UI changes)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Command-line flags&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="configuration-file-location"&gt;Configuration File Location&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Platform&lt;/th&gt;
 &lt;th&gt;Agent Path&lt;/th&gt;
 &lt;th&gt;Server Path&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Windows&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;C:\ProgramData\PrintMaster\agent\config.toml&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;C:\ProgramData\PrintMaster\server\config.toml&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Linux&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/etc/printmaster/agent.toml&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/etc/printmaster/server.toml&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;macOS&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/Library/Application Support/PrintMaster/agent/config.toml&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/Library/Application Support/PrintMaster/server/config.toml&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Docker&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/var/lib/printmaster/agent/config.toml&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/var/lib/printmaster/server/config.toml&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Or place &lt;code&gt;config.toml&lt;/code&gt; in the same directory as the binary.&lt;/p&gt;</description></item><item><title>Contributing to PrintMaster</title><link>https://docs.printmaster.work/project/contributing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/project/contributing/</guid><description>&lt;p&gt;Thank you for your interest in contributing to PrintMaster! This document provides guidelines and information to help you get started.&lt;/p&gt;
&lt;h2 id="table-of-contents"&gt;Table of Contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#code-of-conduct"&gt;Code of Conduct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#getting-started"&gt;Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#development-setup"&gt;Development Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#project-structure"&gt;Project Structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#making-changes"&gt;Making Changes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#testing"&gt;Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#submitting-changes"&gt;Submitting Changes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#adding-printer-support"&gt;Adding Printer Support&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="code-of-conduct"&gt;Code of Conduct&lt;/h2&gt;
&lt;p&gt;Please be respectful and constructive in all interactions. We&amp;rsquo;re building something useful together.&lt;/p&gt;
&lt;h2 id="getting-started"&gt;Getting Started&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Fork the repository&lt;/strong&gt; on GitHub&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clone your fork&lt;/strong&gt; locally&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create a branch&lt;/strong&gt; for your changes&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone https://github.com/YOUR_USERNAME/printmaster.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; printmaster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout -b feature/your-feature-name
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="development-setup"&gt;Development Setup&lt;/h2&gt;
&lt;h3 id="prerequisites"&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Go 1.24+&lt;/strong&gt; - &lt;a href="https://go.dev/dl/"&gt;Download&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Git&lt;/strong&gt; - For version control&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PowerShell&lt;/strong&gt; (Windows) or Bash (Linux/macOS) - For build scripts&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="building"&gt;Building&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Windows - Build agent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ps1&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Windows - Build server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ps1&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Windows - Build both&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ps1&lt;/span&gt; &lt;span class="n"&gt;both&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="running-tests"&gt;Running Tests&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Test agent packages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;go&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="p"&gt;./...&lt;/span&gt; &lt;span class="n"&gt;-v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Test server packages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;go&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="p"&gt;./...&lt;/span&gt; &lt;span class="n"&gt;-v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="quick-development-workflow"&gt;Quick Development Workflow&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Windows - Kill existing processes, build, and launch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ps1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="project-structure"&gt;Project Structure&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;printmaster/
├── agent/ # Agent binary - printer discovery &amp;amp; monitoring
│ ├── scanner/ # SNMP scanning pipeline
│ │ └── vendor/ # Vendor-specific OID profiles
│ ├── storage/ # SQLite device/metrics storage
│ └── web/ # Embedded web UI
├── server/ # Server binary - multi-agent management
│ ├── handlers/ # HTTP API handlers
│ ├── storage/ # Database layer
│ └── web/ # Embedded web UI
├── common/ # Shared packages (logger, config, etc.)
└── docs/ # Design documentation
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Key documentation:&lt;/p&gt;</description></item><item><title>Deprecations and Removed Features</title><link>https://docs.printmaster.work/development/deprecations/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/deprecations/</guid><description>&lt;p&gt;This document tracks features that have been removed or are pending removal, with rationale and migration notes.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="removed-features"&gt;Removed Features&lt;/h2&gt;
&lt;h3 id="candidatemib-profile-workflow"&gt;Candidate/MIB Profile Workflow&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Status&lt;/strong&gt;: ✅ Removed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When&lt;/strong&gt;: Early 2025&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What&lt;/strong&gt;: Agent no longer loads or parses vendor candidate files or MIB profiles. All associated UI and HTTP endpoints removed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rationale&lt;/strong&gt;: Simplify agent, reduce maintenance cost, avoid tight coupling to vendor-specific data files&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migration&lt;/strong&gt;: None required. Discovery now relies on Printer-MIB and minimal vendor-agnostic heuristics&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cleanup&lt;/strong&gt;: Any data under &lt;code&gt;mib_profiles/&lt;/code&gt; can be deleted safely&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="sandbox-simulation"&gt;Sandbox Simulation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Status&lt;/strong&gt;: ✅ Removed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What&lt;/strong&gt;: Sandbox feature (simulate candidates against saved walks) removed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rationale&lt;/strong&gt;: Depended on candidates/MIB profiles; added complexity without core value&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migration&lt;/strong&gt;: Use built-in discovery and targeted diagnostic walks&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mib_walk-http-endpoint"&gt;&lt;code&gt;/mib_walk&lt;/code&gt; HTTP Endpoint&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Status&lt;/strong&gt;: ✅ Removed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What&lt;/strong&gt;: On-demand MIB walk HTTP endpoint&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rationale&lt;/strong&gt;: Encourage bounded, targeted walks inside discovery pipeline; avoid broad, ad-hoc walks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migration&lt;/strong&gt;: Use discovery and &amp;ldquo;Walk All&amp;rdquo; device action in UI where applicable; targeted walks occur automatically for confirmed printers&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="saved_ranges-http-endpoint"&gt;&lt;code&gt;/saved_ranges&lt;/code&gt; HTTP Endpoint&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Status&lt;/strong&gt;: ✅ Removed (Replaced)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When&lt;/strong&gt;: October 2025&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What&lt;/strong&gt;: Legacy IP ranges endpoint&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replacement&lt;/strong&gt;: Use unified &lt;code&gt;/settings&lt;/code&gt; endpoint (GET/POST for &lt;code&gt;discovery.ranges_text&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migration&lt;/strong&gt;:
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Old:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/saved_ranges&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// New:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/settings&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ranges&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;discovery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ranges_text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="manual-mib-walk-ui-functions"&gt;Manual MIB Walk UI Functions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Status&lt;/strong&gt;: ✅ Removed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Location&lt;/strong&gt;: &lt;code&gt;agent/web/app.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Functions&lt;/strong&gt;: &lt;code&gt;runMibWalk()&lt;/code&gt;, &lt;code&gt;runMibWalkFor(ip)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rationale&lt;/strong&gt;: Full device information now gathered automatically during discovery; deep scan pipeline provides comprehensive data collection&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migration&lt;/strong&gt;: Automated scanning provides all needed data&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="removed-features-previously-pending"&gt;Removed Features (Previously Pending)&lt;/h2&gt;
&lt;h3 id="old-logging-system"&gt;Old Logging System&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Status&lt;/strong&gt;: ✅ Removed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When&lt;/strong&gt;: December 2025&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Location&lt;/strong&gt;: Was in &lt;code&gt;agent/main.go&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Functions&lt;/strong&gt;: &lt;code&gt;logMsg(msg string)&lt;/code&gt;, &lt;code&gt;logMutex&lt;/code&gt;, &lt;code&gt;logBuffer []string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Description&lt;/strong&gt;: Simple timestamp-prefixed logging to in-memory buffer and file&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replacement&lt;/strong&gt;: Structured logger package (&lt;code&gt;common/logger/logger.go&lt;/code&gt;) - now used throughout codebase&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migration&lt;/strong&gt;: Complete - all logging now uses &lt;code&gt;appLogger&lt;/code&gt; structured logging&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="deprecated-still-supported"&gt;Deprecated (Still Supported)&lt;/h2&gt;
&lt;h3 id="settingssubnet_scan-http-endpoint"&gt;&lt;code&gt;/settings/subnet_scan&lt;/code&gt; HTTP Endpoint&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Status&lt;/strong&gt;: ⚠️ Deprecated (still works)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replacement&lt;/strong&gt;: Use &lt;code&gt;/settings&lt;/code&gt; endpoint (GET/POST for &lt;code&gt;discovery.subnet_scan&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migration&lt;/strong&gt;:
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Old:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/settings/subnet_scan&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// New:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/settings&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;discovery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_scan&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Removal Date&lt;/strong&gt;: v1.0 (will be removed in 1.0 release)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="migration-checklist"&gt;Migration Checklist&lt;/h2&gt;
&lt;p&gt;When removing deprecated code:&lt;/p&gt;</description></item><item><title>Device Report Proxy Worker</title><link>https://docs.printmaster.work/development/cloudflare-proxy-worker/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/cloudflare-proxy-worker/</guid><description>&lt;p&gt;This document describes the Cloudflare Worker that handles device diagnostic reports for PrintMaster.&lt;/p&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;The proxy worker receives diagnostic reports from PrintMaster agents, creates a GitHub Gist with the full diagnostic data, and returns URLs for creating a pre-filled GitHub issue.&lt;/p&gt;
&lt;h2 id="endpoint"&gt;Endpoint&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;URL&lt;/strong&gt;: &lt;code&gt;https://api.printmaster.work/diagnostic&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Method&lt;/strong&gt;: &lt;code&gt;POST&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Content-Type&lt;/strong&gt;: &lt;code&gt;application/json&lt;/code&gt;&lt;/p&gt;
&lt;h2 id="request-format"&gt;Request Format&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;report&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;report_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;RPT-18B2A3C4D5E6-1234&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2024-01-15T10:30:00Z&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;agent_version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0.25.7&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;windows&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;amd64&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;issue_type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;wrong_manufacturer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expected_value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;HP LaserJet Pro M404dn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;user_message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Device shows as Unknown instead of HP&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;device_ip&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;10.0.1.50&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;device_serial&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;VNC1234567&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;device_model&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;HP LaserJet Pro M404dn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;device_mac&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;00:11:22:33:44:55&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;current_manufacturer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Unknown&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;current_model&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Unknown Printer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;current_serial&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;VNC1234567&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;current_hostname&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;[hash:a1b2c3d4]&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;current_page_count&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;detected_vendor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Unknown&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;detection_steps&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Querying sysDescr (.1.3.6.1.2.1.1.1.0)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;No vendor match found&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;snmp_responses&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;oid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;.1.3.6.1.2.1.1.1.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;OctetString&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;HP LaserJet Pro M404dn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;hex_value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;recent_logs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;2024-01-15T10:29:55Z [INFO] Scanning device 10.0.1.50&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="response-format"&gt;Response Format&lt;/h2&gt;
&lt;h3 id="success-200-ok"&gt;Success (200 OK)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;gist_url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://gist.github.com/printmaster-bot/abc123def456&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;issue_url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://github.com/printmaster-org/printmaster/issues/new?template=device-report.yml&amp;amp;title=%5BDevice+Report%5D+wrong_manufacturer+%E2%80%93+HP+LaserJet+Pro+M404dn&amp;amp;gist_url=https%3A%2F%2Fgist.github.com%2Fprintmaster-bot%2Fabc123def456&amp;amp;issue_type=Wrong+manufacturer+detection&amp;amp;expected_value=HP+LaserJet+Pro+M404dn&amp;amp;device_model=HP+LaserJet+Pro+M404dn&amp;amp;device_manufacturer=Unknown&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="error-4xx5xx"&gt;Error (4xx/5xx)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Failed to create gist: rate limit exceeded&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="cloudflare-worker-implementation"&gt;Cloudflare Worker Implementation&lt;/h2&gt;
&lt;p&gt;Create a new Cloudflare Worker with the following code:&lt;/p&gt;</description></item><item><title>Docker Deployment</title><link>https://docs.printmaster.work/deployment/docker/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/deployment/docker/</guid><description>&lt;p&gt;Deploy PrintMaster Server using Docker containers with multi-architecture support.&lt;/p&gt;
&lt;h2 id="quick-start"&gt;Quick Start&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -d &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; --name printmaster-server &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; -p 9090:9090 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; -v printmaster-data:/var/lib/printmaster/server &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; -e &lt;span class="nv"&gt;ADMIN_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-secure-password &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; ghcr.io/printmaster-org/printmaster-server:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Access at &lt;code&gt;http://localhost:9090&lt;/code&gt; with username &lt;code&gt;admin&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="supported-architectures"&gt;Supported Architectures&lt;/h2&gt;
&lt;p&gt;All images are built for multiple architectures automatically:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Architecture&lt;/th&gt;
 &lt;th&gt;Platform&lt;/th&gt;
 &lt;th&gt;Use Case&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;linux/amd64&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;x86_64 servers&lt;/td&gt;
 &lt;td&gt;Intel/AMD servers, cloud VMs&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;linux/arm64&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;ARM 64-bit&lt;/td&gt;
 &lt;td&gt;Apple Silicon, AWS Graviton, Raspberry Pi 4+&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;linux/arm/v7&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;ARM 32-bit&lt;/td&gt;
 &lt;td&gt;Raspberry Pi 3/4 (32-bit OS)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Docker automatically pulls the correct architecture for your platform.&lt;/p&gt;</description></item><item><title>E2E Testing Strategy</title><link>https://docs.printmaster.work/development/testing/e2e-testing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/testing/e2e-testing/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;End-to-end tests verify that the agent and server work together correctly. These tests are more expensive than unit tests but provide confidence that the full system functions as expected.&lt;/p&gt;
&lt;h2 id="quick-start"&gt;Quick Start&lt;/h2&gt;
&lt;h3 id="run-e2e-tests-locally"&gt;Run E2E Tests Locally&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux/macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; tests
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./run-e2e.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; tests
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.&lt;span class="se"&gt;\r&lt;/span&gt;un-e2e.ps1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="options"&gt;Options&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Option&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--build&lt;/code&gt; / &lt;code&gt;-Build&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Force rebuild Docker containers&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--keep-up&lt;/code&gt; / &lt;code&gt;-KeepUp&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Leave containers running after tests&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--verbose&lt;/code&gt; / &lt;code&gt;-Verbose&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Show detailed output&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="architecture"&gt;Architecture&lt;/h2&gt;
&lt;h3 id="docker-compose-environment"&gt;Docker Compose Environment&lt;/h3&gt;
&lt;p&gt;The E2E tests use Docker Compose to create an isolated test environment:&lt;/p&gt;</description></item><item><title>Epson Enterprise OID Mapping</title><link>https://docs.printmaster.work/development/vendor/epson-oid-mapping/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/vendor/epson-oid-mapping/</guid><description>&lt;p&gt;&lt;strong&gt;Device&lt;/strong&gt;: AM-C550 Series (172.52.105.91)&lt;br&gt;
&lt;strong&gt;Enterprise OID Base&lt;/strong&gt;: &lt;code&gt;1.3.6.1.4.1.1248.1.2.2.27.*&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Validation Date&lt;/strong&gt;: 2025-11-03&lt;br&gt;
&lt;strong&gt;Status&lt;/strong&gt;: ✅ Fully validated against device web interface&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="direct-oid-mappings-no-calculation-needed"&gt;Direct OID Mappings (No Calculation Needed)&lt;/h2&gt;
&lt;h3 id="page-count-totals"&gt;Page Count Totals&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Metric&lt;/th&gt;
 &lt;th&gt;OID&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;th&gt;Status&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total Pages&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;.27.1.1.30.1.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;81,563&lt;/td&gt;
 &lt;td&gt;✅ Exact match&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total B&amp;amp;W Pages&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;.27.1.1.3.1.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;39,797&lt;/td&gt;
 &lt;td&gt;✅ Exact match&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total Color Pages&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;.27.1.1.4.1.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;41,766&lt;/td&gt;
 &lt;td&gt;✅ Exact match&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="function-specific-counters-combined-bw--color"&gt;Function-Specific Counters (Combined B&amp;amp;W + Color)&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Metric&lt;/th&gt;
 &lt;th&gt;OID&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;th&gt;Calculation&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total Print from Computer&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;.27.6.1.4.1.1.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;49,053&lt;/td&gt;
 &lt;td&gt;B&amp;amp;W Print (9,619) + Color Print (39,434) = 49,053 ✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total Copy&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;.27.6.1.4.1.1.2&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;32,474&lt;/td&gt;
 &lt;td&gt;B&amp;amp;W Copy (30,161) + Color Copy (2,313) = 32,474 ✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="color-specific-counters"&gt;Color-Specific Counters&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Metric&lt;/th&gt;
 &lt;th&gt;OID&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;th&gt;Status&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Color Print from Computer&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;.27.6.1.5.1.1.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;39,434&lt;/td&gt;
 &lt;td&gt;✅ Exact match&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Color Copy&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;.27.6.1.5.1.1.2&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;2,313&lt;/td&gt;
 &lt;td&gt;✅ Exact match&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="calculated-metrics-via-subtraction"&gt;Calculated Metrics (via Subtraction)&lt;/h2&gt;
&lt;h3 id="bw-function-breakdown"&gt;B&amp;amp;W Function Breakdown&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;B&amp;amp;W Print from Computer = Total Print from Computer - Color Print from Computer
 = 49,053 - 39,434
 = 9,619 ✅

B&amp;amp;W Copy = Total Copy - Color Copy
 = 32,474 - 2,313
 = 30,161 ✅
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="color-function-breakdown-if-needed"&gt;Color Function Breakdown (if needed)&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Color Print Other = Color Total - Color Print from Computer - Color Copy
 = 41,766 - 39,434 - 2,313
 = 19 ✅
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="bw-function-breakdown-if-needed"&gt;B&amp;amp;W Function Breakdown (if needed)&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;B&amp;amp;W Print Other = B&amp;amp;W Total - B&amp;amp;W Print from Computer - B&amp;amp;W Copy
 = 39,797 - 9,619 - 30,161
 = 17 ✅
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="scan-counters-not-yet-found-in-oids"&gt;Scan Counters (Not Yet Found in OIDs)&lt;/h2&gt;
&lt;p&gt;From web UI:&lt;/p&gt;</description></item><item><title>Epson Remote-Mode Integration Plan</title><link>https://docs.printmaster.work/development/epson-remote-mode-plan/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/epson-remote-mode-plan/</guid><description>&lt;p&gt;This document captures the concrete steps required to land Epson remote-mode support in the agent while keeping the feature isolated behind a flag and reusing the new SNMP batching helper.&lt;/p&gt;
&lt;h2 id="goals"&gt;Goals&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Reuse the remote-mode command surface documented in &lt;code&gt;docs/SNMP_RESEARCH_NOTES.md&lt;/code&gt; (commands &lt;code&gt;di&lt;/code&gt;, &lt;code&gt;st&lt;/code&gt;, &lt;code&gt;ia&lt;/code&gt;, &lt;code&gt;ii&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Surface reliable ink, maintenance-box, and alert data in &lt;code&gt;PrinterInfo&lt;/code&gt;/metrics without relying on sparse Printer-MIB leaves.&lt;/li&gt;
&lt;li&gt;Limit SNMP chatter by batching OIDs (already covered by &lt;code&gt;batchedGet&lt;/code&gt;) and caching EEPROM ranges per device.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="building-blocks"&gt;Building Blocks&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Batching helper&lt;/strong&gt; (&lt;code&gt;agent/scanner/snmp_batch.go&lt;/code&gt;): already available; use it whenever remote-mode helpers need scalar GETs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vendor module hook&lt;/strong&gt; (&lt;code&gt;agent/scanner/vendor/epson.go&lt;/code&gt;): entry point for calling the remote-mode helper from &lt;code&gt;MetricOIDs&lt;/code&gt;/&lt;code&gt;Parse&lt;/code&gt; whenever the feature flag is on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learned OID cache&lt;/strong&gt; (&lt;code&gt;agent/agent/types.go::LearnedOIDMap&lt;/code&gt;): add an &lt;code&gt;EpsonEEPROMWindows&lt;/code&gt; slice so we remember which address ranges returned data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feature flag plumbing&lt;/strong&gt;: add &lt;code&gt;epson_remote_mode_enabled&lt;/code&gt; to agent config, default false, surfaced through settings UI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage + downsampling&lt;/strong&gt;: extend &lt;code&gt;DeviceMetricsSnapshot&lt;/code&gt; to track &lt;code&gt;main_waste&lt;/code&gt;, &lt;code&gt;borderless_waste&lt;/code&gt;, &lt;code&gt;waste_box_3&lt;/code&gt; so they flow through existing downsamplers.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="implementation-steps"&gt;Implementation Steps&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Remote-mode transport helper&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Features Guide</title><link>https://docs.printmaster.work/guides/features/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/guides/features/</guid><description>&lt;p&gt;Complete guide to PrintMaster&amp;rsquo;s features and capabilities.&lt;/p&gt;
&lt;h2 id="table-of-contents"&gt;Table of Contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#device-discovery"&gt;Device Discovery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#device-monitoring"&gt;Device Monitoring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#multi-site-management"&gt;Multi-Site Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#websocket-proxy"&gt;WebSocket Proxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#alerts--notifications"&gt;Alerts &amp;amp; Notifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#scheduled-scans"&gt;Scheduled Scans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#auto-updates"&gt;Auto-Updates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#security-features"&gt;Security Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#api-access"&gt;API Access&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="device-discovery"&gt;Device Discovery&lt;/h2&gt;
&lt;p&gt;PrintMaster automatically discovers printers and copiers on your network using SNMP.&lt;/p&gt;
&lt;h3 id="how-discovery-works"&gt;How Discovery Works&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Port Scanning&lt;/strong&gt;: Quick TCP scan to find devices with printer ports open (80, 443, 9100)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SNMP Detection&lt;/strong&gt;: Query each candidate to confirm it&amp;rsquo;s a printer&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deep Scan&lt;/strong&gt;: Collect detailed device information via SNMP&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="discovery-methods"&gt;Discovery Methods&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Method&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;th&gt;When Used&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;IP Range Scan&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Scan a specified range of IP addresses&lt;/td&gt;
 &lt;td&gt;Manual configuration&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Subnet Auto-Scan&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Automatically scan local subnets&lt;/td&gt;
 &lt;td&gt;Default behavior&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Single Device&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Add a specific printer by IP&lt;/td&gt;
 &lt;td&gt;Known devices&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="supported-devices"&gt;Supported Devices&lt;/h3&gt;
&lt;p&gt;PrintMaster supports most SNMP-enabled printers and copiers, including:&lt;/p&gt;</description></item><item><title>Frequently Asked Questions</title><link>https://docs.printmaster.work/guides/faq/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/guides/faq/</guid><description>&lt;p&gt;Common questions about PrintMaster.&lt;/p&gt;
&lt;h2 id="general"&gt;General&lt;/h2&gt;
&lt;h3 id="what-is-printmaster"&gt;What is PrintMaster?&lt;/h3&gt;
&lt;p&gt;PrintMaster is a cross-platform printer/copier fleet management system. It automatically discovers network printers, collects device information (model, serial number, page counts, toner levels), and provides a web interface for monitoring your print fleet.&lt;/p&gt;
&lt;h3 id="who-is-printmaster-for"&gt;Who is PrintMaster for?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Managed Service Providers (MSPs)&lt;/strong&gt; - Monitor client print infrastructure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Managed Print Services (MPS) providers&lt;/strong&gt; - Track usage and supplies&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Copier dealers&lt;/strong&gt; - Manage devices across customer sites&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IT departments&lt;/strong&gt; - Monitor corporate print fleets&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="is-printmaster-free"&gt;Is PrintMaster free?&lt;/h3&gt;
&lt;p&gt;Yes, PrintMaster is open source and free to use under the MIT license.&lt;/p&gt;</description></item><item><title>Getting Started</title><link>https://docs.printmaster.work/guides/getting-started/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/guides/getting-started/</guid><description>&lt;p&gt;This guide walks you through your first steps with PrintMaster after installation.&lt;/p&gt;
&lt;h2 id="table-of-contents"&gt;Table of Contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#overview"&gt;Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#standalone-agent-setup"&gt;Standalone Agent Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#server--agent-setup"&gt;Server + Agent Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#discovering-printers"&gt;Discovering Printers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#understanding-the-dashboard"&gt;Understanding the Dashboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#next-steps"&gt;Next Steps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;PrintMaster can be used in two modes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Standalone Mode&lt;/strong&gt;: Run just the agent to monitor printers at a single site&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server Mode&lt;/strong&gt;: Run a central server with multiple agents across sites&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Choose the setup that matches your needs:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Use Case&lt;/th&gt;
 &lt;th&gt;Recommended Setup&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Single office, single network&lt;/td&gt;
 &lt;td&gt;Standalone Agent&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Multiple sites, centralized management&lt;/td&gt;
 &lt;td&gt;Server + Agents&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;MSP managing multiple clients&lt;/td&gt;
 &lt;td&gt;Server + Agents (multi-tenant)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="standalone-agent-setup"&gt;Standalone Agent Setup&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re monitoring printers at a single location, the standalone agent is all you need.&lt;/p&gt;</description></item><item><title>Git &amp; GitHub Integration - Complete ✅</title><link>https://docs.printmaster.work/development/git-integration-summary/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/git-integration-summary/</guid><description>&lt;h2 id="what-was-added"&gt;What Was Added&lt;/h2&gt;
&lt;h3 id="1-automated-release-script-releaseps1"&gt;1. Automated Release Script (&lt;code&gt;release.ps1&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Location&lt;/strong&gt;: &lt;code&gt;c:\temp\printmaster\release.ps1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Patch release (bug fixes)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ps1&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;patch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Minor release (new features)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ps1&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;minor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Major release (breaking changes)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ps1&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;major&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Release server or both&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ps1&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="n"&gt;patch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ps1&lt;/span&gt; &lt;span class="n"&gt;both&lt;/span&gt; &lt;span class="n"&gt;patch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;What it does automatically&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;✅ Checks if working directory is clean&lt;/li&gt;
&lt;li&gt;✅ Bumps version in VERSION file(s)&lt;/li&gt;
&lt;li&gt;✅ Runs all tests&lt;/li&gt;
&lt;li&gt;✅ Builds optimized release binary&lt;/li&gt;
&lt;li&gt;✅ Commits VERSION change&lt;/li&gt;
&lt;li&gt;✅ Creates git tag (e.g., v0.2.0)&lt;/li&gt;
&lt;li&gt;✅ Pushes to GitHub&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Flags&lt;/strong&gt;:&lt;/p&gt;</description></item><item><title>Installation Guide</title><link>https://docs.printmaster.work/guides/install/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/guides/install/</guid><description>&lt;p&gt;This guide covers installing PrintMaster on all supported platforms.&lt;/p&gt;
&lt;h2 id="table-of-contents"&gt;Table of Contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#quick-install"&gt;Quick Install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#server-installation"&gt;Server Installation&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#docker-recommended"&gt;Docker (Recommended)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#unraid"&gt;Unraid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#manual-server-installation"&gt;Manual Installation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#agent-installation"&gt;Agent Installation&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#windows"&gt;Windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#linux-debianubuntu"&gt;Linux (Debian/Ubuntu)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#linux-fedorarhel"&gt;Linux (Fedora/RHEL)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#macos"&gt;macOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#docker-agent"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#first-time-setup"&gt;First-Time Setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="quick-install"&gt;Quick Install&lt;/h2&gt;
&lt;h3 id="server-docker"&gt;Server (Docker)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -d &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; --name printmaster-server &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; -p 9090:9090 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; -v printmaster-data:/var/lib/printmaster/server &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; -e &lt;span class="nv"&gt;ADMIN_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-secure-password &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; ghcr.io/printmaster-org/printmaster-server:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Access at &lt;code&gt;http://localhost:9090&lt;/code&gt; with username &lt;code&gt;admin&lt;/code&gt; and your chosen password.&lt;/p&gt;
&lt;h3 id="agent-windows"&gt;Agent (Windows)&lt;/h3&gt;
&lt;p&gt;Download and run the MSI installer from &lt;a href="https://github.com/printmaster-org/printmaster/releases"&gt;GitHub Releases&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Kyocera Enterprise OID Mapping</title><link>https://docs.printmaster.work/development/vendor/kyocera-oid-mapping/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/vendor/kyocera-oid-mapping/</guid><description>&lt;p&gt;&lt;strong&gt;Device&lt;/strong&gt;: TASKalfa 6052ci (172.52.105.95)&lt;br&gt;
&lt;strong&gt;Serial&lt;/strong&gt;: W2D8303202&lt;br&gt;
&lt;strong&gt;Enterprise OID Base&lt;/strong&gt;: &lt;code&gt;1.3.6.1.4.1.1347.*&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Analysis Date&lt;/strong&gt;: 2025-11-03&lt;br&gt;
&lt;strong&gt;Status&lt;/strong&gt;: ✅ VALIDATED - Complete OID structure decoded&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;
&lt;p&gt;Kyocera devices provide &lt;strong&gt;exceptional detail&lt;/strong&gt; via enterprise OIDs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Standard Printer-MIB&lt;/strong&gt; provides total impressions (432,951)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kyocera &lt;code&gt;.42.3.*&lt;/code&gt; tree&lt;/strong&gt; provides complete function and color breakdown&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Direct OIDs available&lt;/strong&gt; for all major metrics (no calculation needed!)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best-in-class metrics&lt;/strong&gt; compared to other vendors&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="validated-oid-mappings"&gt;Validated OID Mappings&lt;/h2&gt;
&lt;h3 id="page-count-totals"&gt;Page Count Totals&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Metric&lt;/th&gt;
 &lt;th&gt;OID&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;th&gt;Validated&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total Impressions&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.2.1.43.10.2.1.4.1.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;432,951&lt;/td&gt;
 &lt;td&gt;✅ Standard Printer-MIB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total Printed Pages&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.43.10.1.1.12.1.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;424,405&lt;/td&gt;
 &lt;td&gt;✅ Kyocera Enterprise&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total B&amp;amp;W Printed&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;em&gt;Calculated&lt;/em&gt;&lt;/td&gt;
 &lt;td&gt;241,538&lt;/td&gt;
 &lt;td&gt;Sum of B&amp;amp;W functions&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total Color Printed&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;em&gt;Calculated&lt;/em&gt;&lt;/td&gt;
 &lt;td&gt;182,867&lt;/td&gt;
 &lt;td&gt;Sum of Color functions&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="kyocera-enterprise-oid-structure-423"&gt;Kyocera Enterprise OID Structure (&lt;code&gt;.42.3.*&lt;/code&gt;)&lt;/h3&gt;
&lt;h4 id="function-totals-423111"&gt;Function Totals (&lt;code&gt;.42.3.1.1.1.*&lt;/code&gt;)&lt;/h4&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Metric&lt;/th&gt;
 &lt;th&gt;OID&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;th&gt;Validated&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Printer Total&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.42.3.1.1.1.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;304,339&lt;/td&gt;
 &lt;td&gt;✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Copy Total&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.42.3.1.1.1.2&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;116,254&lt;/td&gt;
 &lt;td&gt;✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Fax Total&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.42.3.1.1.1.4&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;3,812&lt;/td&gt;
 &lt;td&gt;✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="print-breakdown-by-function-and-color-4231211"&gt;Print Breakdown by Function and Color (&lt;code&gt;.42.3.1.2.1.1.*&lt;/code&gt;)&lt;/h4&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Metric&lt;/th&gt;
 &lt;th&gt;OID&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;th&gt;Validated&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Printer B&amp;amp;W&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.42.3.1.2.1.1.1.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;163,915&lt;/td&gt;
 &lt;td&gt;✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Printer Color&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.42.3.1.2.1.1.1.3&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;140,424&lt;/td&gt;
 &lt;td&gt;✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Copy B&amp;amp;W&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.42.3.1.2.1.1.2.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;73,811&lt;/td&gt;
 &lt;td&gt;✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Copy Color&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.42.3.1.2.1.1.2.3&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;42,443&lt;/td&gt;
 &lt;td&gt;✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Fax B&amp;amp;W&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.42.3.1.2.1.1.4.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;3,812&lt;/td&gt;
 &lt;td&gt;✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="scan-counters-4231311"&gt;Scan Counters (&lt;code&gt;.42.3.1.3.1.1.*&lt;/code&gt;)&lt;/h4&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Metric&lt;/th&gt;
 &lt;th&gt;OID&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;th&gt;Validated&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Copy Scans&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.42.3.1.3.1.1.2&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;42,138&lt;/td&gt;
 &lt;td&gt;✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Fax Scans&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.42.3.1.3.1.1.4&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;3,057&lt;/td&gt;
 &lt;td&gt;✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Other Scans&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1.3.6.1.4.1.1347.42.3.1.4.1.1.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;43,441&lt;/td&gt;
 &lt;td&gt;✅&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="calculated-totals-validation"&gt;Calculated Totals (Validation)&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Total B&amp;amp;W Printed:
 Printer B&amp;amp;W (163,915) + Copy B&amp;amp;W (73,811) + Fax B&amp;amp;W (3,812) = 241,538 ✅

Total Color Printed:
 Printer Color (140,424) + Copy Color (42,443) + Fax Color (0) = 182,867 ✅

Total Printed:
 Printer (304,339) + Copy (116,254) + Fax (3,812) = 424,405 ✅

Total Scans:
 Copy Scans (42,138) + Fax Scans (3,057) + Other Scans (43,441) = 88,636 ✅
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="previously-found-oids-still-investigating"&gt;Previously Found OIDs (Still Investigating)&lt;/h3&gt;
&lt;h4 id="oid-pair-1-bw-vs-color-split"&gt;OID Pair 1: B&amp;amp;W vs Color Split&lt;/h4&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;OID&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;th&gt;Likely Meaning&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.43.10.1.1.16.1.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;221,912&lt;/td&gt;
 &lt;td&gt;B&amp;amp;W Total or Color Total?&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;em&gt;Calculated&lt;/em&gt;&lt;/td&gt;
 &lt;td&gt;211,039&lt;/td&gt;
 &lt;td&gt;Complementary (Total - 221,912)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Math Check&lt;/strong&gt;: 221,912 + 211,039 = 432,951 ✅&lt;/p&gt;</description></item><item><title>MIB profiles (mib_profiles/) and automation</title><link>https://docs.printmaster.work/components/agent/docs/mib-profiles/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/components/agent/docs/mib-profiles/</guid><description>&lt;p&gt;This document describes the lightweight JSON schema used to store manufacturer MIB profiles, recommended workflow for generating profiles from collected MIB walks, and how profiles can be distributed to agents.&lt;/p&gt;
&lt;p&gt;Schema (example keys)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;vendor&lt;/code&gt; (string): short vendor id, e.g. &amp;ldquo;hp&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;enterprise_oid&lt;/code&gt; (string): vendor enterprise prefix, e.g. &amp;ldquo;1.3.6.1.4.1.11&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;version&lt;/code&gt; (string): profile version&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canonical&lt;/code&gt; (map): semantic name -&amp;gt; OID (page_count, serial, supplies roots, etc.)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;probes&lt;/code&gt; (array): recommended quick probe OIDs that are safe/cheap to GET during discovery&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sample_values&lt;/code&gt; (map): example values to help human review and tests&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notes&lt;/code&gt; (string): freeform notes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Storage and runtime plan&lt;/p&gt;</description></item><item><title>PostgreSQL and TimescaleDB Upgrades</title><link>https://docs.printmaster.work/deployment/database-upgrade/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/deployment/database-upgrade/</guid><description>&lt;p&gt;PrintMaster&amp;rsquo;s Compose examples use &lt;code&gt;timescale/timescaledb:latest-pg18&lt;/code&gt; for new
deployments. The server supports PostgreSQL 18 and TimescaleDB through the
standard &lt;code&gt;pgx&lt;/code&gt; driver and TimescaleDB APIs.&lt;/p&gt;
&lt;h2 id="important-warning"&gt;Important warning&lt;/h2&gt;
&lt;p&gt;Changing &lt;code&gt;latest-pg15&lt;/code&gt; to &lt;code&gt;latest-pg18&lt;/code&gt; while keeping the existing
&lt;code&gt;/var/lib/postgresql&lt;/code&gt; volume will not perform a PostgreSQL major upgrade.
PostgreSQL 15 and 18 use incompatible data-directory formats. The container
will normally refuse to start, and deleting the volume would destroy data.&lt;/p&gt;
&lt;p&gt;For PG18, mount the volume at &lt;code&gt;/var/lib/postgresql&lt;/code&gt;, not
&lt;code&gt;/var/lib/postgresql/data&lt;/code&gt;. The PG18 image manages its version-specific data
directory below that root.&lt;/p&gt;</description></item><item><title>PrintMaster Overview</title><link>https://docs.printmaster.work/project/overview/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/project/overview/</guid><description>&lt;div align="center"&gt;
 &lt;img src="https://docs.printmaster.work/media/docs/images/banner.png" alt="Bridge Monitor" width="900"&gt;
&lt;p&gt;&lt;a href="https://github.com/printmaster-org/printmaster/actions/workflows/ci.yml"&gt;&lt;img src="https://github.com/printmaster-org/printmaster/actions/workflows/ci.yml/badge.svg" alt="CI"&gt;&lt;/a&gt;
&lt;a href="https://github.com/printmaster-org/printmaster/releases"&gt;&lt;img src="https://img.shields.io/github/v/release/printmaster-org/printmaster" alt="Release"&gt;&lt;/a&gt;
&lt;a href="https://github.com/printmaster-org/printmaster/pkgs/container/printmaster-server"&gt;&lt;img src="https://ghcr-badge.egpl.dev/printmaster-org/printmaster-server/latest_tag?trim=major&amp;amp;label=latest" alt="Docker"&gt;&lt;/a&gt;
&lt;a href="https://github.com/Printmaster-Org/printmaster/blob/565f4c0762e467f083f54a9e0e7f6bc23ada56c3/LICENSE"&gt;&lt;img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;PrintMaster automatically discovers and monitors network printers and copiers. Built for MSPs, MPS providers, copier dealers, and IT departments managing print fleets.&lt;/p&gt;
&lt;h2 id="why-printmaster"&gt;Why PrintMaster?&lt;/h2&gt;
&lt;p&gt;PrintMaster was born from real-world frustration managing multi-vendor print fleets. Existing solutions meant juggling multiple tools—PrintAudit for metering, Epson Remote Services for Epson devices, Kyocera Net Manager for Kyocera, Epson Device Admin for local management—each with their own quirks, agents that randomly disconnect, and per-device licensing fees.&lt;/p&gt;</description></item><item><title>PrintMaster Test Coverage Analysis</title><link>https://docs.printmaster.work/development/test-coverage-analysis/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/test-coverage-analysis/</guid><description>&lt;p&gt;&lt;strong&gt;Last Updated:&lt;/strong&gt; December 27, 2025&lt;/p&gt;
&lt;p&gt;This document provides a comprehensive analysis of test coverage across the PrintMaster codebase, identifying well-tested areas, gaps, and recommendations for improvement.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="executive-summary"&gt;Executive Summary&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Component&lt;/th&gt;
 &lt;th&gt;Test Files&lt;/th&gt;
 &lt;th&gt;Coverage Level&lt;/th&gt;
 &lt;th&gt;Priority for Improvement&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Server Storage&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;20+&lt;/td&gt;
 &lt;td&gt;⭐⭐⭐⭐⭐ Excellent&lt;/td&gt;
 &lt;td&gt;Low&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Agent Scanner&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;8&lt;/td&gt;
 &lt;td&gt;⭐⭐⭐⭐ Good&lt;/td&gt;
 &lt;td&gt;Medium&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Common Libraries&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;12&lt;/td&gt;
 &lt;td&gt;⭐⭐⭐⭐ Good&lt;/td&gt;
 &lt;td&gt;Low&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Server API/Handlers&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;td&gt;⭐⭐⭐ Moderate&lt;/td&gt;
 &lt;td&gt;Medium&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Agent Storage&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;6&lt;/td&gt;
 &lt;td&gt;⭐⭐⭐⭐ Good&lt;/td&gt;
 &lt;td&gt;Low&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Reports System&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;td&gt;⭐⭐⭐ Moderate&lt;/td&gt;
 &lt;td&gt;Medium&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;WebSocket/Proxy&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;⭐⭐⭐ Moderate&lt;/td&gt;
 &lt;td&gt;Medium&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;E2E Tests&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;td&gt;⭐⭐ Basic&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;HIGH&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Email Templates&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;0&lt;/td&gt;
 &lt;td&gt;⭐ None&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;HIGH&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Spooler (Windows)&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;0&lt;/td&gt;
 &lt;td&gt;⭐ None&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;HIGH&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Metrics Collector&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;0&lt;/td&gt;
 &lt;td&gt;⭐ None&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;HIGH&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Report Scheduler&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;0&lt;/td&gt;
 &lt;td&gt;⭐ None&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;HIGH&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;OIDC Handlers&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;0&lt;/td&gt;
 &lt;td&gt;⭐ None&lt;/td&gt;
 &lt;td&gt;Medium&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;JS/Frontend&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;14&lt;/td&gt;
 &lt;td&gt;⭐⭐⭐ Moderate&lt;/td&gt;
 &lt;td&gt;Medium&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="1-go-unit-tests-92-test-files"&gt;1. Go Unit Tests (92 test files)&lt;/h2&gt;
&lt;h3 id="11-server-package-server"&gt;1.1 Server Package (&lt;code&gt;server/&lt;/code&gt;)&lt;/h3&gt;
&lt;h4 id="-excellent-coverage"&gt;✅ Excellent Coverage&lt;/h4&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;File/Package&lt;/th&gt;
 &lt;th&gt;Tests&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;storage/*_test.go&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;20+ files&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;Most comprehensive testing&lt;/strong&gt; - Covers all CRUD operations, agents, devices, metrics, alerts, reports, users, sessions, tenants, settings, OIDC, dialects&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;main_test.go&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;30+ tests&lt;/td&gt;
 &lt;td&gt;Health endpoints, auth, heartbeat, batch uploads, token handling, device proxy parsing&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;config_test.go&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Multiple&lt;/td&gt;
 &lt;td&gt;Configuration loading/parsing&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;websocket_test.go&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;8+ tests&lt;/td&gt;
 &lt;td&gt;WebSocket connection, heartbeat, proxy requests&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Key storage tests:&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>PrintMaster TODO</title><link>https://docs.printmaster.work/development/todo/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/todo/</guid><description>&lt;p&gt;Consolidated pending features and improvements from across the codebase.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Current Version&lt;/strong&gt;: Agent v0.23.6, Server v0.23.6&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="-high-priority-pre-10"&gt;🔴 High Priority (Pre-1.0)&lt;/h2&gt;
&lt;h3 id="usb-printer-support"&gt;USB Printer Support&lt;/h3&gt;
&lt;p&gt;Implemented via an IPP-USB HTTP proxy (Windows only) — see
&lt;a href="https://docs.printmaster.work/development/usb-implementation/"&gt;USB_IMPLEMENTATION.md&lt;/a&gt;. The earlier pure-Go SNMP-over-USB
plan (&lt;code&gt;gousbsnmp&lt;/code&gt;) was abandoned and never built.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; IPP-USB proxy + web-scraped metrics (Windows)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Linux/macOS USB device enumeration + proxy support&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Same metrics as network printers (page counts, toner, supplies) - USB scraping is best-effort per vendor, not at parity yet&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; USB printer configuration UI&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; USB/network printer differentiation in main devices table (currently tracked separately)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="snmpv3-support"&gt;SNMPv3 Support&lt;/h3&gt;
&lt;p&gt;Security enhancement for enterprise deployments.&lt;/p&gt;</description></item><item><title>PROJECT STRUCTURE</title><link>https://docs.printmaster.work/development/project-structure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/project-structure/</guid><description>&lt;h2 id="project-structure-overview"&gt;Project Structure (Overview)&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;printmaster/
├── agent/ # Agent service and embedded UI (Go)
│ ├── main.go # Agent entrypoint
│ ├── config.go / config.toml # Agent configuration loader + sample
│ ├── agent/ # Discovery + protocol workers (mDNS, SSDP, etc.)
│ ├── scanner/ # SNMP pipeline, vendor registry, metrics extraction
│ ├── storage/ # Embedded SQLite schema + migrations
│ ├── proxy/ / supplies/ # Proxy tunnel + consumables helpers
│ ├── featureflags/ # Toggle definitions used by agent UI
│ ├── web/ # Embedded UI assets (built into the binary)
│ └── docs/ # Agent-specific reference material
├── server/ # Multi-agent server/API hub (Go)
│ ├── main.go # Server entrypoint
│ ├── config.go / config.toml # Server configuration + defaults
│ ├── websocket.go # Agent tunnel / live proxy handling
│ ├── storage/ # Server persistence + tenancy data
│ ├── authz/, logger/, tls.go # Auxiliary subsystems
│ └── web/ # Server UI + static assets
├── common/ # Shared Go modules (config, logger, snmp, util, web)
├── docs/ # Architecture + operations documentation
├── dev/ # Local developer scripts (e.g., launch.ps1)
├── scripts/ # Operational PowerShell helpers (kill, update, etc.)
├── tools/ # Standalone utilities and generators
├── tests/ # Integration / e2e test harnesses
├── static/ # Third-party front-end assets (e.g., flatpickr)
├── ui/ # Legacy UI experiments (kept for reference)
├── logs/, test-results/ # Output folders (ignored in git)
├── build.ps1 / release.ps1 # Build + release orchestration
└── README.md # High-level overview
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="module-descriptions"&gt;Module Descriptions&lt;/h2&gt;
&lt;h3 id="agent-agent"&gt;Agent (&lt;code&gt;agent/&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;Single-binary agent that discovers printers, collects metrics, persists to SQLite, and serves the embedded UI. Key subpackages:&lt;/p&gt;</description></item><item><title>Range syntax and parsing rules</title><link>https://docs.printmaster.work/development/range-syntax/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/range-syntax/</guid><description>&lt;p&gt;This file documents what the server accepts in the range editor textarea and how the &lt;code&gt;ParseRangeText&lt;/code&gt; behavior works.&lt;/p&gt;
&lt;p&gt;Supported formats&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Single IPv4 address: e.g. &lt;code&gt;192.168.1.42&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;CIDR notation: e.g. &lt;code&gt;192.168.1.0/24&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Full range (start-end): e.g. &lt;code&gt;192.168.1.10-192.168.1.20&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Short-hand range (right side maps to last N octets):
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;192.168.1.10-20&lt;/code&gt; expands to &lt;code&gt;192.168.1.10&lt;/code&gt; through &lt;code&gt;192.168.1.20&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;10-20&lt;/code&gt; is interpreted relative to the default/prepended subnet only when configured in the UI as Add/Override behavior.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Last-octet wildcard: &lt;code&gt;192.168.1.x&lt;/code&gt; or &lt;code&gt;192.168.1.*&lt;/code&gt; (expands the last octet 0..255)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Behaviors and constraints&lt;/p&gt;</description></item><item><title>REMAINING TASKS</title><link>https://docs.printmaster.work/components/agent/docs/remaining-tasks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/components/agent/docs/remaining-tasks/</guid><description>&lt;p&gt;Remaining tasks for Printer MIB pairing &amp;amp; candidate workflows&lt;/p&gt;
&lt;p&gt;Overview&lt;/p&gt;
&lt;p&gt;This document lists remaining work items, priorities, acceptance criteria, and testing notes for the features implemented during the recent changes: pairing of list columns (name/level) from saved MIB walks, UI flow to inspect saved walks, and persisting candidate mappings.&lt;/p&gt;
&lt;p&gt;High-level goals&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Let the agent detect and present column-based consumable information (e.g. toner names and levels) from saved MIB walks.&lt;/li&gt;
&lt;li&gt;Allow users to persist discovered column mappings into vendor candidate profiles quickly and reliably.&lt;/li&gt;
&lt;li&gt;Provide robust normalization and tests for edge-cases across vendors.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Priority tasks&lt;/p&gt;</description></item><item><title>Security Architecture for Agent-Server Communication</title><link>https://docs.printmaster.work/development/security-architecture/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/security-architecture/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;This document outlines the security architecture for when the PrintMaster agent communicates with a central server, particularly for the reverse proxy feature where the server may relay connections between users and printers through the agent.&lt;/p&gt;
&lt;h2 id="threat-model"&gt;Threat Model&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Agent → Server&lt;/strong&gt;: Agent authenticates to server, sends discovery data, receives config&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User → Server → Agent → Printer&lt;/strong&gt;: User accesses printer web UI through server proxy that routes through agent&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key Risks&lt;/strong&gt;: Unauthorized agent access, credential interception, session hijacking, MITM attacks, unauthorized printer access&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="security-layers"&gt;Security Layers&lt;/h2&gt;
&lt;h3 id="1-agent-authentication-mvp"&gt;1. Agent Authentication (MVP)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Verify agent identity before accepting connections or data uploads.&lt;/p&gt;</description></item><item><title>Security Policy</title><link>https://docs.printmaster.work/project/security/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/project/security/</guid><description>&lt;h2 id="supported-versions"&gt;Supported Versions&lt;/h2&gt;
&lt;p&gt;We release security patches for the following versions:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Component&lt;/th&gt;
 &lt;th&gt;Version&lt;/th&gt;
 &lt;th&gt;Supported&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Agent&lt;/td&gt;
 &lt;td&gt;latest&lt;/td&gt;
 &lt;td&gt;:white_check_mark:&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Server&lt;/td&gt;
 &lt;td&gt;latest&lt;/td&gt;
 &lt;td&gt;:white_check_mark:&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;We recommend always running the latest version for the best security.&lt;/p&gt;
&lt;h2 id="reporting-a-vulnerability"&gt;Reporting a Vulnerability&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Please do not report security vulnerabilities through public GitHub issues.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Instead, please report them privately via one of these methods:&lt;/p&gt;
&lt;h3 id="option-1-github-security-advisories-preferred"&gt;Option 1: GitHub Security Advisories (Preferred)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Go to the &lt;a href="https://github.com/printmaster-org/printmaster/security"&gt;Security tab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Click &amp;ldquo;Report a vulnerability&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Fill out the form with details&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="option-2-email"&gt;Option 2: Email&lt;/h3&gt;
&lt;p&gt;Send details to the repository owner via GitHub (check profile for contact info).&lt;/p&gt;</description></item><item><title>Service Mode - Quick Reference</title><link>https://docs.printmaster.work/components/agent/service/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/components/agent/service/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;PrintMaster Agent can run as a system service for production deployments. This ensures the agent starts automatically on boot and runs continuously in the background.&lt;/p&gt;
&lt;h2 id="commands"&gt;Commands&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Install service (requires admin/root)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;printmaster-agent --service install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Start service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;printmaster-agent --service start
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Stop service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;printmaster-agent --service stop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Uninstall service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;printmaster-agent --service uninstall
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Run in foreground (testing)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;printmaster-agent --service run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Interactive mode (default)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;printmaster-agent
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="platform-specific-details"&gt;Platform-Specific Details&lt;/h2&gt;
&lt;h3 id="windows"&gt;Windows&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;: Administrator privileges&lt;/p&gt;</description></item><item><title>SNMP Reference Guide</title><link>https://docs.printmaster.work/development/snmp-reference/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/snmp-reference/</guid><description>&lt;p&gt;This document covers SNMP discovery, Printer-MIB OIDs, vendor detection, metrics collection, and meter history tracking in PrintMaster.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;PrintMaster uses SNMP (Simple Network Management Protocol) to discover and monitor network printers. The implementation follows a &lt;strong&gt;two-phase scan approach&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Phase 1 (Quick Probe)&lt;/strong&gt; - Small number of SNMP GETs to quickly verify device is a printer&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 2 (Deep Scan)&lt;/strong&gt; - Targeted walk for confirmed printers to gather detailed metrics&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This approach keeps discovery fast on large networks while still capturing rich vendor-specific data.&lt;/p&gt;</description></item><item><title>SNMP Research Notes</title><link>https://docs.printmaster.work/development/snmp-research-notes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/snmp-research-notes/</guid><description>&lt;p&gt;This file captures actionable takeaways from inspecting other open-source SNMP printer discovery/management tools so we can fold the best ideas into PrintMaster without blindly copying code.&lt;/p&gt;
&lt;h2 id="sources-consulted"&gt;Sources Consulted&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Ircama/epson_print_conf&lt;/code&gt; (Python) — exhaustive remote-mode OIDs plus EEPROM decoding for dozens of Epson models (&lt;a href="https://raw.githubusercontent.com/Ircama/epson_print_conf/main/epson_print_conf.py"&gt;epson_print_conf.py&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;CUPS SNMP backend (&lt;code&gt;backend/snmp.c&lt;/code&gt;) — hardened discovery logic with vendor-specific fallbacks (&lt;a href="https://raw.githubusercontent.com/OpenPrinting/cups/master/backend/snmp.c"&gt;OpenPrinting/cups&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="standard-oids-we-should-poll-everywhere"&gt;Standard OIDs We Should Poll Everywhere&lt;/h2&gt;
&lt;p&gt;These came up repeatedly in both projects and map cleanly to our existing data model:&lt;/p&gt;</description></item><item><title>Testing and CI guidelines</title><link>https://docs.printmaster.work/development/testing-ci/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/testing-ci/</guid><description>&lt;p&gt;This document describes how to write fast, deterministic tests for the PrintMaster agent and server.&lt;/p&gt;
&lt;h2 id="test-types"&gt;Test Types&lt;/h2&gt;
&lt;p&gt;PrintMaster has three levels of testing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Unit Tests&lt;/strong&gt; - Test individual functions/packages in isolation (&lt;code&gt;agent/&lt;/code&gt;, &lt;code&gt;server/&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration Tests&lt;/strong&gt; - Test component interactions (e.g., database rotation)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;End-to-End Tests&lt;/strong&gt; - Test full agent-server communication (see &lt;code&gt;tests/&lt;/code&gt; directory)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For E2E test details, see &lt;a href="https://docs.printmaster.work/development/testing/e2e-testing/"&gt;&lt;code&gt;../tests/E2E_TESTING.md&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="why-mocking-is-necessary"&gt;Why mocking is necessary&lt;/h2&gt;
&lt;hr&gt;
&lt;p&gt;Network operations (ICMP, TCP connect, SNMP Get/Walk) are slow and flaky in CI. Unit tests must avoid touching the real network so they remain fast and reliable. The project uses small package-level factories and interfaces to make mocking easy.&lt;/p&gt;</description></item><item><title>Troubleshooting Guide</title><link>https://docs.printmaster.work/guides/troubleshooting/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/guides/troubleshooting/</guid><description>&lt;p&gt;Solutions for common PrintMaster issues.&lt;/p&gt;
&lt;h2 id="table-of-contents"&gt;Table of Contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#discovery-issues"&gt;Discovery Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#connection-issues"&gt;Connection Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#web-ui-issues"&gt;Web UI Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#service-issues"&gt;Service Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#database-issues"&gt;Database Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#performance-issues"&gt;Performance Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#logs--diagnostics"&gt;Logs &amp;amp; Diagnostics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="discovery-issues"&gt;Discovery Issues&lt;/h2&gt;
&lt;h3 id="no-printers-found"&gt;No Printers Found&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptoms&lt;/strong&gt;: Scan completes but no devices appear.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solutions&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Verify network connectivity&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Can you reach the printer?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ping 192.168.1.100
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Check SNMP is enabled on the printer&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Access the printer&amp;rsquo;s web interface&lt;/li&gt;
&lt;li&gt;Look for SNMP settings in Network or Security&lt;/li&gt;
&lt;li&gt;Ensure SNMP v1/v2c is enabled&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Verify the SNMP community string&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Unraid Deployment</title><link>https://docs.printmaster.work/deployment/unraid/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/deployment/unraid/</guid><description>&lt;p&gt;Deploy PrintMaster Server on Unraid using the Docker container.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="installation-methods"&gt;Installation Methods&lt;/h2&gt;
&lt;h3 id="method-1-community-applications-recommended"&gt;Method 1: Community Applications (Recommended)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;strong&gt;Community Applications&lt;/strong&gt; plugin if not already installed&lt;/li&gt;
&lt;li&gt;Search for &amp;ldquo;PrintMaster Server&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Install&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Configure settings (see below)&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Apply&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="method-2-manual-docker-setup"&gt;Method 2: Manual Docker Setup&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Docker&lt;/strong&gt; tab in Unraid&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add Container&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Configure:&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Setting&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Name&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;PrintMaster-Server&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Repository&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ghcr.io/printmaster-org/printmaster-server:latest&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Network Type&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Bridge&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Port&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;9090&lt;/code&gt; → &lt;code&gt;9090&lt;/code&gt; (TCP)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Volume&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/mnt/user/appdata/printmaster-server/data&lt;/code&gt; → &lt;code&gt;/var/lib/printmaster/server&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Volume&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/mnt/user/appdata/printmaster-server/logs&lt;/code&gt; → &lt;code&gt;/var/log/printmaster/server&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="configuration"&gt;Configuration&lt;/h2&gt;
&lt;h3 id="essential-settings"&gt;Essential Settings&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Setting&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;HTTP Port&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;9090&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Web interface and API&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Data Directory&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/mnt/user/appdata/printmaster-server/data&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Database storage&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Logs Directory&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/mnt/user/appdata/printmaster-server/logs&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Application logs&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Timezone&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Your timezone (e.g., &lt;code&gt;America/New_York&lt;/code&gt;)&lt;/td&gt;
 &lt;td&gt;For correct timestamps&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="environment-variables"&gt;Environment Variables&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Variable&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;BIND_ADDRESS&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;0.0.0.0&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Allow external access&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;BEHIND_PROXY&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Behind Nginx Proxy Manager?&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;LOG_LEVEL&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;info&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;debug&lt;/code&gt;, &lt;code&gt;info&lt;/code&gt;, &lt;code&gt;warn&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;TZ&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;America/New_York&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Your timezone&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;PM_DISABLE_SELFUPDATE&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Recommended for Docker&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="reverse-proxy-setup"&gt;Reverse Proxy Setup&lt;/h2&gt;
&lt;h3 id="with-nginx-proxy-manager"&gt;With Nginx Proxy Manager&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Set container variables:&lt;/p&gt;</description></item><item><title>USB Printer Support</title><link>https://docs.printmaster.work/development/usb-implementation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/usb-implementation/</guid><description>&lt;p&gt;&lt;strong&gt;Status&lt;/strong&gt;: ✅ Implemented (Windows only)&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;
&lt;p&gt;USB printer support is implemented as an &lt;strong&gt;IPP-USB HTTP proxy&lt;/strong&gt;, not the SNMP-over-USB
approach originally planned (see &amp;ldquo;Abandoned approach&amp;rdquo; below). The agent enumerates
USB printers that expose an embedded web UI over the IPP-USB interface class, then
tunnels HTTP requests to that web UI over the USB bulk endpoints — the same
approach used by &lt;a href="https://github.com/OpenPrinting/ipp-usb"&gt;OpenPrinting/ipp-usb&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Metrics (page counts, toner levels, etc.) are obtained by scraping the printer&amp;rsquo;s
embedded web UI/XML endpoints, not by querying SNMP OIDs over USB.&lt;/p&gt;</description></item><item><title>Vendor Meter Analysis from Production Logs</title><link>https://docs.printmaster.work/development/vendor/vendor-meter-analysis/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/vendor/vendor-meter-analysis/</guid><description>&lt;p&gt;&lt;strong&gt;Date&lt;/strong&gt;: November 3, 2025&lt;br&gt;
&lt;strong&gt;Source&lt;/strong&gt;: logs_20251103_064511.zip analysis&lt;br&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Identify meter detection gaps and opportunities for vendor-specific OID improvements&lt;/p&gt;
&lt;h2 id="executive-summary"&gt;Executive Summary&lt;/h2&gt;
&lt;p&gt;Analysis of 10 production devices revealed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;All devices&lt;/strong&gt; successfully report page counts during discovery (standard Printer-MIB)&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Metrics collection fails&lt;/strong&gt; with zeros despite OIDs being correct&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Root cause&lt;/strong&gt;: SNMP GET queries fail where WALK succeeds&lt;/li&gt;
&lt;li&gt;💡 &lt;strong&gt;Solution&lt;/strong&gt;: Learned OID system (already implemented) will fix this&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Opportunity&lt;/strong&gt;: Vendor-specific enterprise OIDs offer additional counters&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="device-breakdown"&gt;Device Breakdown&lt;/h2&gt;
&lt;h3 id="1-epson-am-c550-series-1725210591--validated"&gt;1. Epson AM-C550 Series (172.52.105.91) ✅ VALIDATED&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Current Status&lt;/strong&gt;: ❌ Metrics returning 0 despite discovery finding 81,563 pages&lt;br&gt;
&lt;strong&gt;Vendor Module&lt;/strong&gt;: Generic (no Epson module exists)&lt;br&gt;
&lt;strong&gt;Discovery OID&lt;/strong&gt;: &lt;code&gt;1.3.6.1.2.1.43.10.2.1.4.1.1&lt;/code&gt; = 81,563 ✅
&lt;strong&gt;Validation Date&lt;/strong&gt;: 2025-11-03&lt;/p&gt;</description></item><item><title>WebSocket HTTP Proxy Feature</title><link>https://docs.printmaster.work/development/websocket-proxy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.printmaster.work/development/websocket-proxy/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;The PrintMaster system now supports proxying HTTP requests through the WebSocket connection between agents and the server. This allows you to access:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Agent web UIs from anywhere (even behind NAT/firewalls)&lt;/li&gt;
&lt;li&gt;Device web UIs (printer admin pages) through the agent&amp;rsquo;s network connection&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="architecture"&gt;Architecture&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Browser → Server → WebSocket → Agent → Target (Agent UI or Device)
 ← ← ← ←
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="flow"&gt;Flow&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;User clicks &amp;ldquo;Open UI&amp;rdquo; button&lt;/strong&gt; in the server web interface&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Browser makes HTTP request&lt;/strong&gt; to server proxy endpoint&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server converts HTTP request&lt;/strong&gt; to WebSocket message (&lt;code&gt;proxy_request&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server sends message&lt;/strong&gt; through WebSocket to connected agent&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent receives proxy request&lt;/strong&gt; and makes local HTTP request to target&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent sends HTTP response&lt;/strong&gt; back through WebSocket (&lt;code&gt;proxy_response&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server forwards response&lt;/strong&gt; to browser&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="websocket-protocol"&gt;WebSocket Protocol&lt;/h2&gt;
&lt;h3 id="message-types"&gt;Message Types&lt;/h3&gt;
&lt;h4 id="proxy_request-server--agent"&gt;&lt;code&gt;proxy_request&lt;/code&gt; (Server → Agent)&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;proxy_request&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;request_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;unique-id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://localhost:8080/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;method&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;headers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;User-Agent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;...&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Accept&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;body&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;base64-encoded-body&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2025-11-07T12:00:00Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="proxy_response-agent--server"&gt;&lt;code&gt;proxy_response&lt;/code&gt; (Agent → Server)&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;proxy_response&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;request_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;unique-id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;status_code&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;headers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;text/html&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Content-Length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1234&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;body&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;base64-encoded-response-body&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2025-11-07T12:00:01Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="api-endpoints"&gt;API Endpoints&lt;/h2&gt;
&lt;h3 id="agent-ui-proxy"&gt;Agent UI Proxy&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;GET /api/v1/proxy/agent/{agentID}/{path...}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Proxies HTTP requests to the agent&amp;rsquo;s own web UI (typically running on &lt;code&gt;http://localhost:8080&lt;/code&gt;).&lt;/p&gt;</description></item></channel></rss>