Saltar al contenido principal

🟩 SDK Oficial para Node.js, Bun & TypeScript (Manual Técnico & API)

El paquete validlicense-sdk es el cliente oficial para entornos de servidor (Node.js, Bun, Deno) y aplicaciones de escritorio (Electron, Tauri). Opera de forma autónoma con el módulo nativo node:crypto sin librerías externas de terceros.


🏛️ 1. Estructura de Tipos e Interfaces​

ValidLicenseOptions​

Configuración del cliente:

export interface ValidLicenseOptions {
serverUrl: string; // URL del servidor VPS (ej: 'https://licencias.labtec.sbs')
publicKeyHex?: string; // Clave Pública Ed25519 en formato hexadecimal de 64 caracteres
clientVersion?: string; // Versión del software cliente (por defecto '2026.1')
}

VerifyParams​

Parámetros enviados en la petición de verificación:

export interface VerifyParams {
companyNit?: string; // NIT o documento de identificación de la empresa
companyName?: string; // Nombre o razón social
licenseToken?: string; // Token firmado almacenado localmente
customData?: Record<string, any>; // Metadatos personalizados (ej: { maxClusters: 4 })
features?: string[]; // Lista de módulos solicitados
isPrimaryHost?: boolean; // Indica si el host actual es el nodo principal
onRevoked?: () => void; // Callback ejecutado si la licencia fue revocada en el VPS
}

ValidLicenseRecord​

Respuesta tipada que describe el estado y privilegios de la licencia:

export interface ValidLicenseRecord {
isActive: boolean; // true si la licencia está vigente y autorizada
status: 'ACTIVE' | 'SUSPENDED' | 'EXPIRED' | 'REVOKED' | 'NOT_FOUND'; // Estado operacional
companyName: string; // Razón social del cliente
companyNit?: string; // NIT del cliente
plan: string; // Nombre del plan contratado
expiresAt: string; // Fecha de vencimiento en formato ISO 8601
daysLeft: number; // Días enteros restantes
isTrial: boolean; // true si está en período de prueba
maxUsers: number; // Límite de usuarios simultáneos
dianQuota: number; // Cuota autorizada de facturas electrónicas
dianUsed: number; // Facturas emitidas en el ciclo
features: string[]; // Módulos contratados
customData: Record<string, any>; // Datos adicionales
serverMessage: string; // Mensaje emitido por el servidor
token?: string; // Token renovado emitido por el VPS
}

⚙️ 2. Métodos de la Clase ValidLicenseClient​

Constructor​

const client = new ValidLicenseClient({
serverUrl: 'https://licencias.labtec.sbs',
publicKeyHex: process.env.ED25519_PUBLIC_KEY,
clientVersion: '2026.1',
});

getMachineId(): Promise<string>​

  • Propósito: Genera el identificador de hardware único formateado como REX-XXXX-XXXX-XXXX.
  • Implementación por Sistema Operativo:
    • Windows: Consulta HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid vía reg.exe query. En caso de fallo, realiza una consulta WMI a Win32_ComputerSystemProduct.UUID.
    • Linux / Docker: Lee /etc/machine-id o /var/lib/dbus/machine-id.
    • macOS: Ejecuta ioreg -rd1 -c IOPlatformExpertDevice extrayendo el IOPlatformUUID.
    • Genera una suma criptográfica crypto.createHash('sha256') memoizada en memoria.

verifyTokenSignature(token: string): boolean​

  • Propósito: Valida matemáticamente si la firma digital Ed25519 del token es auténtica sin realizar ninguna petición HTTP.
  • Funcionamiento Criptográfico:
    • Descompone el token en payloadBase64Url y signatureHex.
    • Construye el prefijo estándar ASN.1 SPKI DER de 12 bytes (302a300506032b6570032100) para encapsular los 32 bytes de la clave pública Ed25519.
    • Crea un objeto de clave pública mediante crypto.createPublicKey({ key: spkiDer, format: 'der', type: 'spki' }).
    • Ejecuta la verificación estricta con crypto.verify(null, messageBytes, keyObject, sigBytes).

decodeToken(token: string): any | null​

  • Propósito: Valida la firma del token y retorna el objeto JSON decodificado del payload. Si la firma fue alterada o no corresponde a la clave pública, retorna null.

verify(params: VerifyParams): Promise<ValidLicenseRecord>​

  • Propósito: Realiza la verificación completa en dos fases:
    1. Fase 1 (Online): Realiza un POST a ${serverUrl}/api/v1/license/verify. Si el servidor responde 200 OK, actualiza la fecha de último latido y extrae las cuotas actualizadas. Si la licencia está revocada, ejecuta params.onRevoked?.() y retorna isActive: false.
    2. Fase 2 (Fallback Offline Criptográfico): Si el servidor no responde (o no hay conexión de red), invoca decodeToken(params.licenseToken). Si la firma es legítima, el Machine ID coincide y la fecha de expiración no ha pasado, retorna isActive: true.

🛡️ 3. Módulo AntiTamperHelper (Defensa Avanzada en Node.js / Bun)​

Proporciona utilidades para impedir el parcheo de binarios y el retraso de reloj:

  • AntiTamperHelper.deriveEncryptionKey(rawToken, salt):
    • Deriva una clave AES-256 a partir de la firma Ed25519 para descifrar bases de datos locales o credenciales en memoria.
  • AntiTamperHelper.verifyClockIntegrity(params):
    • Valida el avance del reloj comparando la marca de tiempo contra el hash firmado anterior.
  • AntiTamperHelper.isDebuggerAttached():
    • Detecta si el proceso Node.js o Bun se ejecuta con --inspect, --debug o el inspector V8 activo.

🔒 4. Módulo UiGuard (Protección de Vistas & Frontend en Node / React / Vue)​

Permite blindar vistas de SSR, Next.js, Nuxt o aplicaciones Electron/Tauri:

import { UiGuard } from 'validlicense-sdk';

// 1. Proteger una vista o componente
const viewHtml = UiGuard.guardView(
license,
() => renderFacturacionPage(), // Se ejecuta solo si la licencia es válida
() => renderPantallaBloqueo() // Fallback si no está autorizada
);

// 2. Proteger por Feature Flag
const copilotWidget = UiGuard.guardFeature(
license,
'ai_assistant',
() => renderCopilotWidget(),
() => ''
);

// 3. Proteger páginas compiladas de React (PageVenta.tsx) o Vue (PageVenta.vue)
const finalHtml = UiGuard.guardAsset(license, bundledReactHtml);

💻 5. Ejemplo Completo de Integración​

import { ValidLicenseClient } from 'validlicense-sdk';
import 'dotenv/config';

async function bootstrap() {
const client = new ValidLicenseClient({
serverUrl: process.env.VALID_LICENSE_SERVER_URL || 'https://licencias.labtec.sbs',
publicKeyHex: process.env.ED25519_PUBLIC_KEY,
});

const machineId = await client.getMachineId();
console.log(`🔒 Identificador de Hardware: ${machineId}`);

const license = await client.verify({
companyNit: '900.888.777-1',
companyName: 'Comercializadora Global SAS',
licenseToken: process.env.LICENSE_TOKEN,
features: ['api_gateway', 'electronic_billing'],
onRevoked: () => {
console.error('⛔ ALERTA: La licencia fue revocada o suspendida en el VPS.');
process.exit(1);
},
});

if (!license.isActive) {
console.error('❌ Acceso Denegado:', license.serverMessage);
process.exit(1);
}

console.log('✅ Licencia Autorizada:', license.companyName);
console.log(`📦 Plan: ${license.plan} | Vence: ${license.expiresAt} (${license.daysLeft} días restantes)`);
}

bootstrap();