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

52 KiB

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):

// 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:

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:

{
  "apiBaseUrl": "https://api.hiveops.com/v1"
}

2.3 Update IPC Bridge

File: src/main/preload.js (MODIFY)

Expose new APIs to renderer:

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:

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:

!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:

// 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:

{
  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

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

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

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

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

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

@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

@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

@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

@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

@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

@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

@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

@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

@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

@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

@GetMapping("/profile")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<UserProfileResponse> getProfile(
    @AuthenticationPrincipal UserDetails userDetails
) {
    // Return user profile + licenses
}

PUT /api/v1/users/profile

@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

@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}

@GetMapping("/{key}")
public ResponseEntity<GlobalSettingResponse> getSetting(
    @PathVariable String key
) {
    // Return specific setting value
}

PUT /api/v1/settings/{key} (Admin only)

@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

@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

@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

@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

@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

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

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

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

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)

<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)

# 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

# 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)

# 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):

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:

-- 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:

# 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:
{
  "apiBaseUrl": "https://api.hiveops.com/api/v1"
}
  1. Update version in package.json:
{
  "version": "2.0.0"
}
  1. Build installers:
# 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