4NK_vault/docs/sdk-documentation.md
4NK Dev fcb15afb88 Initial commit: 4NK Vault API with quantum-resistant encryption
- API server with ChaCha20-Poly1305 encryption
- TypeScript SDK client with full functionality
- Complete documentation in docs/
- Environment variable processing with composite variables
- HTTPS-only API on port 6666
- Storage structure for configuration files
- Tests and examples included

Features:
- Quantum-resistant encryption (ChaCha20-Poly1305)
- Variable substitution from .env files
- Comprehensive TypeScript SDK
- Full API documentation and specifications
- Deployment guides and security model
2025-09-29 21:02:18 +00:00

14 KiB

SDK Client TypeScript - Documentation complète

Vue d'ensemble

Le SDK Client TypeScript pour l'API Vault 4NK fournit une interface type-safe et moderne pour interagir avec l'API de stockage sécurisé. Il inclut le déchiffrement côté client, la gestion d'erreurs avancée, et des utilitaires cryptographiques.

Installation

NPM

npm install @4nk/vault-sdk

Depuis les sources

git clone https://git.4nkweb.com/4nk/vault-sdk.git
cd vault-sdk
npm install
npm run build

Configuration

Importation de base

import { VaultClient, createVaultClient, VaultCrypto } from '@4nk/vault-sdk';

Création d'un client

Méthode simple

const client = createVaultClient(
  'https://vault.4nkweb.com:6666',
  'quantum_resistant_demo_key_32byt'
);

Méthode avancée

const client = new VaultClient(
  {
    baseUrl: 'https://vault.4nkweb.com:6666',
    verifySsl: false, // Pour les certificats auto-signés
    timeout: 15000,   // 15 secondes
  },
  'quantum_resistant_demo_key_32byt'
);

API Reference

Classe VaultClient

Constructeur

constructor(config: VaultConfig, decryptionKey: string)

Paramètres :

  • config : Configuration du client
  • decryptionKey : Clé de déchiffrement (32 bytes exactement)

Configuration :

interface VaultConfig {
  baseUrl: string;           // URL de base de l'API
  verifySsl?: boolean;       // Validation SSL (défaut: true)
  timeout?: number;          // Timeout en ms (défaut: 30000)
}

Méthodes

getFile(env: string, filePath: string): Promise<VaultFile>

Récupère et déchiffre un fichier depuis l'API.

Paramètres :

  • env : Environnement (ex: "dev", "prod")
  • filePath : Chemin du fichier relatif

Retour :

interface VaultFile {
  content: string;           // Contenu déchiffré
  filename: string;          // Nom du fichier
  size: number;              // Taille en caractères
  encrypted: boolean;        // Était chiffré
  algorithm?: string;        // Algorithme utilisé
}

Exemple :

try {
  const file = await client.getFile('dev', 'bitcoin/bitcoin.conf');
  console.log(`Fichier: ${file.filename}`);
  console.log(`Taille: ${file.size} caractères`);
  console.log(`Contenu: ${file.content}`);
} catch (error) {
  console.error('Erreur:', error.message);
}
getFiles(requests: FileRequest[]): Promise<VaultFile[]>

Récupère plusieurs fichiers en parallèle.

Paramètres :

interface FileRequest {
  env: string;
  filePath: string;
}

Exemple :

const files = await client.getFiles([
  { env: 'dev', filePath: 'bitcoin/bitcoin.conf' },
  { env: 'dev', filePath: 'tor/torrc' },
  { env: 'dev', filePath: 'sdk_relay/sdk_relay.conf' }
]);

files.forEach(file => {
  console.log(`${file.filename}: ${file.size} caractères`);
});
health(): Promise<VaultHealth>

Vérifie l'état de santé de l'API.

Retour :

interface VaultHealth {
  status: string;            // "healthy" ou "unhealthy"
  service: string;           // Nom du service
  encryption: string;        // Type de chiffrement
  algorithm: string;         // Algorithme utilisé
}

Exemple :

const health = await client.health();
console.log(`Statut: ${health.status}`);
console.log(`Chiffrement: ${health.encryption}`);
info(): Promise<VaultInfo>

Récupère les informations sur l'API.

Retour :

interface VaultInfo {
  name: string;              // Nom de l'API
  version: string;           // Version
  domain: string;            // Domaine
  port: number;              // Port
  protocol: string;          // Protocole
  encryption: string;        // Type de chiffrement
  endpoints: Record<string, string>; // Endpoints disponibles
}

Exemple :

const info = await client.info();
console.log(`API: ${info.name} v${info.version}`);
console.log(`Domaine: ${info.domain}:${info.port}`);
ping(): Promise<boolean>

Teste la connectivité à l'API.

Retour : true si connecté, false sinon

Exemple :

const isConnected = await client.ping();
if (isConnected) {
  console.log('✅ API accessible');
} else {
  console.log('❌ API inaccessible');
}
searchFiles(env: string, pattern?: RegExp): Promise<string[]>

Recherche des fichiers par pattern (non implémenté côté serveur).

Note : Cette méthode retourne toujours un tableau vide car l'endpoint de recherche n'est pas encore implémenté côté serveur.

Classe VaultCrypto

Utilitaires pour la gestion des clés de chiffrement.

generateKey(): string

Génère une clé de déchiffrement aléatoire de 32 bytes.

Retour : Clé de 32 caractères UTF-8

Exemple :

const randomKey = VaultCrypto.generateKey();
console.log(`Clé générée: ${randomKey.substring(0, 10)}...`);

hashToKey(password: string): string

Dérive une clé de 32 bytes depuis un mot de passe.

Paramètres :

  • password : Mot de passe source

Retour : Clé de 32 bytes dérivée avec SHA-256

Exemple :

const password = 'mon-mot-de-passe-secret';
const derivedKey = VaultCrypto.hashToKey(password);
console.log(`Clé dérivée: ${derivedKey.substring(0, 10)}...`);

validateKey(key: string): boolean

Vérifie qu'une clé fait exactement 32 bytes.

Paramètres :

  • key : Clé à valider

Retour : true si la clé est valide, false sinon

Exemple :

const key = 'quantum_resistant_demo_key_32byt';
const isValid = VaultCrypto.validateKey(key);
console.log(`Clé valide: ${isValid}`);

Gestion d'erreurs

Classes d'erreurs

VaultApiError

Erreurs liées aux requêtes HTTP vers l'API.

class VaultApiError extends Error {
  constructor(
    message: string,
    public statusCode?: number,
    public endpoint?: string
  );
}

Propriétés :

  • message : Message d'erreur
  • statusCode : Code HTTP d'erreur
  • endpoint : Endpoint qui a échoué

Exemple :

try {
  await client.getFile('dev', 'fichier-inexistant.conf');
} catch (error) {
  if (error instanceof VaultApiError) {
    console.error(`Erreur API: ${error.message}`);
    console.error(`Code: ${error.statusCode}`);
    console.error(`Endpoint: ${error.endpoint}`);
  }
}

VaultDecryptionError

Erreurs liées au déchiffrement des fichiers.

class VaultDecryptionError extends Error {
  constructor(message: string);
}

Exemple :

try {
  const file = await client.getFile('dev', 'config.conf');
} catch (error) {
  if (error instanceof VaultDecryptionError) {
    console.error(`Erreur de déchiffrement: ${error.message}`);
  }
}

Gestion d'erreurs complète

async function handleFileRequest(env: string, filePath: string) {
  try {
    const file = await client.getFile(env, filePath);
    return file;
  } catch (error) {
    if (error instanceof VaultApiError) {
      switch (error.statusCode) {
        case 404:
          console.error(`Fichier non trouvé: ${filePath}`);
          break;
        case 403:
          console.error(`Accès non autorisé: ${filePath}`);
          break;
        case 500:
          console.error(`Erreur serveur pour: ${filePath}`);
          break;
        default:
          console.error(`Erreur API: ${error.message}`);
      }
    } else if (error instanceof VaultDecryptionError) {
      console.error(`Erreur de déchiffrement: ${error.message}`);
    } else {
      console.error(`Erreur inconnue: ${error.message}`);
    }
    throw error;
  }
}

Exemples d'utilisation

Exemple basique

import { createVaultClient } from '@4nk/vault-sdk';

async function basicExample() {
  // Création du client
  const client = createVaultClient(
    'https://vault.4nkweb.com:6666',
    'quantum_resistant_demo_key_32byt'
  );

  // Test de connectivité
  const isConnected = await client.ping();
  if (!isConnected) {
    throw new Error('Impossible de se connecter à l\'API');
  }

  // Récupération d'un fichier
  const file = await client.getFile('dev', 'bitcoin/bitcoin.conf');
  console.log(`Fichier: ${file.filename}`);
  console.log(`Taille: ${file.size} caractères`);
  console.log(`Contenu: ${file.content.substring(0, 100)}...`);
}

Exemple avancé avec gestion d'erreurs

import { VaultClient, VaultApiError, VaultDecryptionError } from '@4nk/vault-sdk';

async function advancedExample() {
  const client = new VaultClient(
    {
      baseUrl: 'https://vault.4nkweb.com:6666',
      timeout: 10000,
    },
    'quantum_resistant_demo_key_32byt'
  );

  // Informations sur l'API
  try {
    const info = await client.info();
    console.log(`API: ${info.name} v${info.version}`);
  } catch (error) {
    console.error('Erreur info:', error.message);
  }

  // Récupération de plusieurs fichiers
  const requests = [
    { env: 'dev', filePath: 'bitcoin/bitcoin.conf' },
    { env: 'dev', filePath: 'tor/torrc' },
    { env: 'dev', filePath: 'sdk_relay/sdk_relay.conf' }
  ];

  try {
    const files = await client.getFiles(requests);
    console.log(`${files.length} fichiers récupérés`);

    files.forEach((file, index) => {
      console.log(`${index + 1}. ${file.filename}: ${file.size} chars`);
    });
  } catch (error) {
    if (error instanceof VaultApiError) {
      console.error(`Erreur API: ${error.statusCode} - ${error.message}`);
    } else if (error instanceof VaultDecryptionError) {
      console.error(`Erreur de déchiffrement: ${error.message}`);
    }
  }
}

Exemple avec retry automatique

async function retryOperation<T>(
  operation: () => Promise<T>,
  maxRetries: number = 3,
  delay: number = 1000
): Promise<T> {
  let lastError: Error;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error) {
      lastError = error as Error;
      console.log(`Tentative ${attempt}/${maxRetries} échouée: ${lastError.message}`);

      if (attempt < maxRetries) {
        await new Promise(resolve => setTimeout(resolve, delay));
      }
    }
  }

  throw lastError!;
}

// Utilisation
const file = await retryOperation(
  () => client.getFile('dev', 'bitcoin/bitcoin.conf'),
  3,
  500
);

Configuration TypeScript

tsconfig.json recommandé

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020", "DOM"],
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "sourceMap": true
  }
}

Types personnalisés

// Extension des types existants
interface CustomVaultFile extends VaultFile {
  metadata?: {
    lastModified: Date;
    checksum: string;
  };
}

// Types pour vos applications
interface ConfigFile {
  environment: string;
  services: string[];
  variables: Record<string, string>;
}

Tests

Tests unitaires avec Jest

import { VaultClient, VaultCrypto } from '@4nk/vault-sdk';

describe('VaultClient', () => {
  let client: VaultClient;

  beforeEach(() => {
    client = new VaultClient(
      { baseUrl: 'https://vault.4nkweb.com:6666' },
      'quantum_resistant_demo_key_32byt'
    );
  });

  it('devrait récupérer un fichier', async () => {
    const file = await client.getFile('dev', 'bitcoin/bitcoin.conf');
    expect(file).toBeDefined();
    expect(file.filename).toBe('bitcoin.conf');
    expect(file.content).toBeTruthy();
  });

  it('devrait gérer les erreurs 404', async () => {
    await expect(client.getFile('dev', 'fichier-inexistant.conf'))
      .rejects
      .toThrow('Fichier non trouvé');
  });
});

Tests d'intégration

describe('Intégration API', () => {
  it('devrait fonctionner end-to-end', async () => {
    const client = createVaultClient(
      'https://vault.4nkweb.com:6666',
      'quantum_resistant_demo_key_32byt'
    );

    // Test de santé
    const health = await client.health();
    expect(health.status).toBe('healthy');

    // Test de fichier
    const file = await client.getFile('dev', 'bitcoin/bitcoin.conf');
    expect(file.content).toContain('bitcoin');
  });
});

Performance et optimisation

Récupération parallèle

// ✅ Bon : Récupération parallèle
const files = await client.getFiles(requests);

// ❌ Mauvais : Récupération séquentielle
const files = [];
for (const request of requests) {
  const file = await client.getFile(request.env, request.filePath);
  files.push(file);
}

Cache local

class CachedVaultClient extends VaultClient {
  private cache = new Map<string, VaultFile>();

  async getFile(env: string, filePath: string): Promise<VaultFile> {
    const key = `${env}/${filePath}`;

    if (this.cache.has(key)) {
      return this.cache.get(key)!;
    }

    const file = await super.getFile(env, filePath);
    this.cache.set(key, file);
    return file;
  }
}

Dépannage

Problèmes courants

Erreur de clé de déchiffrement

Error: La clé de déchiffrement doit faire exactement 32 bytes

Solution : Vérifiez que votre clé fait exactement 32 caractères UTF-8.

Erreur de connectivité

Error: fetch failed

Solutions :

  • Vérifiez que l'API est démarrée
  • Vérifiez l'URL de base
  • Désactivez la validation SSL si nécessaire (verifySsl: false)

Erreur de déchiffrement

VaultDecryptionError: Erreur de déchiffrement

Solutions :

  • Vérifiez que la clé correspond à celle utilisée côté serveur
  • Vérifiez que le fichier n'est pas corrompu

Debug

// Activation des logs détaillés
const client = new VaultClient(
  {
    baseUrl: 'https://vault.4nkweb.com:6666',
    timeout: 30000
  },
  'quantum_resistant_demo_key_32byt'
);

// Test de connectivité
const isConnected = await client.ping();
console.log('Connecté:', isConnected);

// Test d'information
try {
  const info = await client.info();
  console.log('Info API:', info);
} catch (error) {
  console.error('Erreur info:', error);
}

Support


Version SDK : 1.0.0 Compatibilité API : 1.0.0+