directlx-claude-config/plans/wise-dancing-shore.md

1749 lines
52 KiB
Markdown

# HiveOps Browser: Protocol Handling, Licensing & User Management
## Overview
Add domain-based protocol handling (*.hiveops.com), external API-based licensing system with full feature controls (activation, tiers, expiration), and user authentication (license key + user profile).
**Architecture**: Two-component system:
1. **hiveops-browser** (Electron app) - Desktop client with protocol handling and licensing enforcement
2. **hiveops-mgmt** (Spring Boot 4 microservice) - Central management service for licensing, user profiles, and global settings
## Requirements Summary
- **Protocol Handling**: Domain-based (*.hiveops.com) and custom protocol (hiveops://)
- **Licensing**: External API service with full controls (activation, feature-based tiers, time-based expiration)
- **Authentication**: License key + User profile system
- **License Tiers**: Basic, Pro, Enterprise (each with different feature sets)
- **Backend**: Spring Boot 4 microservice with PostgreSQL database
- **Repository**: Separate repository for hiveops-mgmt microservice
## Implementation Plan
### 1. Core License Management Infrastructure
#### 1.1 Create License Manager Module
**File**: `src/main/license-manager.js` (NEW)
Core responsibilities:
- Validate license key format (XXXXX-XXXXX-XXXXX-XXXXX-XXXXX)
- Store/retrieve license data using encrypted electron-store
- Verify license signatures (anti-tamper using HMAC-SHA256)
- Check license validity (expiration, signature)
- Feature gate checks (tier-based feature access)
- User profile management
Key methods:
- `validateLicenseKeyFormat(key)` - Format validation
- `storeLicense(licenseData)` - Encrypted storage
- `isLicenseValid()` - Validity check (expiration + signature)
- `hasFeature(featureName)` - Feature gate check
- `getTier()` - Get license tier (basic/pro/enterprise)
- `getDaysUntilExpiration()` - Expiration countdown
#### 1.2 Create API Client Module
**File**: `src/main/api-client.js` (NEW)
External API communication:
- Base URL: `https://api.hiveops.com/v1` (configurable)
- 30-second timeout for all requests
- HTTPS-only with proper error handling
Key endpoints:
- `POST /licenses/activate` - Activate license key
- `POST /licenses/validate` - Online validation
- `POST /auth/login` - User login
- `GET /users/profile` - Get user profile
- `GET /licenses/{key}/status` - Check license status
- `POST /licenses/deactivate` - Deactivate license
Key methods:
- `activateLicense(licenseKey, machineId)` - Activate license
- `validateLicense(licenseKey, machineId)` - Validate online
- `login(email, password)` - User authentication
- `getUserProfile(authToken)` - Fetch profile
- `getMachineId()` - Generate unique device ID
#### 1.3 Create Authentication Manager
**File**: `src/main/auth-manager.js` (NEW)
User authentication and session management:
- Store auth tokens securely
- Manage user profiles
- Handle login/logout
- Token refresh logic
Key methods:
- `login(email, password)` - User login
- `logout()` - Clear session
- `isAuthenticated()` - Check auth status
- `getUser()` - Get current user
- `getToken()` - Get auth token
- `refreshProfile()` - Update user data
### 2. Application Lifecycle Integration
#### 2.1 Modify Main Process
**File**: `src/main/main.js` (MODIFY)
Changes at app startup (app.whenReady):
```javascript
// Add license check before main window
if (!licenseManager.isLicenseValid()) {
createLicenseActivationWindow(); // Block app until activated
} else {
createMainWindow();
// Show expiration warning if < 7 days remaining
const daysRemaining = licenseManager.getDaysUntilExpiration();
if (daysRemaining <= 7) showExpirationWarning(daysRemaining);
}
```
Add new window functions:
- `createLicenseActivationWindow()` - 600x500 modal for activation
- `openLicenseManagement()` - 600x500 modal for license info
- `showExpirationWarning(days)` - Dialog for expiration alerts
Add background license validation:
- Every 24 hours, validate license online
- Update local cache with server data
- Handle offline gracefully (use local validation)
- Force quit if license revoked or expired
Add IPC handlers:
- `activate-license` - Activate via API
- `get-license-info` - Return license data
- `deactivate-license` - Deactivate and quit
- `validate-license` - Online validation
- `has-feature` - Check feature access
- `login` - User authentication
- `logout` - Clear session
- `get-user-profile` - Get user data
- `is-authenticated` - Check auth status
#### 2.2 Update Configuration Module
**File**: `src/main/config.js` (MODIFY)
Add feature tier definitions:
```javascript
const FEATURE_TIERS = {
basic: ['single-url', 'basic-navigation'],
pro: ['single-url', 'basic-navigation', 'subdomain-access', 'zoom-controls'],
enterprise: ['single-url', 'basic-navigation', 'subdomain-access', 'zoom-controls',
'custom-protocols', 'advanced-settings', 'api-access']
};
```
Add methods:
- `isFeatureEnabled(featureName)` - Check if feature is in current tier
- Modify `isUrlAllowed()` to check license validity first
Update default-config.json:
```json
{
"apiBaseUrl": "https://api.hiveops.com/v1"
}
```
#### 2.3 Update IPC Bridge
**File**: `src/main/preload.js` (MODIFY)
Expose new APIs to renderer:
```javascript
electronAPI: {
// License APIs
activateLicense: (licenseKey) => ipcRenderer.invoke('activate-license', licenseKey),
getLicenseInfo: () => ipcRenderer.invoke('get-license-info'),
deactivateLicense: () => ipcRenderer.invoke('deactivate-license'),
validateLicense: () => ipcRenderer.invoke('validate-license'),
hasFeature: (featureName) => ipcRenderer.invoke('has-feature', featureName),
// Auth APIs
login: (email, password) => ipcRenderer.invoke('login', email, password),
logout: () => ipcRenderer.invoke('logout'),
getUserProfile: () => ipcRenderer.invoke('get-user-profile'),
isAuthenticated: () => ipcRenderer.invoke('is-authenticated'),
// Window control
closeLicenseWindow: () => ipcRenderer.send('close-license-window'),
openLicenseManagement: () => ipcRenderer.send('open-license-management')
}
```
### 3. User Interface Components
#### 3.1 License Activation Screen
**Files**:
- `src/renderer/license-activation.html` (NEW)
- `src/renderer/license-activation.js` (NEW)
- `src/renderer/license.css` (NEW)
Features:
- Tabbed interface: "License Key" and "User Login"
- License key input with auto-formatting (dashes added automatically)
- Email/password login form
- Error/success message display
- Loading states for async operations
- Links to trial/purchase pages
Workflow:
1. User enters license key OR logs in with credentials
2. Validate format client-side
3. Call API via IPC
4. Show success/error
5. Close window on success (main window opens)
6. Quit app on cancel if no valid license
#### 3.2 License Management Screen
**Files**:
- `src/renderer/license-management.html` (NEW)
- `src/renderer/license-management.js` (NEW)
Features:
- Display license status (active/expired/trial)
- Show license tier (basic/pro/enterprise)
- Show expiration date and days remaining
- Display masked license key
- Show user profile (name, email) if logged in
- List enabled features for current tier
- Refresh button (online validation)
- Deactivate button (clear license and quit)
#### 3.3 Update Settings Page
**File**: `src/renderer/settings.html` (MODIFY)
Add license information section:
- Display current tier
- Display expiration date
- "Manage License" button → opens license management window
Add to settings.js:
- Load license info on page load
- Display tier and expiration
- Handle "Manage License" button click
### 4. Protocol Handler Registration
#### 4.1 Update Build Configuration
**File**: `electron-builder.yml` (MODIFY)
Add protocol registration:
```yaml
protocols:
- name: HiveOps Browser
schemes:
- hiveops
role: Viewer
win:
fileAssociations:
- ext: hiveops
name: HiveOps Link
description: HiveOps Browser Link
role: Viewer
nsis:
include: installer-script.nsh # Custom registry script
linux:
mimeTypes:
- x-scheme-handler/hiveops
desktop:
MimeType: x-scheme-handler/hiveops
```
#### 4.2 Windows Protocol Registration
**File**: `installer-script.nsh` (NEW)
NSIS script for Windows registry:
```nsis
!macro customInstall
WriteRegStr HKCR "hiveops" "" "URL:HiveOps Protocol"
WriteRegStr HKCR "hiveops" "URL Protocol" ""
WriteRegStr HKCR "hiveops\DefaultIcon" "" "$INSTDIR\${APP_EXECUTABLE_FILENAME},0"
WriteRegStr HKCR "hiveops\shell\open\command" "" '"$INSTDIR\${APP_EXECUTABLE_FILENAME}" "%1"'
!macroend
!macro customUnInstall
DeleteRegKey HKCR "hiveops"
!macroend
```
#### 4.3 Protocol Handling in Main Process
**File**: `src/main/main.js` (MODIFY)
Add protocol handler setup:
```javascript
// Register protocol
app.setAsDefaultProtocolClient('hiveops');
// Handle macOS protocol URLs
app.on('open-url', (event, url) => {
event.preventDefault();
handleProtocolUrl(url);
});
// Handle Windows/Linux (single instance)
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
} else {
app.on('second-instance', (event, commandLine) => {
const url = commandLine.find(arg => arg.startsWith('hiveops://'));
if (url) handleProtocolUrl(url);
if (mainWindow) {
mainWindow.restore();
mainWindow.focus();
}
});
}
function handleProtocolUrl(protocolUrl) {
// Parse: hiveops://open?url=https://example.hiveops.com/path
const url = new URL(protocolUrl);
const targetUrl = url.searchParams.get('url');
if (targetUrl && config.isUrlAllowed(targetUrl)) {
mainWindow.loadURL(targetUrl);
}
}
```
### 5. Feature Gates Implementation
#### 5.1 Feature-Gated Menu Items
**File**: `src/main/main.js` (MODIFY)
Wrap menu items with feature checks:
```javascript
{
label: 'Zoom In',
click: () => {
if (!config.isFeatureEnabled('zoom-controls')) {
dialog.showMessageBoxSync({
type: 'info',
title: 'Feature Not Available',
message: 'Zoom controls require Pro or Enterprise license.'
});
return;
}
// Zoom logic
}
}
```
Apply to:
- Zoom controls (Pro+)
- Settings (if advanced settings are Enterprise-only)
- Multiple windows (Pro+)
- Custom protocol handling (Enterprise)
#### 5.2 Feature-Gated URL Access
**File**: `src/main/config.js` (MODIFY)
Already implemented in `isUrlAllowed()`:
- Basic: Single URL only
- Pro: Single URL + subdomains
- Enterprise: Single URL + subdomains + custom protocols
### 6. Security Implementation
#### 6.1 Encrypted License Storage
- Use electron-store with encryption key derived from machine ID
- Store license data in: `~/.config/HiveOps/hiveops-license` (Linux)
- Encryption prevents tampering with local data
#### 6.2 License Signature Verification
- Server generates HMAC-SHA256 signature: `HMAC(key + tier + expiry, secret)`
- Client verifies signature on every validation
- Prevents local tampering with tier/expiration
#### 6.3 Machine ID Fingerprinting
- Use `app.getSystemId()` or fallback to deterministic ID
- Hash with SHA256 for consistent device identification
- Used to enforce activation limits (e.g., 3 devices per license)
#### 6.4 Online/Offline Validation
- Primary: Local signature + expiration check (works offline)
- Secondary: Background API validation every 24 hours (when online)
- Grace period: Allow offline operation for up to 7 days
- Forced validation: On app startup if last check > 7 days ago
### 7. HiveOps Management Microservice (hiveops-mgmt)
**Separate Repository**: Create new Spring Boot 4 microservice in separate repository
#### 7.1 Technology Stack
- **Framework**: Spring Boot 4.0.x
- **Language**: Java 21 (LTS)
- **Database**: PostgreSQL 16+
- **Security**: Spring Security 6 with JWT
- **ORM**: Spring Data JPA (Hibernate)
- **API Docs**: SpringDoc OpenAPI 3
- **Build**: Maven or Gradle
- **Deployment**: Docker containerized
#### 7.2 Project Structure
```
hiveops-mgmt/
├── src/
│ ├── main/
│ │ ├── java/com/hiveops/mgmt/
│ │ │ ├── HiveOpsMgmtApplication.java
│ │ │ ├── config/
│ │ │ │ ├── SecurityConfig.java
│ │ │ │ ├── JwtConfig.java
│ │ │ │ └── CorsConfig.java
│ │ │ ├── controller/
│ │ │ │ ├── LicenseController.java
│ │ │ │ ├── AuthController.java
│ │ │ │ ├── UserController.java
│ │ │ │ └── GlobalSettingsController.java
│ │ │ ├── service/
│ │ │ │ ├── LicenseService.java
│ │ │ │ ├── AuthService.java
│ │ │ │ ├── UserService.java
│ │ │ │ ├── LicenseKeyGenerator.java
│ │ │ │ └── GlobalSettingsService.java
│ │ │ ├── repository/
│ │ │ │ ├── LicenseRepository.java
│ │ │ │ ├── UserRepository.java
│ │ │ │ ├── LicenseActivationRepository.java
│ │ │ │ └── GlobalSettingsRepository.java
│ │ │ ├── model/
│ │ │ │ ├── entity/
│ │ │ │ │ ├── License.java
│ │ │ │ │ ├── User.java
│ │ │ │ │ ├── LicenseActivation.java
│ │ │ │ │ └── GlobalSetting.java
│ │ │ │ ├── dto/
│ │ │ │ │ ├── LicenseActivationRequest.java
│ │ │ │ │ ├── LicenseActivationResponse.java
│ │ │ │ │ ├── LoginRequest.java
│ │ │ │ │ ├── LoginResponse.java
│ │ │ │ │ └── UserProfileResponse.java
│ │ │ │ └── enums/
│ │ │ │ ├── LicenseTier.java
│ │ │ │ ├── LicenseStatus.java
│ │ │ │ └── UserRole.java
│ │ │ ├── security/
│ │ │ │ ├── JwtTokenProvider.java
│ │ │ │ ├── JwtAuthenticationFilter.java
│ │ │ │ └── UserDetailsServiceImpl.java
│ │ │ ├── exception/
│ │ │ │ ├── GlobalExceptionHandler.java
│ │ │ │ ├── LicenseException.java
│ │ │ │ └── AuthenticationException.java
│ │ │ └── util/
│ │ │ ├── SignatureUtils.java
│ │ │ └── DateUtils.java
│ │ └── resources/
│ │ ├── application.yml
│ │ ├── application-dev.yml
│ │ ├── application-prod.yml
│ │ └── db/migration/ # Flyway migrations
│ │ ├── V1__init_schema.sql
│ │ └── V2__seed_data.sql
│ └── test/
│ └── java/com/hiveops/mgmt/
│ ├── service/
│ ├── controller/
│ └── integration/
├── Dockerfile
├── docker-compose.yml
├── pom.xml (or build.gradle)
└── README.md
```
#### 7.3 Database Schema (PostgreSQL)
**Table: users**
```sql
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
uuid UUID UNIQUE NOT NULL DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
name VARCHAR(255),
role VARCHAR(50) NOT NULL DEFAULT 'USER',
enabled BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login_at TIMESTAMP
);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_uuid ON users(uuid);
```
**Table: licenses**
```sql
CREATE TABLE licenses (
id BIGSERIAL PRIMARY KEY,
license_key VARCHAR(29) UNIQUE NOT NULL, -- XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
user_id BIGINT REFERENCES users(id) ON DELETE CASCADE,
tier VARCHAR(50) NOT NULL, -- BASIC, PRO, ENTERPRISE
status VARCHAR(50) NOT NULL DEFAULT 'ACTIVE', -- ACTIVE, EXPIRED, REVOKED, TRIAL
max_activations INTEGER DEFAULT 3,
features JSONB, -- Array of feature names
issued_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP,
trial_ends_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
metadata JSONB -- Additional data (company, notes, etc.)
);
CREATE INDEX idx_licenses_key ON licenses(license_key);
CREATE INDEX idx_licenses_user ON licenses(user_id);
CREATE INDEX idx_licenses_status ON licenses(status);
```
**Table: license_activations**
```sql
CREATE TABLE license_activations (
id BIGSERIAL PRIMARY KEY,
license_id BIGINT NOT NULL REFERENCES licenses(id) ON DELETE CASCADE,
machine_id VARCHAR(255) NOT NULL,
platform VARCHAR(50), -- linux, windows, darwin
app_version VARCHAR(50),
activated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_validated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ip_address INET,
hostname VARCHAR(255),
metadata JSONB,
UNIQUE(license_id, machine_id)
);
CREATE INDEX idx_activations_license ON license_activations(license_id);
CREATE INDEX idx_activations_machine ON license_activations(machine_id);
```
**Table: global_settings**
```sql
CREATE TABLE global_settings (
id BIGSERIAL PRIMARY KEY,
setting_key VARCHAR(255) UNIQUE NOT NULL,
setting_value TEXT NOT NULL,
setting_type VARCHAR(50) DEFAULT 'STRING', -- STRING, INTEGER, BOOLEAN, JSON
description TEXT,
editable BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_settings_key ON global_settings(setting_key);
```
**Table: audit_logs**
```sql
CREATE TABLE audit_logs (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
action VARCHAR(100) NOT NULL, -- LICENSE_ACTIVATED, LOGIN, LICENSE_REVOKED, etc.
entity_type VARCHAR(50), -- LICENSE, USER, SETTING
entity_id BIGINT,
details JSONB,
ip_address INET,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_audit_user ON audit_logs(user_id);
CREATE INDEX idx_audit_action ON audit_logs(action);
CREATE INDEX idx_audit_created ON audit_logs(created_at);
```
#### 7.4 Core Entities (JPA)
**License.java**
```java
@Entity
@Table(name = "licenses")
public class License {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "license_key", unique = true, nullable = false, length = 29)
private String licenseKey;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
@Enumerated(EnumType.STRING)
private LicenseTier tier;
@Enumerated(EnumType.STRING)
private LicenseStatus status;
@Column(name = "max_activations")
private Integer maxActivations = 3;
@Type(JsonBinaryType.class)
@Column(columnDefinition = "jsonb")
private List<String> features;
@Column(name = "issued_at")
private LocalDateTime issuedAt;
@Column(name = "expires_at")
private LocalDateTime expiresAt;
@Column(name = "trial_ends_at")
private LocalDateTime trialEndsAt;
@OneToMany(mappedBy = "license", cascade = CascadeType.ALL)
private List<LicenseActivation> activations;
// Standard getters, setters, constructors
}
```
**LicenseActivation.java**
```java
@Entity
@Table(name = "license_activations")
public class LicenseActivation {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "license_id", nullable = false)
private License license;
@Column(name = "machine_id", nullable = false)
private String machineId;
private String platform;
@Column(name = "app_version")
private String appVersion;
@Column(name = "activated_at")
private LocalDateTime activatedAt;
@Column(name = "last_validated_at")
private LocalDateTime lastValidatedAt;
@Column(name = "ip_address")
private String ipAddress;
private String hostname;
// Standard getters, setters
}
```
**User.java**
```java
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private UUID uuid;
@Column(unique = true, nullable = false)
private String email;
@Column(name = "password_hash", nullable = false)
private String passwordHash;
private String name;
@Enumerated(EnumType.STRING)
private UserRole role = UserRole.USER;
private Boolean enabled = true;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "last_login_at")
private LocalDateTime lastLoginAt;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<License> licenses;
// Standard getters, setters
}
```
#### 7.5 REST API Endpoints
**LicenseController.java**
**POST /api/v1/licenses/activate**
```java
@PostMapping("/activate")
public ResponseEntity<LicenseActivationResponse> activateLicense(
@RequestBody LicenseActivationRequest request
) {
// Validate license key format
// Check license exists and is active
// Check activation limit
// Create activation record
// Generate signature
// Return license data with features and signature
}
```
**POST /api/v1/licenses/validate**
```java
@PostMapping("/validate")
public ResponseEntity<LicenseValidationResponse> validateLicense(
@RequestBody LicenseValidationRequest request
) {
// Find activation by license key + machine ID
// Update last_validated_at
// Check expiration
// Return updated license data
}
```
**POST /api/v1/licenses/deactivate**
```java
@PostMapping("/deactivate")
public ResponseEntity<Void> deactivateLicense(
@RequestBody LicenseDeactivationRequest request,
@AuthenticationPrincipal UserDetails userDetails
) {
// Find activation
// Verify ownership or admin
// Delete activation record
// Audit log
}
```
**GET /api/v1/licenses/{licenseKey}/status**
```java
@GetMapping("/{licenseKey}/status")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<LicenseStatusResponse> getLicenseStatus(
@PathVariable String licenseKey,
@AuthenticationPrincipal UserDetails userDetails
) {
// Verify ownership
// Return license status, tier, expiration, activation count
}
```
**AuthController.java**
**POST /api/v1/auth/login**
```java
@PostMapping("/login")
public ResponseEntity<LoginResponse> login(
@RequestBody LoginRequest request
) {
// Authenticate credentials
// Generate JWT token
// Update last_login_at
// Return token + user profile + associated licenses
}
```
**POST /api/v1/auth/register**
```java
@PostMapping("/register")
public ResponseEntity<UserProfileResponse> register(
@RequestBody UserRegistrationRequest request
) {
// Validate email uniqueness
// Hash password (BCrypt)
// Create user
// Return user profile
}
```
**POST /api/v1/auth/refresh**
```java
@PostMapping("/refresh")
public ResponseEntity<TokenResponse> refreshToken(
@RequestHeader("Authorization") String refreshToken
) {
// Validate refresh token
// Generate new access token
// Return new token
}
```
**UserController.java**
**GET /api/v1/users/profile**
```java
@GetMapping("/profile")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<UserProfileResponse> getProfile(
@AuthenticationPrincipal UserDetails userDetails
) {
// Return user profile + licenses
}
```
**PUT /api/v1/users/profile**
```java
@PutMapping("/profile")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<UserProfileResponse> updateProfile(
@RequestBody UserUpdateRequest request,
@AuthenticationPrincipal UserDetails userDetails
) {
// Update user name, email, etc.
// Return updated profile
}
```
**GlobalSettingsController.java**
**GET /api/v1/settings**
```java
@GetMapping
public ResponseEntity<Map<String, Object>> getGlobalSettings() {
// Return public global settings
// e.g., allowed domains, feature flags, client update URLs
}
```
**GET /api/v1/settings/{key}**
```java
@GetMapping("/{key}")
public ResponseEntity<GlobalSettingResponse> getSetting(
@PathVariable String key
) {
// Return specific setting value
}
```
**PUT /api/v1/settings/{key}** (Admin only)
```java
@PutMapping("/{key}")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<GlobalSettingResponse> updateSetting(
@PathVariable String key,
@RequestBody GlobalSettingUpdateRequest request
) {
// Update setting value
// Audit log
}
```
#### 7.6 Service Layer
**LicenseService.java**
```java
@Service
public class LicenseService {
public LicenseActivationResponse activateLicense(
String licenseKey,
String machineId,
String platform,
String appVersion,
String ipAddress
) {
// 1. Find license by key
// 2. Validate status (ACTIVE, not EXPIRED/REVOKED)
// 3. Check expiration date
// 4. Count current activations
// 5. Enforce max_activations limit
// 6. Create or update activation record
// 7. Generate HMAC signature
// 8. Return LicenseActivationResponse with:
// - license key, tier, features, expiresAt
// - signature (HMAC-SHA256)
// 9. Audit log
}
public LicenseValidationResponse validateLicense(
String licenseKey,
String machineId
) {
// 1. Find activation
// 2. Check license status
// 3. Check expiration
// 4. Update last_validated_at
// 5. Return updated license data
}
public void deactivateLicense(String licenseKey, String machineId, User user) {
// 1. Find activation
// 2. Verify ownership (user owns license OR user is admin)
// 3. Delete activation
// 4. Audit log
}
public String generateSignature(License license) {
// HMAC-SHA256(licenseKey + tier + expiresAt, SECRET_KEY)
String payload = license.getLicenseKey() + "|" +
license.getTier() + "|" +
license.getExpiresAt();
return HmacUtils.hmacSha256Hex(secretKey, payload);
}
public boolean verifySignature(License license, String signature) {
return generateSignature(license).equals(signature);
}
}
```
**LicenseKeyGenerator.java**
```java
@Service
public class LicenseKeyGenerator {
public String generateLicenseKey(LicenseTier tier) {
// Format: TTTPP-RRRRR-RRRRR-CCCCC-RRRRR
// TTT: Tier code (BAS, PRO, ENT)
// PP: Product code (HB = HiveOps Browser)
// R: Random alphanumeric
// C: Checksum
String tierCode = tier == LicenseTier.BASIC ? "BAS" :
tier == LicenseTier.PRO ? "PRO" : "ENT";
String productCode = "HB";
String random1 = RandomStringUtils.randomAlphanumeric(5).toUpperCase();
String random2 = RandomStringUtils.randomAlphanumeric(5).toUpperCase();
String random3 = RandomStringUtils.randomAlphanumeric(5).toUpperCase();
String partialKey = tierCode + productCode + random1 + random2;
String checksum = calculateChecksum(partialKey);
return format(tierCode + productCode, random1, random2, checksum, random3);
}
private String calculateChecksum(String data) {
// Simple checksum using CRC or custom algorithm
int sum = 0;
for (char c : data.toCharArray()) {
sum += c;
}
return String.format("%05d", sum % 100000).substring(0, 5);
}
private String format(String p1, String p2, String p3, String p4, String p5) {
return p1 + "-" + p2 + "-" + p3 + "-" + p4 + "-" + p5;
}
}
```
#### 7.7 Security Configuration
**SecurityConfig.java**
```java
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.cors().and()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/v1/auth/**").permitAll()
.requestMatchers("/api/v1/licenses/activate").permitAll()
.requestMatchers("/api/v1/licenses/validate").permitAll()
.requestMatchers("/api/v1/settings").permitAll()
.requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
}
```
**JwtTokenProvider.java**
```java
@Component
public class JwtTokenProvider {
@Value("${jwt.secret}")
private String jwtSecret;
@Value("${jwt.expiration}")
private long jwtExpiration = 86400000; // 24 hours
public String generateToken(User user) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + jwtExpiration);
return Jwts.builder()
.setSubject(user.getEmail())
.claim("userId", user.getId())
.claim("role", user.getRole())
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
public String getUserEmailFromToken(String token) {
Claims claims = Jwts.parser()
.setSigningKey(jwtSecret)
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
}
```
#### 7.8 Configuration Files
**application.yml**
```yaml
spring:
application:
name: hiveops-mgmt
datasource:
url: jdbc:postgresql://localhost:5432/hiveops_mgmt
username: ${DB_USERNAME:hiveops}
password: ${DB_PASSWORD:changeme}
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: validate # Use Flyway for migrations
show-sql: false
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: true
server:
port: 8080
servlet:
context-path: /api
jwt:
secret: ${JWT_SECRET:your-secret-key-change-in-production}
expiration: 86400000 # 24 hours
license:
signature-secret: ${LICENSE_SECRET:your-license-secret-key}
max-activations-default: 3
offline-grace-period-days: 7
logging:
level:
com.hiveops.mgmt: DEBUG
org.springframework.security: DEBUG
```
**application-prod.yml**
```yaml
spring:
datasource:
url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:hiveops_mgmt}
jpa:
show-sql: false
logging:
level:
com.hiveops.mgmt: INFO
org.springframework.security: WARN
server:
port: ${PORT:8080}
ssl:
enabled: ${SSL_ENABLED:false}
key-store: ${SSL_KEYSTORE_PATH}
key-store-password: ${SSL_KEYSTORE_PASSWORD}
```
#### 7.9 Docker Configuration
**Dockerfile**
```dockerfile
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY target/hiveops-mgmt-*.jar app.jar
EXPOSE 8080
ENV JAVA_OPTS="-Xmx512m -Xms256m"
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
```
**docker-compose.yml**
```yaml
version: '3.8'
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: hiveops_mgmt
POSTGRES_USER: hiveops
POSTGRES_PASSWORD: changeme
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- hiveops-network
hiveops-mgmt:
build: .
ports:
- "8080:8080"
environment:
DB_HOST: postgres
DB_PORT: 5432
DB_NAME: hiveops_mgmt
DB_USERNAME: hiveops
DB_PASSWORD: changeme
JWT_SECRET: your-production-jwt-secret
LICENSE_SECRET: your-production-license-secret
depends_on:
- postgres
networks:
- hiveops-network
volumes:
postgres_data:
networks:
hiveops-network:
driver: bridge
```
#### 7.10 Maven Dependencies (pom.xml)
```xml
<dependencies>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Database -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<!-- JSON support -->
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-60</artifactId>
<version>2.21.1</version>
</dependency>
<!-- API Documentation -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.2.0</version>
</dependency>
<!-- Utilities -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
```
### 8. Browser Client Updates (Connects to hiveops-mgmt)
The browser client API implementation from earlier sections remains mostly the same, but with these key changes:
**api-client.js modifications:**
- Base URL points to hiveops-mgmt: `https://api.hiveops.com/api/v1` (adjust based on deployment)
- All endpoints match the Spring Boot REST API paths
- Error handling matches Spring Boot error response format
### 9. API Server Requirements (Now hiveops-mgmt Implementation)
The external API must implement these endpoints (implemented in Spring Boot microservice above):
**POST /v1/licenses/activate**
- Validate license key
- Check activation limit (e.g., max 3 devices)
- Store machine ID
- Return license data with signature
- Status: 200 (success), 400 (invalid), 409 (max activations), 410 (expired)
**POST /v1/licenses/validate**
- Verify license still valid
- Check revocation status
- Return updated license data
- Status: 200 (valid), 403 (invalid/expired)
**POST /v1/auth/login**
- Authenticate user credentials
- Return JWT token + user profile + associated license
- Status: 200 (success), 401 (invalid credentials)
**GET /v1/users/profile** (Bearer token required)
- Return user profile and license list
- Status: 200 (success), 401 (unauthorized)
**GET /v1/licenses/{key}/status** (Bearer token required)
- Return license status, expiration, tier, features
- Return activation count (current/max)
- Status: 200 (success), 404 (not found)
**POST /v1/licenses/deactivate**
- Remove machine ID from activation list
- Free up activation slot
- Status: 200 (success), 404 (not found)
### 8. Testing Strategy
#### 8.1 License Validation Testing
- [ ] Valid license key format accepted
- [ ] Invalid format rejected
- [ ] Expired license blocks app startup
- [ ] Valid license allows app to run
- [ ] Signature tampering detected and rejected
- [ ] Feature gates work correctly per tier
#### 8.2 API Integration Testing
- [ ] Successful license activation
- [ ] Invalid key returns error
- [ ] Network error handled gracefully
- [ ] Timeout handled (30s)
- [ ] Offline mode uses local validation
- [ ] Online validation updates local cache
#### 8.3 Authentication Testing
- [ ] Successful login stores token and profile
- [ ] Invalid credentials show error
- [ ] Logout clears session data
- [ ] Token expiration triggers re-login
#### 8.4 Protocol Handler Testing
- [ ] `hiveops://open?url=https://test.hiveops.com` opens URL
- [ ] Invalid URLs blocked
- [ ] Single instance enforcement works
- [ ] Windows registry entries created on install
- [ ] Linux .desktop file includes MIME type
#### 8.5 Feature Gate Testing
- [ ] Basic tier: Only basic features available
- [ ] Pro tier: Advanced features unlocked
- [ ] Enterprise tier: All features available
- [ ] Feature upgrade prompt shows correctly
#### 8.6 Security Testing
- [ ] License data encryption verified
- [ ] Signature tampering detected
- [ ] Machine ID consistent across runs
- [ ] API authentication required
- [ ] Offline grace period enforced
### 9. Implementation Timeline
#### Phase 1: Microservice Backend (hiveops-mgmt) - Weeks 1-3
**Week 1: Project Setup & Core Entities**
1. Create new Spring Boot 4 project (Maven/Gradle)
2. Set up PostgreSQL database and docker-compose
3. Configure Spring Security, JPA, Flyway
4. Create database schema (migrations)
5. Implement entity classes (User, License, LicenseActivation, GlobalSetting)
6. Create repositories (Spring Data JPA)
7. Write unit tests for entities
**Week 2: Service Layer & Business Logic**
8. Implement LicenseService (activate, validate, deactivate)
9. Implement AuthService (login, register, token management)
10. Implement UserService (profile, CRUD)
11. Implement GlobalSettingsService
12. Create LicenseKeyGenerator with checksum validation
13. Implement signature generation/verification (HMAC-SHA256)
14. Write service layer unit tests
**Week 3: REST API & Security**
15. Implement LicenseController with all endpoints
16. Implement AuthController (login, register, refresh)
17. Implement UserController (profile management)
18. Implement GlobalSettingsController
19. Configure JWT authentication filter
20. Add global exception handling
21. Set up API documentation (SpringDoc/Swagger)
22. Integration tests for all endpoints
23. Security testing (authentication, authorization)
#### Phase 2: Browser Client (hiveops-browser) - Weeks 4-6
**Week 4: Client Infrastructure**
24. Create `license-manager.js` with client-side validation
25. Create `api-client.js` connecting to hiveops-mgmt
26. Create `auth-manager.js` with token management
27. Update `preload.js` with new IPC APIs
28. Add IPC handlers to `main.js`
29. Test API communication with backend
30. Test license storage and validation
**Week 5: UI Development**
31. Create `license-activation.html/js` with dual-tab interface
32. Create `license-management.html/js` with status display
33. Create `license.css` for styling
34. Update `settings.html` with license info section
35. Update `about.html` to show tier
36. Test all UI flows with mock data
37. Integration with real backend API
**Week 6: Features & Integration**
38. Modify `main.js` startup to check license
39. Add background validation (24-hour interval)
40. Update `config.js` with feature gates
41. Implement feature-gated menu items
42. Add expiration warnings
43. Test end-to-end flows (client + backend)
#### Phase 3: Protocol Handler & Distribution - Week 7
**Week 7: Protocol & Build**
44. Update `electron-builder.yml` with protocol config
45. Create `installer-script.nsh` for Windows
46. Add protocol handling to `main.js`
47. Test protocol handler on all platforms
48. Full integration testing (client + backend + protocol)
49. Security testing and penetration tests
#### Phase 4: Deployment & Documentation - Week 8
**Week 8: Deploy & Polish**
50. Deploy hiveops-mgmt to production (Docker/K8s)
51. Configure production database (PostgreSQL)
52. Set up SSL/TLS certificates
53. Build and test installers (Windows/Linux)
54. Write user documentation
55. Write API documentation
56. Create admin panel for license management (optional)
57. Final QA and release
### 10. Critical Files Summary
#### hiveops-mgmt (Spring Boot Microservice - NEW REPOSITORY)
**New Java Files** (~30 files):
- `HiveOpsMgmtApplication.java` - Main Spring Boot application
- `SecurityConfig.java` - Spring Security configuration
- `JwtConfig.java` - JWT configuration
- `LicenseController.java` - License REST endpoints
- `AuthController.java` - Authentication endpoints
- `UserController.java` - User management endpoints
- `GlobalSettingsController.java` - Settings endpoints
- `LicenseService.java` - License business logic
- `AuthService.java` - Authentication service
- `UserService.java` - User service
- `LicenseKeyGenerator.java` - Key generation logic
- `GlobalSettingsService.java` - Settings service
- `License.java` - License entity (JPA)
- `User.java` - User entity
- `LicenseActivation.java` - Activation entity
- `GlobalSetting.java` - Setting entity
- `JwtTokenProvider.java` - JWT token handling
- `JwtAuthenticationFilter.java` - JWT filter
- `GlobalExceptionHandler.java` - Exception handling
- DTO classes (requests/responses)
- Repository interfaces
- Utility classes
**Configuration Files**:
- `application.yml` - Main configuration
- `application-prod.yml` - Production config
- `pom.xml` - Maven dependencies
- `Dockerfile` - Container config
- `docker-compose.yml` - Local development
- `V1__init_schema.sql` - Flyway migration
- `installer-script.nsh` - Windows protocol registration
#### hiveops-browser (Electron Client - EXISTING REPOSITORY)
**New Files** (9 total):
- `src/main/license-manager.js` - License validation core
- `src/main/api-client.js` - External API communication
- `src/main/auth-manager.js` - User authentication
- `src/renderer/license-activation.html` - Activation UI
- `src/renderer/license-activation.js` - Activation logic
- `src/renderer/license-management.html` - Management UI
- `src/renderer/license-management.js` - Management logic
- `src/renderer/license.css` - License UI styles
- `installer-script.nsh` - Windows protocol registration
**Modified Files** (6 total):
- `src/main/main.js` - Add license checks, protocol handler, IPC handlers
- `src/main/config.js` - Add feature gates, license-aware URL validation
- `src/main/preload.js` - Expose license/auth APIs
- `src/renderer/settings.html` - Add license info section
- `config/default-config.json` - Add apiBaseUrl
- `electron-builder.yml` - Add protocol registration
- `package.json` - Update version to 2.0.0
### 11. Verification Checklist
#### Backend (hiveops-mgmt) Verification
- [ ] Spring Boot application starts without errors
- [ ] Database schema created via Flyway
- [ ] PostgreSQL connection established
- [ ] Swagger UI accessible at `/swagger-ui.html`
- [ ] License activation endpoint works
- [ ] License validation endpoint works
- [ ] User login returns JWT token
- [ ] JWT authentication filter validates tokens
- [ ] License signature verification works
- [ ] Activation limit enforcement works (max 3 devices)
- [ ] License expiration checked correctly
- [ ] Global settings CRUD operations work
- [ ] Audit logs created for actions
- [ ] API error handling returns proper status codes
- [ ] Docker container builds and runs
- [ ] docker-compose brings up full stack
#### Client (hiveops-browser) Verification
- [ ] Fresh install shows license activation screen
- [ ] Valid license key activates successfully via API
- [ ] Invalid license key shows error from backend
- [ ] User login works and stores profile + token
- [ ] Main window opens after successful activation
- [ ] License expiration is enforced
- [ ] Feature gates work per tier (Basic/Pro/Enterprise)
- [ ] Protocol handler opens app with URL (hiveops://)
- [ ] Settings page shows license info
- [ ] License management shows all data from backend
- [ ] Deactivation calls backend API and quits
- [ ] Offline operation works (local validation)
- [ ] Background validation (24hr) calls backend
- [ ] Network errors handled gracefully
- [ ] Build creates installers with protocol registration
- [ ] Windows installer registers protocol in registry
- [ ] Linux .deb includes MIME type associations
#### Integration Testing
- [ ] End-to-end: Activate license from fresh install
- [ ] End-to-end: Login with user account
- [ ] End-to-end: Validate license online
- [ ] End-to-end: Deactivate license
- [ ] Backend handles concurrent activations
- [ ] Backend enforces activation limits
- [ ] Client handles backend downtime gracefully
- [ ] Offline mode works for 7 days
- [ ] Expired license blocks app startup
- [ ] Revoked license detected on validation
### 12. Deployment Guide
#### Backend Deployment (hiveops-mgmt)
**Infrastructure Requirements**:
- **Server**: 2 vCPU, 4GB RAM minimum
- **Database**: PostgreSQL 16+ (separate instance recommended)
- **Storage**: 20GB minimum
- **Network**: SSL/TLS certificate for HTTPS
**Deployment Options**:
**Option 1: Docker (Recommended)**
```bash
# Build and run with docker-compose
docker-compose up -d
# Or deploy to container orchestration
docker build -t hiveops-mgmt:latest .
docker push registry.hiveops.com/hiveops-mgmt:latest
```
**Option 2: Kubernetes**
```yaml
# Create deployment, service, ingress
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/ingress.yaml
```
**Option 3: Traditional Server (JAR)**
```bash
# Build JAR
mvn clean package -DskipTests
# Run with production profile
java -jar target/hiveops-mgmt-1.0.0.jar \
--spring.profiles.active=prod \
--server.port=8080
```
**Environment Variables (Production)**:
```bash
DB_HOST=postgres.hiveops.com
DB_PORT=5432
DB_NAME=hiveops_mgmt
DB_USERNAME=hiveops_user
DB_PASSWORD=<secure-password>
JWT_SECRET=<generate-secure-secret>
LICENSE_SECRET=<generate-secure-secret>
SSL_ENABLED=true
SSL_KEYSTORE_PATH=/etc/ssl/hiveops.jks
SSL_KEYSTORE_PASSWORD=<keystore-password>
```
**Database Setup**:
```sql
-- Create database and user
CREATE DATABASE hiveops_mgmt;
CREATE USER hiveops_user WITH ENCRYPTED PASSWORD 'secure-password';
GRANT ALL PRIVILEGES ON DATABASE hiveops_mgmt TO hiveops_user;
-- Flyway will handle schema migrations automatically
```
**SSL/TLS Certificate**:
```bash
# Generate Let's Encrypt certificate
certbot certonly --standalone -d api.hiveops.com
# Or use existing certificate
# Configure in application-prod.yml
```
**Post-Deployment Checks**:
- [ ] Health check: `curl https://api.hiveops.com/api/actuator/health`
- [ ] Swagger UI: `https://api.hiveops.com/api/swagger-ui.html`
- [ ] Test license activation endpoint
- [ ] Test user login endpoint
- [ ] Verify database connectivity
- [ ] Check logs for errors
#### Client Deployment (hiveops-browser)
**Build Configuration**:
1. Update `config/default-config.json`:
```json
{
"apiBaseUrl": "https://api.hiveops.com/api/v1"
}
```
2. Update version in `package.json`:
```json
{
"version": "2.0.0"
}
```
3. Build installers:
```bash
# Build all platforms
./build-all.sh
# Or individually
npm run build:linux
npm run build:win
```
**Distribution**:
- Windows: `dist/customer-packages/windows/HiveOps Browser Setup 2.0.0.exe`
- Linux: `dist/customer-packages/linux/hiveops-browser_2.0.0_amd64.deb`
- AppImage: `dist/customer-packages/linux/HiveOps Browser-2.0.0.AppImage`
**Deployment Prerequisites**:
1. ✅ Backend API deployed and accessible
2. ✅ Database populated with initial data
3. ✅ SSL certificates configured
4. ✅ DNS records set (api.hiveops.com)
5. ✅ Monitoring and logging configured
6. ✅ Admin user created for license management
7. ✅ Initial license keys generated for testing
8. ✅ Documentation prepared
9. ✅ Support channel established
### 13. Post-Launch Monitoring
**Backend Monitoring (hiveops-mgmt)**:
- API response times and latency
- Database query performance
- License activation/validation success rate
- Failed authentication attempts (security)
- API error rates (4xx, 5xx)
- Active license count by tier
- Server resource usage (CPU, memory, disk)
- Database connection pool utilization
**Client Monitoring**:
- License activation success rate
- Offline validation failures
- Feature gate usage by tier
- Protocol handler usage
- Crash reports and errors
- User feedback on licensing UX
- Update installation rates
**Recommended Tools**:
- **Backend**: Spring Boot Actuator + Prometheus + Grafana
- **Database**: PostgreSQL pg_stat_statements
- **Logging**: ELK Stack (Elasticsearch, Logstash, Kibana)
- **Alerts**: PagerDuty or similar
- **Client**: Sentry for error tracking
---
## Implementation Summary
### Two-Component Architecture
```
┌─────────────────────────────────────┐
│ HiveOps Browser (Electron) │
│ - License validation UI │
│ - Protocol handler (hiveops://) │
│ - Feature gates (Basic/Pro/Ent) │
│ - Offline validation (7-day grace)│
│ - Background sync (24hr) │
└─────────────┬───────────────────────┘
│ HTTPS/REST API
│ (JWT Authentication)
┌─────────────────────────────────────┐
│ hiveops-mgmt (Spring Boot 4) │
│ - License activation/validation │
│ - User authentication (JWT) │
│ - License key generation │
│ - Feature management │
│ - Global settings │
│ - Audit logging │
└─────────────┬───────────────────────┘
┌─────────────────────────────────────┐
│ PostgreSQL Database │
│ - users │
│ - licenses │
│ - license_activations │
│ - global_settings │
│ - audit_logs │
└─────────────────────────────────────┘
```
### Key Features
**Licensing System**:
- Three-tier license model (Basic, Pro, Enterprise)
- Machine-based activation (max 3 devices per license)
- Online validation with offline grace period (7 days)
- License expiration and trial support
- Anti-tamper signature verification (HMAC-SHA256)
- Revocation support
**User Management**:
- User authentication with JWT
- User profile with associated licenses
- Role-based access control (USER, ADMIN)
- Password hashing (BCrypt)
**Protocol Handling**:
- Custom protocol: `hiveops://`
- Domain-based: `*.hiveops.com`
- Platform-specific registration (Windows registry, Linux MIME types)
- Deep linking support
**Security**:
- Encrypted license storage (electron-store)
- JWT authentication (Spring Security)
- HTTPS-only API communication
- SQL injection prevention (parameterized queries)
- XSS protection (CSP headers)
- Audit logging for all actions
### Total Effort Estimate
- **Backend Development**: 3 weeks
- **Client Development**: 3 weeks
- **Integration & Testing**: 1 week
- **Deployment & Documentation**: 1 week
- **Total**: 8 weeks (2 months)
### Success Metrics
- ✅ License activation success rate > 95%
- ✅ API response time < 200ms (p95)
- Zero license bypass incidents
- Offline operation works seamlessly
- Protocol handler registration success > 90%
- ✅ User satisfaction score > 4/5