PR Sécurité 4 (Interfaces TS/Wasm) #4

Open
opened 2025-07-18 09:28:13 +00:00 by nicolas.cantu · 0 comments

PR : Interfaces TypeScript/WebAssembly (TS/Wasm)

Objectif

Renforcer la sécurité, la robustesse et la conformité des interfaces entre le code TypeScript et WebAssembly (Rust) en :

  • Instaurant des guidelines de tests et de validation des interfaces TS/Wasm.
  • Proposant des adaptations concrètes du code et des tests pour garantir l’intégrité, la validation des types, la gestion des erreurs et la traçabilité des échanges.

1. Guidelines pour la sécurité et la conformité des interfaces TS/Wasm

A. Validation stricte des entrées/sorties

  • Toujours valider les types et la structure des données échangées entre TS et Wasm (avant l’appel et après le retour).
  • Utiliser des schémas de validation (ex : Zod, io-ts, custom validators) côté TypeScript pour toutes les structures complexes.
  • Vérifier la présence et la validité des champs obligatoires (ex : pas de undefined, pas de champ manquant, pas de type inattendu).

B. Gestion des erreurs et des exceptions

  • Encapsuler tous les appels Wasm dans des blocs try/catch côté TypeScript.
  • Remonter les erreurs Wasm sous forme d’objets structurés (ex : { code, message, stack }).
  • Logger systématiquement les erreurs inattendues et prévoir une gestion utilisateur (alerte, rollback, etc.).

C. Sérialisation/désérialisation sécurisée

  • Éviter le passage de données brutes non validées (ex : JSON.parse sans contrôle, buffers non typés).
  • Préférer des structures typées et validées pour tous les échanges (ex : interfaces, enums, tuples).

D. Tests unitaires et d’intégration systématiques

  • Écrire des tests unitaires pour chaque fonction d’interface (TS <-> Wasm) : cas nominal, cas d’erreur, cas de bord.
  • Écrire des tests d’intégration pour les scénarios critiques (ex : création de process, signature, validation, etc.).
  • Automatiser les tests dans la CI/CD (GitHub Actions, GitLab CI, etc.).

E. Documentation et traçabilité

  • Documenter chaque interface TS/Wasm (types attendus, exceptions possibles, schémas de validation).
  • Tracer les appels critiques (logs, audit trail) pour les opérations sensibles (signature, backup, gestion des rôles, etc.).

2. Modifications à apporter dans le code

A. Ajout de schémas de validation TypeScript

  • Créer des validateurs pour chaque structure échangée avec Wasm, par exemple :
import { z } from 'zod';

export const ProcessInputSchema = z.object({
  id: z.string(),
  name: z.string(),
  // ... autres champs
});

export type ProcessInput = z.infer<typeof ProcessInputSchema>;
  • Valider les données avant tout appel Wasm :
function callWasmProcess(input: any) {
  const parseResult = ProcessInputSchema.safeParse(input);
  if (!parseResult.success) {
    throw new Error('Invalid process input: ' + parseResult.error.message);
  }
  // Appel Wasm ici
}

B. Encapsulation des appels Wasm

  • Créer des wrappers pour chaque fonction Wasm, avec gestion d’erreur et validation de sortie :
async function safeWasmCall<T, R>(fn: (input: T) => R, input: T, outputSchema: z.ZodType<R>): Promise<R> {
  try {
    const result = fn(input);
    const parseResult = outputSchema.safeParse(result);
    if (!parseResult.success) {
      throw new Error('Invalid output from Wasm: ' + parseResult.error.message);
    }
    return parseResult.data;
  } catch (e) {
    // Log, notifier, etc.
    throw new Error('Wasm call failed: ' + (e instanceof Error ? e.message : String(e)));
  }
}

C. Ajout de tests unitaires et d’intégration

  • Pour chaque interface critique, ajouter des tests dans __tests__/ ou tests/ :
import { safeWasmCall } from '../src/wasm-wrapper';
import { ProcessInputSchema, ProcessOutputSchema } from '../src/models/validation';

test('Wasm process creation - valid input', async () => {
  const input = { id: 'p1', name: 'Test' /* ... */ };
  const result = await safeWasmCall(wasm.create_process, input, ProcessOutputSchema);
  expect(result).toHaveProperty('process_id');
});

test('Wasm process creation - invalid input', async () => {
  const input = { id: 123, name: null };
  await expect(safeWasmCall(wasm.create_process, input, ProcessOutputSchema)).rejects.toThrow();
});

D. CI/CD

  • Ajouter l’exécution des tests dans le pipeline CI/CD de chaque repo du dossier 4NK.
  • Bloquer le merge en cas d’échec des tests d’interface.

3. Documentation à ajouter

  • Pour chaque interface TS/Wasm, ajouter un commentaire JSDoc/TSdoc précisant :
    • Les types attendus/retournés
    • Les erreurs possibles
    • Les schémas de validation utilisés

4. Bénéfices attendus

  • Réduction drastique des risques d’injection, de corruption de données ou de crash liés aux échanges TS/Wasm.
  • Auditabilité et traçabilité des échanges critiques.
  • Conformité avec les exigences de sécurité (OWASP, EBA, SecNumCloud, etc.).
  • Robustesse accrue du code et meilleure maintenabilité.

5. Plan d’action

Lister toutes les interfaces TS/Wasm critiques dans chaque repo du dossier 4NK.

1. ihm_client

a. Appels principaux (src/services/service.ts, src/pages/...)
  • createProcess / updateProcess / createPairingProcess

    • Entrée : objets process, rôles, données privées/publiques
    • Sortie : objet ApiReturn (process créé/mis à jour)
    • Sécurisation attendue :
      • Validation stricte des objets (schéma Zod/io-ts)
      • Vérification des types et champs obligatoires
      • Gestion d’erreur (try/catch, message utilisateur)
      • Validation de la sortie (structure attendue)
  • sdkClient.encode_json / encode_binary / decode_json

    • Entrée : objets ou buffers à sérialiser/désérialiser
    • Sortie : string ou objet typé
    • Sécurisation attendue :
      • Validation du format avant encodage/décodage
      • Gestion des erreurs de parsing
      • Contrôle de la taille et du contenu
  • sdkClient.create_new_process / update_process / validate_state

    • Entrée : objets process, rôles, données
    • Sortie : objet ApiReturn
    • Sécurisation attendue :
      • Validation des structures avant appel
      • Vérification des droits (rôle, session)
      • Gestion d’erreur et rollback en cas d’échec
  • sdkClient.sign_transaction / parse_new_tx / parse_cipher

    • Entrée : transaction, message, cipher
    • Sortie : objet transaction/signature
    • Sécurisation attendue :
      • Validation du format de la transaction/message
      • Contrôle d’intégrité (hash, signature)
      • Gestion d’erreur et logs

2. sdk_client

a. Appels Wasm exposés (crates/sp_client/src/lib.rs, api.rs, user.rs, process.rs, etc.)
  • create_user / create_process / update_process / add_data_to_image

    • Entrée : objets utilisateur, process, image, etc.
    • Sortie : objets typés (User, Process, etc.)
    • Sécurisation attendue :
      • Validation des types à l’entrée (via tsify ou schéma JS)
      • Vérification des valeurs (non null, non vide, format)
      • Gestion d’erreur Rust (Result, panic catch)
      • Validation de la sortie (structure, types)
  • get_main_address / get_outputs / get_processes

    • Entrée : identifiants, filtres
    • Sortie : string, array, objets
    • Sécurisation attendue :
      • Validation des paramètres
      • Contrôle d’accès (session, droits)
      • Gestion d’erreur

3. sdk_storage

a. Appels via FFI/wasm (si exposés)
  • store_data / retrieve_data
    • Entrée : clé, valeur, TTL
    • Sortie : confirmation, données
    • Sécurisation attendue :
      • Validation de la clé (format, longueur)
      • Validation du contenu (taille, type)
      • Gestion d’erreur (clé existante, non trouvée)
      • Contrôle d’accès si multi-tenant

4. sdk_relay

a. Appels Wasm/TS (si relay expose une API JS/TS)
  • send_message / receive_message / subscribe
    • Entrée : message, type, destinataire
    • Sortie : confirmation, message reçu
    • Sécurisation attendue :
      • Validation du format du message
      • Contrôle du type et du destinataire
      • Gestion d’erreur (message non délivré, format invalide)
      • Logs/audit des échanges critiques

5. skeleton (si usage direct du SDK Wasm)

  • Appels via MessageBus/Iframe vers le SDK
    • Entrée/Sortie : objets process, profils, rôles, etc.
    • Sécurisation attendue :
      • Validation des messages échangés (schéma, type)
      • Gestion d’erreur et logs
      • Contrôle d’accès (session utilisateur)

Sécurisation attendue pour toutes les interfaces

  • Validation stricte des entrées et sorties (schéma, type, valeurs)
  • Gestion d’erreur systématique (try/catch, Result, logs)
  • Typage fort (TypeScript, Rust, tsify, enums)
  • Contrôle d’accès et de droits pour les opérations sensibles
  • Logs et audit pour les opérations critiques
  • Tests unitaires et d’intégration couvrant les cas nominaux, d’erreur et de bord

Créer les schémas de validation pour chaque structure échangée.

1. ihm_client

Processus (ProcessInput)
import { z } from 'zod';

export const ProcessInputSchema = z.object({
  id: z.string(),
  name: z.string(),
  description: z.string().optional(),
  icon: z.string().optional(),
  zoneList: z.array(z.object({
    id: z.string(),
    name: z.string(),
    // ... autres champs zone
  })),
  roles: z.record(z.string(), z.any()), // à raffiner avec RoleDefinitionSchema
  // Champs de conformité structurés
  legalClauses: z.array(z.object({
    title: z.string(),
    text: z.string(),
    version: z.string(),
    applicableFrom: z.string(),
  })),
  consent: z.object({
    given: z.boolean(),
    date: z.string(),
    method: z.enum(['checkbox', 'signature', 'other']),
    scope: z.string(),
    expiration: z.object({
      duration: z.string(),
      expiresAt: z.string(),
      reason: z.string(),
    }),
  }),
  contract: z.object({
    contractId: z.string(),
    parties: z.array(z.string()),
    signedAt: z.string(),
    expiration: z.object({
      duration: z.string(),
      expiresAt: z.string(),
      reason: z.string(),
    }),
    documentUrl: z.string(),
  }),
  legitimateInterest: z.object({
    description: z.string(),
    assessmentDate: z.string(),
    balancingTestDocumentUrl: z.string().optional(),
  }),
  oppositionRight: z.object({
    enabled: z.boolean(),
    process: z.string(),
    roles: z.array(z.string()),
    requests: z.array(z.any()), // à raffiner
  }),
  expiration: z.object({
    duration: z.string(),
    expiresAt: z.string(),
    reason: z.string(),
  }),
  dataLocations: z.array(z.object({
    country: z.string(),
    region: z.string().optional(),
    provider: z.string().optional(),
    storageType: z.enum(['cloud', 'on-premise', 'hybrid']),
    declaredBy: z.string(),
    declaredAt: z.string(),
  })),
  thirdPartyActors: z.array(z.object({
    name: z.string(),
    type: z.enum(['processor', 'sub-processor', 'controller', 'other']),
    contact: z.string(),
    contractReference: z.string(),
    dataCategories: z.array(z.string()),
    location: z.any(), // à raffiner avec DataLocationSchema
  })),
  privacyPolicy: z.object({
    url: z.string(),
    version: z.string(),
    applicableFrom: z.string(),
    summary: z.string(),
  }),
  legalNotice: z.object({
    url: z.string(),
    version: z.string(),
    applicableFrom: z.string(),
    summary: z.string(),
  }),
  inactiveAccountMetadata: z.object({
    lastActivityDate: z.string(),
    maxInactivityDuration: z.string(),
    status: z.enum(['active', 'inactive', 'pending_deletion']),
    deletionScheduledAt: z.string().optional(),
  }),
  trainingProofs: z.array(z.object({
    type: z.enum(['security', 'data_protection']),
    completed: z.boolean(),
    date: z.string(),
    provider: z.string(),
    certificateUrl: z.string().optional(),
  })),
});
Rôle de conformité (ComplianceRoleData)

Pour chaque rôle, un schéma dédié :

export const BackupRoleDataSchema = z.object({
  backupHistory: z.array(z.object({
    date: z.string(),
    performedBy: z.string(),
    backupType: z.enum(['full', 'incremental']),
    location: z.string(),
    integrityCheck: z.boolean(),
  })),
  lastBackupDate: z.string(),
  incidentProcedure: z.object({
    documentUrl: z.string(),
    version: z.string(),
    applicableFrom: z.string(),
    steps: z.array(z.string()),
    contact: z.string(),
  }),
});

Idem pour chaque rôle (DigitalLegalRequestsRoleDataSchema, SupportN1RoleDataSchema, etc.).

2. sdk_client

User (UserInput)
export const UserInputSchema = z.object({
  pre_id: z.string(),
  processes: z.array(z.string()),
  peers: z.array(z.any()), // à raffiner
  recover_data: z.any(),
  revoke_data: z.any().optional(),
  shares: z.array(z.any()),
  outputs: z.array(z.any()),
});
Process (ProcessInput)

Réutiliser le schéma de ihm_client ou l’adapter selon les besoins Rust/wasm.

3. sdk_storage

StoreRequest
export const StoreRequestSchema = z.object({
  key: z.string().length(64).regex(/^[a-fA-F0-9]+$/),
  value: z.string(), // hex ou base64 selon usage
  ttl: z.number().int().min(60).max(31_536_000).optional(),
});

4. sdk_relay

Message (RelayMessage)
export const RelayMessageSchema = z.object({
  type: z.string(),
  payload: z.any(), // à raffiner selon le type
  sender: z.string(),
  timestamp: z.string(),
});

5. skeleton

ProfileData
export const ProfileDataSchema = z.object({
  name: z.string(),
  surname: z.string(),
  email: z.string().email(),
  phone: z.string(),
  address: z.string(),
  postalCode: z.string(),
  city: z.string(),
  country: z.string(),
  idDocument: z.any().nullable(),
  idCertified: z.boolean(),
  // ... autres champs structurés si besoin
});

Sécurisation attendue pour chaque schéma

  • safeParse avant tout appel TS/Wasm ou lors de la réception de données.
  • Gestion d’erreur en cas d’échec de validation (log, rollback, message utilisateur).
  • Tests unitaires pour chaque schéma (cas valide, cas invalide, cas limite).

Encapsuler tous les appels Wasm dans des wrappers avec validation et gestion d’erreur.

Objectif

  • Encapsuler tous les appels Wasm (Rust <-> TypeScript) dans des fonctions wrappers.
  • Valider systématiquement les entrées et sorties via des schémas (Zod ou équivalent).
  • Gérer les erreurs de façon centralisée (try/catch, logs, messages utilisateur).
  • Renforcer la robustesse, la sécurité et la conformité des échanges TS/Wasm dans tous les projets du dossier 4NK.

1. Liste des appels Wasm à encapsuler

ihm_client / sdk_client (exemples principaux)
  • sdkClient.create_new_process
  • sdkClient.update_process
  • sdkClient.create_user
  • sdkClient.add_data_to_image
  • sdkClient.sign_transaction
  • sdkClient.parse_new_tx
  • sdkClient.parse_cipher
  • sdkClient.validate_state
  • sdkClient.encode_json
  • sdkClient.encode_binary
  • sdkClient.decode_json
  • sdkClient.get_main_address
  • sdkClient.get_outputs
  • sdkClient.get_processes
  • (et tout autre appel direct à une fonction exposée par le module Wasm)

2. Encapsulation type générique

Création d’un wrapper générique

Dans un fichier utilitaire commun (ex : src/wasm-wrapper.ts) :

import { z, ZodType } from 'zod';

export async function safeWasmCall<T, R>(
  fn: (input: T) => R | Promise<R>,
  input: T,
  inputSchema: ZodType<T>,
  outputSchema: ZodType<R>
): Promise<R> {
  // Validation de l'entrée
  const inputParse = inputSchema.safeParse(input);
  if (!inputParse.success) {
    throw new Error('Entrée invalide pour Wasm : ' + inputParse.error.message);
  }
  try {
    const result = await fn(input);
    // Validation de la sortie
    const outputParse = outputSchema.safeParse(result);
    if (!outputParse.success) {
      throw new Error('Sortie invalide de Wasm : ' + outputParse.error.message);
    }
    return outputParse.data;
  } catch (e) {
    // Gestion d’erreur centralisée
    console.error('Erreur lors de l’appel Wasm :', e);
    throw new Error('Erreur Wasm : ' + (e instanceof Error ? e.message : String(e)));
  }
}

3. Encapsulation de chaque appel critique

Exemple pour la création de process
import { safeWasmCall } from './wasm-wrapper';
import { ProcessInputSchema, ProcessOutputSchema } from './models/validation';

async function createProcessWasm(input: ProcessInput) {
  return await safeWasmCall(
    sdkClient.create_new_process,
    input,
    ProcessInputSchema,
    ProcessOutputSchema
  );
}
Exemple pour la mise à jour de process
async function updateProcessWasm(input: ProcessInput) {
  return await safeWasmCall(
    sdkClient.update_process,
    input,
    ProcessInputSchema,
    ProcessOutputSchema
  );
}
Exemple pour la signature de transaction
async function signTransactionWasm(input: TransactionInput) {
  return await safeWasmCall(
    sdkClient.sign_transaction,
    input,
    TransactionInputSchema,
    TransactionOutputSchema
  );
}
Exemple pour l’encodage/décodage
async function encodeJsonWasm(input: any) {
  return await safeWasmCall(
    sdkClient.encode_json,
    input,
    z.any(), // ou un schéma plus précis
    z.string()
  );
}

4. Utilisation dans la logique métier

  • Remplacer tous les appels directs à sdkClient.* par les wrappers sécurisés.
  • Gérer les erreurs retournées par les wrappers (affichage utilisateur, rollback, logs).
  • Ajouter des tests unitaires pour chaque wrapper (cas valide, cas invalide, cas d’erreur).

5. Bénéfices

  • Validation stricte des échanges TS/Wasm (plus de données corrompues ou inattendues).
  • Gestion d’erreur centralisée et traçable.
  • Sécurité et robustesse accrues (prévention des injections, crash, corruptions).
  • Conformité avec les exigences d’audit et de sécurité (OWASP, EBA, SecNumCloud, etc.).

6. Plan d’action

  1. Lister tous les appels Wasm critiques dans chaque repo du dossier 4NK.
  2. Créer les schémas de validation pour chaque structure échangée.
  3. Créer le wrapper générique safeWasmCall.
  4. Encapsuler chaque appel Wasm dans un wrapper dédié.
  5. Remplacer les appels directs dans la logique métier.
  6. Ajouter des tests unitaires et d’intégration.
  7. Documenter l’usage des wrappers et des schémas.

Écrire des tests unitaires et d’intégration pour chaque interface.

Objectif

  • Lister toutes les interfaces critiques TS/Wasm à tester .
  • Décrire la méthodologie de tests (unitaires et d’intégration).
  • Proposer l’intégration et l’implémentation concrète des tests.
  • Systématiser la couverture de tests pour garantir la robustesse, la sécurité et la conformité.

1. Liste des interfaces TS/Wasm à tester

ihm_client / sdk_client
  • sdkClient.create_new_process
  • sdkClient.update_process
  • sdkClient.create_user
  • sdkClient.add_data_to_image
  • sdkClient.sign_transaction
  • sdkClient.parse_new_tx
  • sdkClient.parse_cipher
  • sdkClient.validate_state
  • sdkClient.encode_json
  • sdkClient.encode_binary
  • sdkClient.decode_json
  • sdkClient.get_main_address
  • sdkClient.get_outputs
  • sdkClient.get_processes
  • (et tout autre appel direct à une fonction exposée par le module Wasm)
sdk_storage
  • store_data
  • retrieve_data
sdk_relay
  • send_message
  • receive_message
  • subscribe

2. Méthodologie de tests

A. Tests unitaires
  • But : Vérifier que chaque fonction d’interface TS/Wasm fonctionne correctement en isolation.
  • Cas à couvrir :
    • Cas nominal (entrée valide, sortie attendue)
    • Cas d’erreur (entrée invalide, exception, retour d’erreur)
    • Cas de bord (valeurs limites, champs manquants, types inattendus)
  • Outils : Jest, Vitest, Mocha, etc. (selon le repo)
  • Utilisation des schémas de validation : Les entrées/sorties sont validées avec Zod/io-ts avant et après l’appel.
B. Tests d’intégration
  • But : Vérifier que l’interface TS/Wasm fonctionne dans un scénario applicatif réel (ex : création de process, signature, etc.).
  • Cas à couvrir :
    • Enchaînement d’appels (ex : create_process puis update_process)
    • Interaction avec la persistance (IndexedDB, storage, etc.)
    • Gestion des erreurs et des retours inattendus
  • Outils : Jest, Playwright, Cypress, tests end-to-end, etc.

3. Intégration et implémentation des tests

A. Structure des fichiers de tests
  • Créer un dossier __tests__ ou tests/ à la racine de chaque repo ou dans src/.
  • Un fichier de test par interface ou par module (ex : createProcess.wasm.test.ts, signTransaction.wasm.test.ts).

B. Exemple de test unitaire (Jest + Zod)

import { safeWasmCall } from '../src/wasm-wrapper';
import { ProcessInputSchema, ProcessOutputSchema } from '../src/models/validation';
import sdkClient from '../src/wasm-client';

describe('Wasm create_new_process', () => {
  it('should create a process with valid input', async () => {
    const input = { id: 'p1', name: 'Test', /* ... */ };
    const result = await safeWasmCall(
      sdkClient.create_new_process,
      input,
      ProcessInputSchema,
      ProcessOutputSchema
    );
    expect(result).toHaveProperty('process_id');
  });

  it('should throw on invalid input', async () => {
    const input = { id: 123, name: null };
    await expect(
      safeWasmCall(sdkClient.create_new_process, input, ProcessInputSchema, ProcessOutputSchema)
    ).rejects.toThrow();
  });
});
C. Exemple de test d’intégration
import { safeWasmCall } from '../src/wasm-wrapper';
import { ProcessInputSchema, ProcessOutputSchema } from '../src/models/validation';
import sdkClient from '../src/wasm-client';

describe('Wasm process integration', () => {
  it('should create and update a process end-to-end', async () => {
    const createInput = { id: 'p2', name: 'Integration', /* ... */ };
    const created = await safeWasmCall(
      sdkClient.create_new_process,
      createInput,
      ProcessInputSchema,
      ProcessOutputSchema
    );
    expect(created).toHaveProperty('process_id');

    const updateInput = { ...createInput, name: 'Integration Updated' };
    const updated = await safeWasmCall(
      sdkClient.update_process,
      updateInput,
      ProcessInputSchema,
      ProcessOutputSchema
    );
    expect(updated).toHaveProperty('process_id');
    expect(updated.name).toBe('Integration Updated');
  });
});

4. Systématisation des tests

  • Chaque nouvelle interface TS/Wasm doit être accompagnée d’un test unitaire et d’un test d’intégration.
  • Les tests doivent être exécutés automatiquement dans la CI/CD (GitHub Actions, GitLab CI, etc.).
  • Le merge est bloqué si la couverture de tests sur les interfaces critiques baisse ou si un test échoue.
  • Les schémas de validation sont utilisés dans tous les tests pour garantir la conformité des échanges.

5. Bénéfices

  • Robustesse : détection précoce des régressions et des erreurs d’intégration.
  • Sécurité : prévention des injections, corruptions, crashs liés aux échanges TS/Wasm.
  • Conformité : traçabilité et auditabilité des échanges critiques.
  • Qualité : confiance accrue dans la stabilité de la plateforme.

6. Plan d’action

  1. Lister toutes les interfaces TS/Wasm critiques dans chaque repo.
  2. Créer les schémas de validation pour chaque structure échangée.
  3. Écrire les tests unitaires et d’intégration pour chaque interface.
  4. Automatiser l’exécution des tests dans la CI/CD.
  5. Documenter la méthodologie et les cas de test.

Automatiser l’exécution des tests dans la CI/CD.

Objectif

  • Automatiser l’exécution des tests unitaires et d’intégration pour toutes les interfaces TS/Wasm critiques.
  • Garantir la robustesse, la sécurité et la conformité du code à chaque push, merge ou release.
  • Bloquer le merge en cas d’échec des tests ou de baisse de couverture sur les interfaces critiques.

1. Liste des tests à automatiser

  • Tous les tests unitaires et d’intégration couvrant les interfaces TS/Wasm listées dans la PR précédente :
    • sdkClient.create_new_process, update_process, create_user, etc.
    • Fonctions de validation, d’encodage/décodage, de signature, etc.
    • Tests de validation des schémas (Zod/io-ts)
    • Tests de gestion d’erreur et de cas limites

2. Méthodologie d’intégration CI/CD

A. Ajout d’un job de test dans le pipeline CI/CD
  • GitHub Actions (.github/workflows/ci.yml) ou GitLab CI (.gitlab-ci.yml) ou autre selon le repo.
  • Étapes principales :
    1. Installation des dépendances (npm/yarn/pnpm + build wasm si besoin)
    2. Compilation du code (TypeScript, Rust/Wasm)
    3. Exécution des tests (Jest, Vitest, Mocha, etc.)
    4. Vérification de la couverture (optionnel mais recommandé)
    5. Blocage du pipeline en cas d’échec
B. Exemple de configuration GitHub Actions
name: CI

on:
  push:
    branches: [main, develop, feature/*]
  pull_request:
    branches: [main, develop]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
      - name: Install dependencies
        run: npm ci
      - name: Build Wasm (si besoin)
        run: npm run build_wasm || true
      - name: Build TypeScript
        run: npm run build || true
      - name: Run tests
        run: npm test
      - name: Check coverage
        run: npm run coverage || true

C. Exemple de configuration GitLab CI

stages:
  - test

test:
  image: node:20
  script:
    - npm ci
    - npm run build_wasm || true
    - npm run build || true
    - npm test
    - npm run coverage || true
  only:
    - merge_requests
    - main
    - develop

3. Implémentation concrète

  • Ajouter/adapter le script de test dans le package.json :
    "scripts": {
      "test": "jest --runInBand",
      "build_wasm": "wasm-pack build --out-dir ./dist/pkg ./crates/sp_client --target bundler --dev",
      "build": "tsc && vite build",
      "coverage": "jest --coverage"
    }
    
  • S’assurer que tous les tests sont détectés (dossier __tests__ ou tests/).
  • Inclure la compilation du Wasm si besoin avant les tests.
  • Ajouter un badge de statut CI dans le README de chaque repo.

4. Systématisation et blocage du merge

  • Le pipeline doit échouer si un test échoue ou si la couverture baisse sur les interfaces critiques.
  • Le merge est bloqué tant que la CI n’est pas verte.
  • Les tests sont exécutés sur chaque push, PR/MR, et avant chaque release.

5. Bénéfices

  • Détection immédiate des régressions ou des failles sur les interfaces TS/Wasm.
  • Conformité avec les exigences de sécurité et d’audit (OWASP, EBA, SecNumCloud, etc.).
  • Qualité et robustesse du code garanties à chaque livraison.

6. Plan d’action

  1. Ajouter/adapter le pipeline CI/CD dans chaque repo du dossier 4NK.
  2. S’assurer que tous les tests unitaires et d’intégration sont exécutés automatiquement.
  3. Bloquer le merge en cas d’échec.
  4. Documenter la procédure dans le README et la spec technique.

Documenter chaque interface et chaque schéma de validation.

# PR : Interfaces TypeScript/WebAssembly (TS/Wasm) ## Objectif Renforcer la sécurité, la robustesse et la conformité des interfaces entre le code TypeScript et WebAssembly (Rust) en : - Instaurant des guidelines de tests et de validation des interfaces TS/Wasm. - Proposant des adaptations concrètes du code et des tests pour garantir l’intégrité, la validation des types, la gestion des erreurs et la traçabilité des échanges. --- ## 1. **Guidelines pour la sécurité et la conformité des interfaces TS/Wasm** ### **A. Validation stricte des entrées/sorties** - **Toujours valider les types et la structure des données** échangées entre TS et Wasm (avant l’appel et après le retour). - **Utiliser des schémas de validation** (ex : Zod, io-ts, custom validators) côté TypeScript pour toutes les structures complexes. - **Vérifier la présence et la validité des champs obligatoires** (ex : pas de `undefined`, pas de champ manquant, pas de type inattendu). ### **B. Gestion des erreurs et des exceptions** - **Encapsuler tous les appels Wasm dans des blocs try/catch** côté TypeScript. - **Remonter les erreurs Wasm sous forme d’objets structurés** (ex : `{ code, message, stack }`). - **Logger systématiquement les erreurs inattendues** et prévoir une gestion utilisateur (alerte, rollback, etc.). ### **C. Sérialisation/désérialisation sécurisée** - **Éviter le passage de données brutes non validées** (ex : JSON.parse sans contrôle, buffers non typés). - **Préférer des structures typées et validées** pour tous les échanges (ex : interfaces, enums, tuples). ### **D. Tests unitaires et d’intégration systématiques** - **Écrire des tests unitaires pour chaque fonction d’interface** (TS <-> Wasm) : cas nominal, cas d’erreur, cas de bord. - **Écrire des tests d’intégration pour les scénarios critiques** (ex : création de process, signature, validation, etc.). - **Automatiser les tests dans la CI/CD** (GitHub Actions, GitLab CI, etc.). ### **E. Documentation et traçabilité** - **Documenter chaque interface TS/Wasm** (types attendus, exceptions possibles, schémas de validation). - **Tracer les appels critiques** (logs, audit trail) pour les opérations sensibles (signature, backup, gestion des rôles, etc.). --- ## 2. **Modifications à apporter dans le code** ### **A. Ajout de schémas de validation TypeScript** - Créer des validateurs pour chaque structure échangée avec Wasm, par exemple : ```typescript import { z } from 'zod'; export const ProcessInputSchema = z.object({ id: z.string(), name: z.string(), // ... autres champs }); export type ProcessInput = z.infer<typeof ProcessInputSchema>; ``` - **Valider les données avant tout appel Wasm** : ```typescript function callWasmProcess(input: any) { const parseResult = ProcessInputSchema.safeParse(input); if (!parseResult.success) { throw new Error('Invalid process input: ' + parseResult.error.message); } // Appel Wasm ici } ``` ### **B. Encapsulation des appels Wasm** - Créer des wrappers pour chaque fonction Wasm, avec gestion d’erreur et validation de sortie : ```typescript async function safeWasmCall<T, R>(fn: (input: T) => R, input: T, outputSchema: z.ZodType<R>): Promise<R> { try { const result = fn(input); const parseResult = outputSchema.safeParse(result); if (!parseResult.success) { throw new Error('Invalid output from Wasm: ' + parseResult.error.message); } return parseResult.data; } catch (e) { // Log, notifier, etc. throw new Error('Wasm call failed: ' + (e instanceof Error ? e.message : String(e))); } } ``` ### **C. Ajout de tests unitaires et d’intégration** - Pour chaque interface critique, ajouter des tests dans `__tests__/` ou `tests/` : ```typescript import { safeWasmCall } from '../src/wasm-wrapper'; import { ProcessInputSchema, ProcessOutputSchema } from '../src/models/validation'; test('Wasm process creation - valid input', async () => { const input = { id: 'p1', name: 'Test' /* ... */ }; const result = await safeWasmCall(wasm.create_process, input, ProcessOutputSchema); expect(result).toHaveProperty('process_id'); }); test('Wasm process creation - invalid input', async () => { const input = { id: 123, name: null }; await expect(safeWasmCall(wasm.create_process, input, ProcessOutputSchema)).rejects.toThrow(); }); ``` ### **D. CI/CD** - Ajouter l’exécution des tests dans le pipeline CI/CD de chaque repo du dossier `4NK`. - Bloquer le merge en cas d’échec des tests d’interface. --- ## 3. **Documentation à ajouter** - Pour chaque interface TS/Wasm, ajouter un commentaire JSDoc/TSdoc précisant : - Les types attendus/retournés - Les erreurs possibles - Les schémas de validation utilisés --- ## 4. **Bénéfices attendus** - **Réduction drastique des risques d’injection, de corruption de données ou de crash** liés aux échanges TS/Wasm. - **Auditabilité et traçabilité** des échanges critiques. - **Conformité** avec les exigences de sécurité (OWASP, EBA, SecNumCloud, etc.). - **Robustesse accrue** du code et meilleure maintenabilité. --- ## 5. **Plan d’action** ### **Lister toutes les interfaces TS/Wasm critiques dans chaque repo du dossier 4NK.** #### 1. **ihm_client** ##### **a. Appels principaux (src/services/service.ts, src/pages/...)** - **createProcess / updateProcess / createPairingProcess** - **Entrée** : objets process, rôles, données privées/publiques - **Sortie** : objet ApiReturn (process créé/mis à jour) - **Sécurisation attendue** : - Validation stricte des objets (schéma Zod/io-ts) - Vérification des types et champs obligatoires - Gestion d’erreur (try/catch, message utilisateur) - Validation de la sortie (structure attendue) - **sdkClient.encode_json / encode_binary / decode_json** - **Entrée** : objets ou buffers à sérialiser/désérialiser - **Sortie** : string ou objet typé - **Sécurisation attendue** : - Validation du format avant encodage/décodage - Gestion des erreurs de parsing - Contrôle de la taille et du contenu - **sdkClient.create_new_process / update_process / validate_state** - **Entrée** : objets process, rôles, données - **Sortie** : objet ApiReturn - **Sécurisation attendue** : - Validation des structures avant appel - Vérification des droits (rôle, session) - Gestion d’erreur et rollback en cas d’échec - **sdkClient.sign_transaction / parse_new_tx / parse_cipher** - **Entrée** : transaction, message, cipher - **Sortie** : objet transaction/signature - **Sécurisation attendue** : - Validation du format de la transaction/message - Contrôle d’intégrité (hash, signature) - Gestion d’erreur et logs #### 2. **sdk_client** ##### **a. Appels Wasm exposés (crates/sp_client/src/lib.rs, api.rs, user.rs, process.rs, etc.)** - **create_user / create_process / update_process / add_data_to_image** - **Entrée** : objets utilisateur, process, image, etc. - **Sortie** : objets typés (User, Process, etc.) - **Sécurisation attendue** : - Validation des types à l’entrée (via tsify ou schéma JS) - Vérification des valeurs (non null, non vide, format) - Gestion d’erreur Rust (Result, panic catch) - Validation de la sortie (structure, types) - **get_main_address / get_outputs / get_processes** - **Entrée** : identifiants, filtres - **Sortie** : string, array, objets - **Sécurisation attendue** : - Validation des paramètres - Contrôle d’accès (session, droits) - Gestion d’erreur #### 3. **sdk_storage** ##### **a. Appels via FFI/wasm (si exposés)** - **store_data / retrieve_data** - **Entrée** : clé, valeur, TTL - **Sortie** : confirmation, données - **Sécurisation attendue** : - Validation de la clé (format, longueur) - Validation du contenu (taille, type) - Gestion d’erreur (clé existante, non trouvée) - Contrôle d’accès si multi-tenant #### 4. **sdk_relay** ##### **a. Appels Wasm/TS (si relay expose une API JS/TS)** - **send_message / receive_message / subscribe** - **Entrée** : message, type, destinataire - **Sortie** : confirmation, message reçu - **Sécurisation attendue** : - Validation du format du message - Contrôle du type et du destinataire - Gestion d’erreur (message non délivré, format invalide) - Logs/audit des échanges critiques #### 5. **skeleton** (si usage direct du SDK Wasm) - **Appels via MessageBus/Iframe vers le SDK** - **Entrée/Sortie** : objets process, profils, rôles, etc. - **Sécurisation attendue** : - Validation des messages échangés (schéma, type) - Gestion d’erreur et logs - Contrôle d’accès (session utilisateur) #### **Sécurisation attendue pour toutes les interfaces** - **Validation stricte** des entrées et sorties (schéma, type, valeurs) - **Gestion d’erreur** systématique (try/catch, Result, logs) - **Typage fort** (TypeScript, Rust, tsify, enums) - **Contrôle d’accès** et de droits pour les opérations sensibles - **Logs et audit** pour les opérations critiques - **Tests unitaires et d’intégration** couvrant les cas nominaux, d’erreur et de bord ### **Créer les schémas de validation pour chaque structure échangée.** #### **1. ihm_client** ##### **Processus (ProcessInput)** ```typescript import { z } from 'zod'; export const ProcessInputSchema = z.object({ id: z.string(), name: z.string(), description: z.string().optional(), icon: z.string().optional(), zoneList: z.array(z.object({ id: z.string(), name: z.string(), // ... autres champs zone })), roles: z.record(z.string(), z.any()), // à raffiner avec RoleDefinitionSchema // Champs de conformité structurés legalClauses: z.array(z.object({ title: z.string(), text: z.string(), version: z.string(), applicableFrom: z.string(), })), consent: z.object({ given: z.boolean(), date: z.string(), method: z.enum(['checkbox', 'signature', 'other']), scope: z.string(), expiration: z.object({ duration: z.string(), expiresAt: z.string(), reason: z.string(), }), }), contract: z.object({ contractId: z.string(), parties: z.array(z.string()), signedAt: z.string(), expiration: z.object({ duration: z.string(), expiresAt: z.string(), reason: z.string(), }), documentUrl: z.string(), }), legitimateInterest: z.object({ description: z.string(), assessmentDate: z.string(), balancingTestDocumentUrl: z.string().optional(), }), oppositionRight: z.object({ enabled: z.boolean(), process: z.string(), roles: z.array(z.string()), requests: z.array(z.any()), // à raffiner }), expiration: z.object({ duration: z.string(), expiresAt: z.string(), reason: z.string(), }), dataLocations: z.array(z.object({ country: z.string(), region: z.string().optional(), provider: z.string().optional(), storageType: z.enum(['cloud', 'on-premise', 'hybrid']), declaredBy: z.string(), declaredAt: z.string(), })), thirdPartyActors: z.array(z.object({ name: z.string(), type: z.enum(['processor', 'sub-processor', 'controller', 'other']), contact: z.string(), contractReference: z.string(), dataCategories: z.array(z.string()), location: z.any(), // à raffiner avec DataLocationSchema })), privacyPolicy: z.object({ url: z.string(), version: z.string(), applicableFrom: z.string(), summary: z.string(), }), legalNotice: z.object({ url: z.string(), version: z.string(), applicableFrom: z.string(), summary: z.string(), }), inactiveAccountMetadata: z.object({ lastActivityDate: z.string(), maxInactivityDuration: z.string(), status: z.enum(['active', 'inactive', 'pending_deletion']), deletionScheduledAt: z.string().optional(), }), trainingProofs: z.array(z.object({ type: z.enum(['security', 'data_protection']), completed: z.boolean(), date: z.string(), provider: z.string(), certificateUrl: z.string().optional(), })), }); ``` ##### **Rôle de conformité (ComplianceRoleData)** Pour chaque rôle, un schéma dédié : ```typescript export const BackupRoleDataSchema = z.object({ backupHistory: z.array(z.object({ date: z.string(), performedBy: z.string(), backupType: z.enum(['full', 'incremental']), location: z.string(), integrityCheck: z.boolean(), })), lastBackupDate: z.string(), incidentProcedure: z.object({ documentUrl: z.string(), version: z.string(), applicableFrom: z.string(), steps: z.array(z.string()), contact: z.string(), }), }); ``` Idem pour chaque rôle (`DigitalLegalRequestsRoleDataSchema`, `SupportN1RoleDataSchema`, etc.). #### **2. sdk_client** ##### **User (UserInput)** ```typescript export const UserInputSchema = z.object({ pre_id: z.string(), processes: z.array(z.string()), peers: z.array(z.any()), // à raffiner recover_data: z.any(), revoke_data: z.any().optional(), shares: z.array(z.any()), outputs: z.array(z.any()), }); ``` ##### **Process (ProcessInput)** Réutiliser le schéma de ihm_client ou l’adapter selon les besoins Rust/wasm. #### **3. sdk_storage** ##### **StoreRequest** ```typescript export const StoreRequestSchema = z.object({ key: z.string().length(64).regex(/^[a-fA-F0-9]+$/), value: z.string(), // hex ou base64 selon usage ttl: z.number().int().min(60).max(31_536_000).optional(), }); ``` #### **4. sdk_relay** ##### **Message (RelayMessage)** ```typescript export const RelayMessageSchema = z.object({ type: z.string(), payload: z.any(), // à raffiner selon le type sender: z.string(), timestamp: z.string(), }); ``` #### **5. skeleton** ##### **ProfileData** ```typescript export const ProfileDataSchema = z.object({ name: z.string(), surname: z.string(), email: z.string().email(), phone: z.string(), address: z.string(), postalCode: z.string(), city: z.string(), country: z.string(), idDocument: z.any().nullable(), idCertified: z.boolean(), // ... autres champs structurés si besoin }); ``` #### **Sécurisation attendue pour chaque schéma** - **safeParse** avant tout appel TS/Wasm ou lors de la réception de données. - **Gestion d’erreur** en cas d’échec de validation (log, rollback, message utilisateur). - **Tests unitaires** pour chaque schéma (cas valide, cas invalide, cas limite). ### **Encapsuler tous les appels Wasm dans des wrappers avec validation et gestion d’erreur.** #### Objectif - **Encapsuler tous les appels Wasm** (Rust <-> TypeScript) dans des fonctions wrappers. - **Valider systématiquement** les entrées et sorties via des schémas (Zod ou équivalent). - **Gérer les erreurs** de façon centralisée (try/catch, logs, messages utilisateur). - **Renforcer la robustesse, la sécurité et la conformité** des échanges TS/Wasm dans tous les projets du dossier `4NK`. #### 1. **Liste des appels Wasm à encapsuler** ##### **ihm_client / sdk_client (exemples principaux)** - `sdkClient.create_new_process` - `sdkClient.update_process` - `sdkClient.create_user` - `sdkClient.add_data_to_image` - `sdkClient.sign_transaction` - `sdkClient.parse_new_tx` - `sdkClient.parse_cipher` - `sdkClient.validate_state` - `sdkClient.encode_json` - `sdkClient.encode_binary` - `sdkClient.decode_json` - `sdkClient.get_main_address` - `sdkClient.get_outputs` - `sdkClient.get_processes` - (et tout autre appel direct à une fonction exposée par le module Wasm) #### 2. **Encapsulation type générique** ##### **Création d’un wrapper générique** Dans un fichier utilitaire commun (ex : `src/wasm-wrapper.ts`) : ```typescript import { z, ZodType } from 'zod'; export async function safeWasmCall<T, R>( fn: (input: T) => R | Promise<R>, input: T, inputSchema: ZodType<T>, outputSchema: ZodType<R> ): Promise<R> { // Validation de l'entrée const inputParse = inputSchema.safeParse(input); if (!inputParse.success) { throw new Error('Entrée invalide pour Wasm : ' + inputParse.error.message); } try { const result = await fn(input); // Validation de la sortie const outputParse = outputSchema.safeParse(result); if (!outputParse.success) { throw new Error('Sortie invalide de Wasm : ' + outputParse.error.message); } return outputParse.data; } catch (e) { // Gestion d’erreur centralisée console.error('Erreur lors de l’appel Wasm :', e); throw new Error('Erreur Wasm : ' + (e instanceof Error ? e.message : String(e))); } } ``` #### 3. **Encapsulation de chaque appel critique** ##### **Exemple pour la création de process** ```typescript import { safeWasmCall } from './wasm-wrapper'; import { ProcessInputSchema, ProcessOutputSchema } from './models/validation'; async function createProcessWasm(input: ProcessInput) { return await safeWasmCall( sdkClient.create_new_process, input, ProcessInputSchema, ProcessOutputSchema ); } ``` ##### **Exemple pour la mise à jour de process** ```typescript async function updateProcessWasm(input: ProcessInput) { return await safeWasmCall( sdkClient.update_process, input, ProcessInputSchema, ProcessOutputSchema ); } ``` ##### **Exemple pour la signature de transaction** ```typescript async function signTransactionWasm(input: TransactionInput) { return await safeWasmCall( sdkClient.sign_transaction, input, TransactionInputSchema, TransactionOutputSchema ); } ``` ##### **Exemple pour l’encodage/décodage** ```typescript async function encodeJsonWasm(input: any) { return await safeWasmCall( sdkClient.encode_json, input, z.any(), // ou un schéma plus précis z.string() ); } ``` #### 4. **Utilisation dans la logique métier** - **Remplacer tous les appels directs** à `sdkClient.*` par les wrappers sécurisés. - **Gérer les erreurs** retournées par les wrappers (affichage utilisateur, rollback, logs). - **Ajouter des tests unitaires** pour chaque wrapper (cas valide, cas invalide, cas d’erreur). #### 5. **Bénéfices** - **Validation stricte** des échanges TS/Wasm (plus de données corrompues ou inattendues). - **Gestion d’erreur centralisée** et traçable. - **Sécurité et robustesse accrues** (prévention des injections, crash, corruptions). - **Conformité** avec les exigences d’audit et de sécurité (OWASP, EBA, SecNumCloud, etc.). #### 6. **Plan d’action** 1. **Lister tous les appels Wasm critiques dans chaque repo du dossier 4NK.** 2. **Créer les schémas de validation pour chaque structure échangée.** 3. **Créer le wrapper générique `safeWasmCall`.** 4. **Encapsuler chaque appel Wasm dans un wrapper dédié.** 5. **Remplacer les appels directs dans la logique métier.** 6. **Ajouter des tests unitaires et d’intégration.** 7. **Documenter l’usage des wrappers et des schémas.** ### **Écrire des tests unitaires et d’intégration pour chaque interface.** #### Objectif - **Lister toutes les interfaces critiques TS/Wasm** à tester . - **Décrire la méthodologie de tests** (unitaires et d’intégration). - **Proposer l’intégration et l’implémentation concrète** des tests. - **Systématiser la couverture de tests pour garantir la robustesse, la sécurité et la conformité.** #### 1. **Liste des interfaces TS/Wasm à tester** ##### **ihm_client / sdk_client** - `sdkClient.create_new_process` - `sdkClient.update_process` - `sdkClient.create_user` - `sdkClient.add_data_to_image` - `sdkClient.sign_transaction` - `sdkClient.parse_new_tx` - `sdkClient.parse_cipher` - `sdkClient.validate_state` - `sdkClient.encode_json` - `sdkClient.encode_binary` - `sdkClient.decode_json` - `sdkClient.get_main_address` - `sdkClient.get_outputs` - `sdkClient.get_processes` - (et tout autre appel direct à une fonction exposée par le module Wasm) ##### **sdk_storage** - `store_data` - `retrieve_data` ##### **sdk_relay** - `send_message` - `receive_message` - `subscribe` #### 2. **Méthodologie de tests** ##### **A. Tests unitaires** - **But** : Vérifier que chaque fonction d’interface TS/Wasm fonctionne correctement en isolation. - **Cas à couvrir** : - Cas nominal (entrée valide, sortie attendue) - Cas d’erreur (entrée invalide, exception, retour d’erreur) - Cas de bord (valeurs limites, champs manquants, types inattendus) - **Outils** : Jest, Vitest, Mocha, etc. (selon le repo) - **Utilisation des schémas de validation** : Les entrées/sorties sont validées avec Zod/io-ts avant et après l’appel. ##### **B. Tests d’intégration** - **But** : Vérifier que l’interface TS/Wasm fonctionne dans un scénario applicatif réel (ex : création de process, signature, etc.). - **Cas à couvrir** : - Enchaînement d’appels (ex : create_process puis update_process) - Interaction avec la persistance (IndexedDB, storage, etc.) - Gestion des erreurs et des retours inattendus - **Outils** : Jest, Playwright, Cypress, tests end-to-end, etc. #### 3. **Intégration et implémentation des tests** ##### **A. Structure des fichiers de tests** - Créer un dossier `__tests__` ou `tests/` à la racine de chaque repo ou dans `src/`. - Un fichier de test par interface ou par module (ex : `createProcess.wasm.test.ts`, `signTransaction.wasm.test.ts`). ### **B. Exemple de test unitaire (Jest + Zod)** ```typescript import { safeWasmCall } from '../src/wasm-wrapper'; import { ProcessInputSchema, ProcessOutputSchema } from '../src/models/validation'; import sdkClient from '../src/wasm-client'; describe('Wasm create_new_process', () => { it('should create a process with valid input', async () => { const input = { id: 'p1', name: 'Test', /* ... */ }; const result = await safeWasmCall( sdkClient.create_new_process, input, ProcessInputSchema, ProcessOutputSchema ); expect(result).toHaveProperty('process_id'); }); it('should throw on invalid input', async () => { const input = { id: 123, name: null }; await expect( safeWasmCall(sdkClient.create_new_process, input, ProcessInputSchema, ProcessOutputSchema) ).rejects.toThrow(); }); }); ``` ##### **C. Exemple de test d’intégration** ```typescript import { safeWasmCall } from '../src/wasm-wrapper'; import { ProcessInputSchema, ProcessOutputSchema } from '../src/models/validation'; import sdkClient from '../src/wasm-client'; describe('Wasm process integration', () => { it('should create and update a process end-to-end', async () => { const createInput = { id: 'p2', name: 'Integration', /* ... */ }; const created = await safeWasmCall( sdkClient.create_new_process, createInput, ProcessInputSchema, ProcessOutputSchema ); expect(created).toHaveProperty('process_id'); const updateInput = { ...createInput, name: 'Integration Updated' }; const updated = await safeWasmCall( sdkClient.update_process, updateInput, ProcessInputSchema, ProcessOutputSchema ); expect(updated).toHaveProperty('process_id'); expect(updated.name).toBe('Integration Updated'); }); }); ``` #### 4. **Systématisation des tests** - **Chaque nouvelle interface TS/Wasm** doit être accompagnée d’un test unitaire et d’un test d’intégration. - **Les tests doivent être exécutés automatiquement** dans la CI/CD (GitHub Actions, GitLab CI, etc.). - **Le merge est bloqué** si la couverture de tests sur les interfaces critiques baisse ou si un test échoue. - **Les schémas de validation** sont utilisés dans tous les tests pour garantir la conformité des échanges. #### 5. **Bénéfices** - **Robustesse** : détection précoce des régressions et des erreurs d’intégration. - **Sécurité** : prévention des injections, corruptions, crashs liés aux échanges TS/Wasm. - **Conformité** : traçabilité et auditabilité des échanges critiques. - **Qualité** : confiance accrue dans la stabilité de la plateforme. #### 6. **Plan d’action** 1. **Lister toutes les interfaces TS/Wasm critiques dans chaque repo.** 2. **Créer les schémas de validation pour chaque structure échangée.** 3. **Écrire les tests unitaires et d’intégration pour chaque interface.** 4. **Automatiser l’exécution des tests dans la CI/CD.** 5. **Documenter la méthodologie et les cas de test.** ### **Automatiser l’exécution des tests dans la CI/CD.** #### Objectif - **Automatiser l’exécution des tests unitaires et d’intégration** pour toutes les interfaces TS/Wasm critiques. - **Garantir la robustesse, la sécurité et la conformité** du code à chaque push, merge ou release. - **Bloquer le merge en cas d’échec des tests** ou de baisse de couverture sur les interfaces critiques. #### 1. **Liste des tests à automatiser** - Tous les tests unitaires et d’intégration couvrant les interfaces TS/Wasm listées dans la PR précédente : - `sdkClient.create_new_process`, `update_process`, `create_user`, etc. - Fonctions de validation, d’encodage/décodage, de signature, etc. - Tests de validation des schémas (Zod/io-ts) - Tests de gestion d’erreur et de cas limites #### 2. **Méthodologie d’intégration CI/CD** ##### **A. Ajout d’un job de test dans le pipeline CI/CD** - **GitHub Actions** (`.github/workflows/ci.yml`) ou **GitLab CI** (`.gitlab-ci.yml`) ou autre selon le repo. - **Étapes principales** : 1. **Installation des dépendances** (npm/yarn/pnpm + build wasm si besoin) 2. **Compilation du code** (TypeScript, Rust/Wasm) 3. **Exécution des tests** (Jest, Vitest, Mocha, etc.) 4. **Vérification de la couverture** (optionnel mais recommandé) 5. **Blocage du pipeline** en cas d’échec ##### **B. Exemple de configuration GitHub Actions** ```yaml name: CI on: push: branches: [main, develop, feature/*] pull_request: branches: [main, develop] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 20 - name: Install dependencies run: npm ci - name: Build Wasm (si besoin) run: npm run build_wasm || true - name: Build TypeScript run: npm run build || true - name: Run tests run: npm test - name: Check coverage run: npm run coverage || true ``` ### **C. Exemple de configuration GitLab CI** ```yaml stages: - test test: image: node:20 script: - npm ci - npm run build_wasm || true - npm run build || true - npm test - npm run coverage || true only: - merge_requests - main - develop ``` #### 3. **Implémentation concrète** - **Ajouter/adapter le script de test** dans le `package.json` : ```json "scripts": { "test": "jest --runInBand", "build_wasm": "wasm-pack build --out-dir ./dist/pkg ./crates/sp_client --target bundler --dev", "build": "tsc && vite build", "coverage": "jest --coverage" } ``` - **S’assurer que tous les tests sont détectés** (dossier `__tests__` ou `tests/`). - **Inclure la compilation du Wasm** si besoin avant les tests. - **Ajouter un badge de statut CI** dans le README de chaque repo. #### 4. **Systématisation et blocage du merge** - **Le pipeline doit échouer** si un test échoue ou si la couverture baisse sur les interfaces critiques. - **Le merge est bloqué** tant que la CI n’est pas verte. - **Les tests sont exécutés sur chaque push, PR/MR, et avant chaque release.** #### 5. **Bénéfices** - **Détection immédiate des régressions** ou des failles sur les interfaces TS/Wasm. - **Conformité** avec les exigences de sécurité et d’audit (OWASP, EBA, SecNumCloud, etc.). - **Qualité et robustesse** du code garanties à chaque livraison. #### 6. **Plan d’action** 1. **Ajouter/adapter le pipeline CI/CD dans chaque repo du dossier 4NK.** 2. **S’assurer que tous les tests unitaires et d’intégration sont exécutés automatiquement.** 3. **Bloquer le merge en cas d’échec.** 4. **Documenter la procédure dans le README et la spec technique.** ### **Documenter chaque interface et chaque schéma de validation.**
nicolas.cantu changed title from PR Sécurité 4 to PR Sécurité 4 (Interfaces TS/Wasm) 2025-07-18 10:12:22 +00:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: 4nk/ihm_client#4
No description provided.