import crypto from 'crypto';
import fs from 'fs/promises';
import path from 'path';
import os from 'os';
/**
* License validation module for Day-1 monetization
* Uses HMAC-SHA256 for token validation
*/
// Shared secret - in production, this should be securely managed
const SHARED_SECRET = 'chhotu-ai-pc-assistant-2025-secret-key';
const LICENSE_FILE = path.join(os.homedir(), '.mcp-license');
export interface LicenseConfig {
isValid: boolean;
licensee?: string;
expiresAt?: string;
features?: string[];
}
/**
* Generate a valid license token
* This is for testing/setup purposes only
*/
export function generateLicenseToken(licensee: string = 'default-user'): string {
const timestamp = Math.floor(Date.now() / 1000);
const data = `${licensee}:${timestamp}`;
const signature = crypto
.createHmac('sha256', SHARED_SECRET)
.update(data)
.digest('hex');
return `${data}:${signature}`;
}
/**
* Validate a license token
* Checks HMAC signature and optional expiration
*/
export function validateLicenseToken(token: string): LicenseConfig {
try {
const parts = token.split(':');
if (parts.length < 3) {
return { isValid: false };
}
const licensee = parts[0];
const timestamp = parseInt(parts[1], 10);
const signature = parts.slice(2).join(':');
// Reconstruct and verify signature
const data = `${licensee}:${timestamp}`;
const expectedSignature = crypto
.createHmac('sha256', SHARED_SECRET)
.update(data)
.digest('hex');
if (signature !== expectedSignature) {
return { isValid: false };
}
// Optional: Check expiration (90 days from creation)
const now = Math.floor(Date.now() / 1000);
const expirationDays = 90;
const expiresAt = new Date(timestamp * 1000 + expirationDays * 24 * 60 * 60 * 1000);
if (now > timestamp + expirationDays * 24 * 60 * 60) {
return {
isValid: false,
licensee,
expiresAt: expiresAt.toISOString(),
};
}
return {
isValid: true,
licensee,
expiresAt: expiresAt.toISOString(),
features: ['all'],
};
} catch (error) {
return { isValid: false };
}
}
/**
* Load license from ~/.mcp-license file
*/
export async function loadLicense(): Promise<LicenseConfig> {
try {
const content = await fs.readFile(LICENSE_FILE, 'utf-8');
const token = content.trim();
return validateLicenseToken(token);
} catch (error) {
return { isValid: false };
}
}
/**
* Save license to ~/.mcp-license file
*/
export async function saveLicense(token: string): Promise<void> {
try {
await fs.writeFile(LICENSE_FILE, token, { mode: 0o600 });
} catch (error) {
throw new Error(`Failed to save license: ${error}`);
}
}
/**
* Initialize license or create demo license for development
*/
export async function initializeLicense(forceNew: boolean = false): Promise<LicenseConfig> {
if (!forceNew) {
const existing = await loadLicense();
if (existing.isValid) {
return existing;
}
}
// Create a new demo license
const token = generateLicenseToken('mcp-user');
await saveLicense(token);
return validateLicenseToken(token);
}