
- 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
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 clientdecryptionKey
: 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'erreurstatusCode
: Code HTTP d'erreurendpoint
: 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
- Documentation : docs/README.md
- API Specification : docs/api-specification.md
- Issues : Git Issues
- Email : sdk-support@4nkweb.com
Version SDK : 1.0.0 Compatibilité API : 1.0.0+