# NUPST Project Hints ## Recent Refactoring (January 2026) ### Phase 1 - Quick Wins 1. **Prompt Utility (`ts/helpers/prompt.ts`)** - Extracted readline/prompt pattern from all CLI handlers - Provides `createPrompt()` and `withPrompt()` helper functions - Used in: `ups-handler.ts`, `group-handler.ts`, `service-handler.ts`, `action-handler.ts`, `feature-handler.ts` 2. **Constants File (`ts/constants.ts`)** - Centralized all magic numbers (timeouts, intervals, thresholds) - Contains: `TIMING`, `SNMP`, `THRESHOLDS`, `WEBHOOK`, `SCRIPT`, `SHUTDOWN`, `HTTP_SERVER`, `UI`, `NETWORK`, `UPSD`, `PAUSE`, `PROXMOX` - Used in: `daemon.ts`, `snmp/manager.ts`, `actions/*.ts`, `upsd/client.ts` 3. **Logger Consistency** - Replaced all `console.log/console.error` in `snmp/manager.ts` with proper `logger.*` calls - Debug output uses `logger.dim()` for less intrusive output ### Phase 2 - Type Safety 4. **Circular Dependency Fix (`ts/interfaces/nupst-accessor.ts`)** - Created `INupstAccessor` interface to break the circular dependency between `Nupst` and `NupstSnmp` - `NupstSnmp.nupst` property now uses the interface instead of `any` 5. **Webhook Payload Interface (`ts/actions/webhook-action.ts`)** - Added `IWebhookPayload` interface for webhook action payloads - Exported from `ts/actions/index.ts` 6. **CLI Handler Type Safety** - Replaced `any` types in `ups-handler.ts` and `group-handler.ts` with proper interfaces - Uses: `IUpsConfig`, `INupstConfig`, `ISnmpConfig`, `IActionConfig`, `IThresholds`, `ISnmpUpsStatus` 7. **SNMP Manager Boundary Types (`ts/snmp/manager.ts`)** - Added local wrapper interfaces for the untyped `net-snmp` package surface used by NUPST - SNMP metric reads now coerce values explicitly instead of relying on `any`-typed responses ## Features Added (February 2026) ### Network Loss Handling - `TPowerStatus` extended with `'unreachable'` state - `IUpsStatus` has `consecutiveFailures` and `unreachableSince` tracking - After `NETWORK.CONSECUTIVE_FAILURE_THRESHOLD` (3) failures, UPS transitions to `unreachable` - Shutdown action explicitly won't fire on `unreachable` (prevents false shutdowns) - Recovery is logged when UPS comes back from unreachable ### UPSD/NIS Protocol Support - New `ts/upsd/` directory with TCP client for NUT (Network UPS Tools) servers - `ts/protocol/` directory with `ProtocolResolver` for protocol-agnostic status queries - `IUpsConfig.protocol` field: `'snmp'` (default) or `'upsd'` - `IUpsConfig.snmp` is now optional (not needed for UPSD devices) - CLI supports protocol selection during `nupst ups add` - Config version is now `4.3`, including the `4.2` -> `4.3` runtime unit migration ### Pause/Resume Command - File-based signaling via `/etc/nupst/pause` JSON file - `nupst pause [--duration 30m|2h|1d]` creates pause file - `nupst resume` deletes pause file - `ts/pause-state.ts` owns pause snapshot parsing and transition detection for daemon polling - Daemon polls continue but actions are suppressed while paused - Auto-resume after duration expires - HTTP API includes pause state in response ### Shutdown Orchestration - `ts/shutdown-executor.ts` owns command discovery and fallback execution for delayed and emergency shutdowns - `ts/daemon.ts` now delegates OS shutdown execution instead of embedding command lookup logic inline - `defaultShutdownDelay` in config provides the inherited delay for shutdown actions without an explicit `shutdownDelay` override ### Config Watch Handling - `ts/config-watch.ts` owns file-watch event matching and config-reload transition analysis - `ts/daemon.ts` now delegates config/pause watch event classification and reload messaging decisions ### UPS Status Tracking - `ts/ups-status.ts` owns the daemon UPS status shape and default status factory - `ts/daemon.ts` now reuses a shared initializer instead of duplicating the default UPS status object ### UPS Monitoring Transitions - `ts/ups-monitoring.ts` owns pure UPS poll success/failure transition logic and threshold detection - `ts/daemon.ts` now orchestrates protocol calls and logging while delegating state transitions ### Action Orchestration - `ts/action-orchestration.ts` owns action context construction and action execution decisions - `ts/daemon.ts` now delegates pause suppression, legacy shutdown fallback, and action context building ### Shutdown Monitoring - `ts/shutdown-monitoring.ts` owns shutdown-loop row building and emergency candidate selection - `ts/daemon.ts` now keeps the shutdown loop orchestration while delegating row/emergency decisions ### Proxmox VM Shutdown Action - New action type `'proxmox'` in `ts/actions/proxmox-action.ts` - Uses Proxmox REST API with PVEAPIToken authentication - Shuts down QEMU VMs and LXC containers before host shutdown - Supports: exclude IDs, configurable timeout, force-stop, TLS skip for self-signed certs - Should be placed BEFORE shutdown actions in the action chain ## Architecture Notes - **SNMP Manager**: Uses `INupstAccessor` interface (not direct `Nupst` reference) to avoid circular imports - **Protocol Resolver**: Routes to SNMP or UPSD based on `IUpsConfig.protocol` - **CLI Handlers**: All use the `helpers.withPrompt()` utility for interactive input - **Constants**: All timing values should be referenced from `ts/constants.ts` - **Actions**: Use `IActionConfig` from `ts/actions/base-action.ts` for action configuration - **Action orchestration**: Use helpers from `ts/action-orchestration.ts` for action context and execution decisions - **Config watch logic**: Use helpers from `ts/config-watch.ts` for file event filtering and reload transitions - **Pause state**: Use `loadPauseSnapshot()` and `IPauseState` from `ts/pause-state.ts` - **Shutdown execution**: Use `ShutdownExecutor` for OS-level shutdown command lookup and fallbacks - **Shutdown monitoring**: Use helpers from `ts/shutdown-monitoring.ts` for emergency loop rows and candidate selection - **UPS status state**: Use `IUpsStatus` and `createInitialUpsStatus()` from `ts/ups-status.ts` - **UPS poll transitions**: Use helpers from `ts/ups-monitoring.ts` for success/failure updates - **Config version**: Currently `4.3`, migrations run automatically ## File Organization ``` ts/ ├── constants.ts # All timing/threshold constants ├── action-orchestration.ts # Action context and execution decisions ├── config-watch.ts # File watch filters and config reload transitions ├── shutdown-monitoring.ts # Shutdown loop rows and emergency selection ├── ups-monitoring.ts # Pure UPS poll transition and threshold helpers ├── pause-state.ts # Shared pause state types and transition detection ├── shutdown-executor.ts # Delayed/emergency shutdown command execution ├── ups-status.ts # Daemon UPS status shape and initializer ├── interfaces/ │ └── nupst-accessor.ts # Interface to break circular deps ├── helpers/ │ ├── prompt.ts # Readline utility │ └── shortid.ts # ID generation ├── actions/ │ ├── base-action.ts # Base action class, IActionConfig, TPowerStatus │ ├── webhook-action.ts # Includes IWebhookPayload │ ├── proxmox-action.ts # Proxmox VM/LXC shutdown │ └── ... ├── upsd/ │ ├── types.ts # IUpsdConfig │ ├── client.ts # NupstUpsd TCP client │ └── index.ts ├── protocol/ │ ├── types.ts # TProtocol = 'snmp' | 'upsd' │ ├── resolver.ts # ProtocolResolver │ └── index.ts ├── migrations/ │ ├── migration-runner.ts │ └── migration-v4.2-to-v4.3.ts # Adds SNMP runtimeUnit defaults └── cli/ └── ... # All handlers use helpers.withPrompt() ```