Come funziona

Dal lancio all'orbita

Passo per passo: un admin prepara un tenant MindooDB, poi due utenti si scambiano dati cifrati e collaborano — senza che il server veda mai testo in chiaro.

01

Lancio

L'admin prepara il tenant

1
Admin e Alice

Creare il tenant

Con una sola chiamata l'admin crea un nuovo tenant. L'operazione genera tutte le chiavi, apre il tenant e registra nella directory la prima utente, Alice.

const { tenant, adminUser, appUser, keyBag }
  = await factory.createTenant({
    tenantId: "acme",
    adminName: "cn=admin/o=acme",
    adminPassword: "••••••••",
    userName: "cn=alice/o=acme",
    userPassword: "••••••••",
  });
2
Admin e Alice

Pubblicare sul server

L'admin registra il tenant su un server MindooDB. Il server archivia soltanto dati cifrati e chiavi pubbliche.

await tenant.publishToServer(
  "https://sync.acme.com",
  { registerUsers: [appUser] }
);
🔒 register-tenant
Il server non riceve mai la chiave del tenant
3
Admin e Alice

Creare e sincronizzare un documento

Alice crea un documento todo e invia al server le modifiche cifrate.

const db = await tenant.openDB("todos");
const doc = await db.createDocument();
await db.changeDoc(doc, (d) => {
  const data = d.getData();
  data.title = "Buy groceries";
  data.done = false;
});

const remote = await tenant.connectToServer(
  "https://sync.acme.com", "todos"
);
await db.pushChangesTo(remote);
02

Segnale

Un nuovo utente chiede di aderire

4
Bob

Creare la richiesta di adesione

Bob crea la propria identità in locale: le sue chiavi private non lasciano mai il dispositivo. Genera una richiesta di adesione che contiene solo chiavi pubbliche.

const bob = await factory.createUserId(
  "cn=bob/o=acme", "••••••••"
);

const joinRequestURI = factory.createJoinRequest(
  bob, { format: "uri" }
);
// → mdb://join-request/eyJ2IjoxLCJ1c2Vy...
mdb://join-request/...
Solo chiavi pubbliche — condivisibile senza rischi su qualsiasi canale
03

Attracco

L'admin approva la richiesta di adesione

5
Admin e Alice

Approvare la richiesta di adesione

L'admin approva la richiesta di Bob. Così Bob viene registrato nella directory e le chiavi simmetriche vengono cifrate con una password di condivisione.

const joinResponseURI =
  await tenant.approveJoinRequest(
    joinRequestURI,
    {
      adminSigningKey: adminUser
        .userSigningKeyPair.privateKey,
      adminPassword: "••••••••",
      sharePassword: "one-time-secret",
      format: "uri",
    }
  );
// → mdb://join-response/eyJ2IjoxLCJ0ZW5h...
🔒 mdb://join-response/...
Comunica la password di condivisione su un secondo canale: per telefono o di persona
04

Orbita

Inizia la collaborazione in tempo reale

6
Bob

Adesione, pull, modifica, push

Bob aderisce al tenant, scarica i dati più recenti, segna il todo come completato e rimanda indietro la modifica.

const { tenant: bobTenant } =
  await factory.joinTenant(
    joinResponseURI,
    {
      user: bob,
      password: "••••••••",
      sharePassword: "one-time-secret",
    }
  );

const remote = await bobTenant.connectToServer(
  "https://sync.acme.com", "todos"
);
const db = await bobTenant.openDB("todos");
await db.pullChangesFrom(remote);
await db.syncStoreChanges();

const todo = await db.getDocument(todoDocId);
await db.changeDoc(todo, (d) => {
  d.getData().done = true;
});
await db.pushChangesTo(remote);
7
Admin e Alice

Recuperare le modifiche

Alice scarica le ultime modifiche e vede che il todo è completato.

await db.pullChangesFrom(remote);
await db.syncStoreChanges();

const updated = await db.getDocument(todoDocId);
console.log(updated.getData().done);
// → true ✓
Todo completato ✓

Cosa vede il server e cosa non vede

Il server vede

  • Chiavi di firma pubbliche (Ed25519)
  • Chiavi di crittografia pubbliche (RSA-OAEP)
  • Blob cifrati (testo cifrato AES-256-GCM)
  • Metadati delle voci (marche temporali, hash del contenuto)
  • Hash dei nomi utente (SHA-256 — non i nomi veri)

Il server non vede mai

  • I nomi utente (cifrati con la chiave RSA dell'admin)
  • Il contenuto dei documenti (cifrato end-to-end)
  • Le chiavi private (restano sul dispositivo)
  • Le password condivise (solo out-of-band)
  • Le chiavi di crittografia simmetriche
Per iniziare Architettura nel dettaglio