diff --git a/Cargo.lock b/Cargo.lock
index 6a5b6ce..9a568ee 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3449,6 +3449,7 @@ dependencies = [
  "lazy_static",
  "ng-net",
  "ng-repo",
+ "ng-verifier",
  "rand 0.7.3",
  "safe-transmute",
  "serde",
diff --git a/nextgraph/Cargo.toml b/nextgraph/Cargo.toml
index 79d105c..8a025ea 100644
--- a/nextgraph/Cargo.toml
+++ b/nextgraph/Cargo.toml
@@ -42,4 +42,8 @@ required-features = []
 
 [[example]]
 name = "persistent"
+required-features = []
+
+[[example]]
+name = "open"
 required-features = []
\ No newline at end of file
diff --git a/nextgraph/examples/README.md b/nextgraph/examples/README.md
index 4f94f27..fd2a88c 100644
--- a/nextgraph/examples/README.md
+++ b/nextgraph/examples/README.md
@@ -7,9 +7,11 @@ run them with:
 ```
 cargo run -p nextgraph --example in_memory
 cargo run -p nextgraph --example persistent
+cargo run -p nextgraph --example open
 ```
 
 See the code:
 
 - [in_memory](in_memory.md)
 - [persistent](persistent.md)
+- [open](open.md)
diff --git a/nextgraph/examples/in_memory.rs b/nextgraph/examples/in_memory.rs
index bb61d32..336edea 100644
--- a/nextgraph/examples/in_memory.rs
+++ b/nextgraph/examples/in_memory.rs
@@ -8,9 +8,10 @@
 // according to those terms.
 
 use nextgraph::local_broker::{
-    init_local_broker, session_start, session_stop, user_connect, user_disconnect, wallet_close,
-    wallet_create_v0, wallet_get_file, wallet_import, wallet_open_with_pazzle_words,
-    wallet_read_file, wallet_was_opened, LocalBrokerConfig, SessionConfig,
+    doc_fetch, init_local_broker, session_start, session_stop, user_connect, user_disconnect,
+    wallet_close, wallet_create_v0, wallet_get, wallet_get_file, wallet_import,
+    wallet_open_with_pazzle_words, wallet_read_file, wallet_was_opened, LocalBrokerConfig,
+    SessionConfig,
 };
 use nextgraph::net::types::BootstrapContentV0;
 use nextgraph::repo::errors::NgError;
@@ -57,6 +58,8 @@ async fn main() -> std::io::Result<()> {
     })
     .await?;
 
+    println!("Your wallet name is : {}", wallet_result.wallet_name);
+
     let pazzle = display_pazzle(&wallet_result.pazzle);
     let mut pazzle_words = vec![];
     println!("Your pazzle is: {:?}", wallet_result.pazzle);
@@ -70,16 +73,21 @@ async fn main() -> std::io::Result<()> {
         .for_each(|word| print!("{} ", word.as_str()));
     println!("");
 
-    // at this point, the wallet is kept in the internal memory of the LocalBroker, but it hasn't been saved to disk
-    // and it hasn't been opened yet, so it is not usable right away.
-    // now let's open the wallet, by providing the pazzle and PIN code
-    let opened_wallet =
-        wallet_open_with_pazzle_words(&wallet_result.wallet, &pazzle_words, [1, 2, 1, 2])?;
+    // A session has been opened for you and you can directly use it without the need to call [wallet_was_opened] nor [session_start].
+    let user_id = wallet_result.personal_identity();
 
-    let user_id = opened_wallet.personal_identity();
+    // if the user has internet access, they can now decide to connect to its Server Broker, in order to sync data
+    let status = user_connect(&user_id).await?;
 
-    // once the wallet is opened, we notify the LocalBroker that we have opened it.
-    let _client = wallet_was_opened(opened_wallet).await?;
+    // The connection cannot succeed because we miss-configured the core_bootstrap of the wallet. its Peer ID is invalid.
+    let error_reason = status[0].3.as_ref().unwrap();
+    assert!(error_reason == "NoiseHandshakeFailed" || error_reason == "ConnectionError");
+
+    // a session ID has been assigned to you in `wallet_result.session_id` you can use it to fetch a document
+    //let _ = doc_fetch(wallet_result.session_id, "ng:example".to_string(), None).await?;
+
+    // Then we should disconnect
+    user_disconnect(&user_id).await?;
 
     // if you need the Wallet File again (if you didn't select `result_with_wallet_file` by example), you can retrieve it with:
     let wallet_file = wallet_get_file(&wallet_result.wallet_name).await?;
@@ -87,17 +95,39 @@ async fn main() -> std::io::Result<()> {
     // if you did ask for `result_with_wallet_file`, as we did above, then the 2 vectors should be identical
     assert_eq!(wallet_file, wallet_result.wallet_file);
 
+    // stop the session
+    session_stop(&user_id).await?;
+
+    // closes the wallet
+    wallet_close(&wallet_result.wallet_name).await?;
+
+    // if you have saved the wallet locally (which we haven't done in the example above, see `local_save: false`), next time you want to connect,
+    // you can retrieve the wallet, display the security phrase and image to the user, ask for the pazzle or mnemonic, and then open the wallet
+    // if you haven't saved the wallet, the next line will not work once you restart the LocalBroker.
+    let wallet = wallet_get(&wallet_result.wallet_name).await?;
+
+    // at this point, the wallet is kept in the internal memory of the LocalBroker
+    // and it hasn't been opened yet, so it is not usable right away.
+    // now let's open the wallet, by providing the pazzle and PIN code
+    let opened_wallet =
+        wallet_open_with_pazzle_words(&wallet_result.wallet, &pazzle_words, [1, 2, 1, 2])?;
+
+    // once the wallet is opened, we notify the LocalBroker that we have opened it.
+    let _client = wallet_was_opened(opened_wallet).await?;
+
+    // if instead of saving the wallet locally, you want to provide the Wallet File for every login,
+    // then you have to import the wallet. here is an example:
     {
-        // this part should happen on another device. just given here as an example
+        // this part should happen on another device or on the same machine if you haven't saved the wallet locally
 
-        // on another device, you could use the Wallet File and import it there so it could be used for login.
+        // you could use the Wallet File and import it there so it could be used for login.
         // first you would read and decode the Wallet File
         // this fails here because we already added this wallet in the LocalBroker (when we created it).
-        // But on another device, it would work.
+        // But on another device or after a restart of LocalBroker, it would work.
         let wallet = wallet_read_file(wallet_file).await;
         assert_eq!(wallet.unwrap_err(), NgError::WalletAlreadyAdded);
 
-        // on another device, we would then open the wallet
+        // we would then open the wallet
         // (here we take the Wallet as we received it from wallet_create_v0, but in real case you would use `wallet`)
         let opened_wallet2 =
             wallet_open_with_pazzle_words(&wallet_result.wallet, &pazzle_words, [1, 2, 1, 2])?;
@@ -109,7 +139,7 @@ async fn main() -> std::io::Result<()> {
         assert_eq!(client_fail.unwrap_err(), NgError::WalletAlreadyAdded);
     }
 
-    // anyway, now that the wallet is opened, let's start a session.
+    // now that the wallet is opened or imported, let's start a session.
     // we pass the user_id and the wallet_name
     let _session = session_start(SessionConfig::new_in_memory(
         &user_id,
diff --git a/nextgraph/examples/open.md b/nextgraph/examples/open.md
new file mode 100644
index 0000000..6b9f826
--- /dev/null
+++ b/nextgraph/examples/open.md
@@ -0,0 +1,17 @@
+# open LocalBroker
+
+Example of LocalBroker configured with persistence to disk, and opening of a previsouly saved wallet
+
+You need to replace `wallet_name` on line 40 with the name that was given to you when you ran the example [persistent], in `Your wallet name is : `
+
+You need to replace the argument `pazzle` in the function call `wallet_open_with_pazzle` with the array that you received in `Your pazzle is:`
+
+then, run with:
+
+```
+cargo run -p nextgraph -r --example open
+```
+
+we assume that you run this command from the root of the git repo (nextgraph-rs).
+
+the `-r` for release version is important, without it, the creation and opening of the wallet will take ages.
diff --git a/nextgraph/examples/open.rs b/nextgraph/examples/open.rs
new file mode 100644
index 0000000..a733d03
--- /dev/null
+++ b/nextgraph/examples/open.rs
@@ -0,0 +1,81 @@
+// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
+// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+
+use nextgraph::local_broker::{
+    doc_fetch, init_local_broker, session_start, session_stop, user_connect, user_disconnect,
+    wallet_close, wallet_create_v0, wallet_get, wallet_get_file, wallet_import,
+    wallet_open_with_pazzle, wallet_open_with_pazzle_words, wallet_read_file, wallet_was_opened,
+    LocalBrokerConfig, SessionConfig,
+};
+use nextgraph::net::types::BootstrapContentV0;
+use nextgraph::repo::errors::NgError;
+use nextgraph::repo::types::PubKey;
+use nextgraph::wallet::types::CreateWalletV0;
+use nextgraph::wallet::{display_mnemonic, emojis::display_pazzle};
+
+use std::env::current_dir;
+use std::fs::create_dir_all;
+use std::fs::read;
+
+#[async_std::main]
+async fn main() -> std::io::Result<()> {
+    // get the current working directory
+    let mut current_path = current_dir()?;
+    current_path.push(".ng");
+    current_path.push("example");
+    create_dir_all(current_path.clone())?;
+
+    // initialize the local_broker with config to save to disk in a folder called `.ng/example` in the current directory
+    init_local_broker(Box::new(move || {
+        LocalBrokerConfig::BasePath(current_path.clone())
+    }))
+    .await;
+
+    let wallet_name = "EJdLRVx93o3iUXoB0wSTqxh1-zYac-84vHb3oBbZ_HY".to_string();
+
+    // as we have previously saved the wallet,
+    // we can retrieve it, display the security phrase and image to the user, ask for the pazzle or mnemonic, and then open the wallet
+    let wallet = wallet_get(&wallet_name).await?;
+
+    // at this point, the wallet is kept in the internal memory of the LocalBroker
+    // and it hasn't been opened yet, so it is not usable right away.
+    // now let's open the wallet, by providing the pazzle and PIN code
+    let opened_wallet = wallet_open_with_pazzle(
+        &wallet,
+        vec![117, 134, 59, 92, 98, 35, 70, 22, 9],
+        [1, 2, 1, 2],
+    )?;
+
+    let user_id = opened_wallet.personal_identity();
+
+    // once the wallet is opened, we notify the LocalBroker that we have opened it.
+    let _client = wallet_was_opened(opened_wallet).await?;
+
+    // now that the wallet is opened, let's start a session.
+    // we pass the user_id and the wallet_name
+    let _session = session_start(SessionConfig::new_rocksdb(&user_id, &wallet_name)).await?;
+
+    // if the user has internet access, they can now decide to connect to its Server Broker, in order to sync data
+    let status = user_connect(&user_id).await?;
+
+    // The connection cannot succeed because we miss-configured the core_bootstrap of the wallet. its Peer ID is invalid.
+    let error_reason = status[0].3.as_ref().unwrap();
+    assert!(error_reason == "NoiseHandshakeFailed" || error_reason == "ConnectionError");
+
+    // Then we should disconnect
+    user_disconnect(&user_id).await?;
+
+    // stop the session
+    session_stop(&user_id).await?;
+
+    // closes the wallet
+    wallet_close(&wallet_name).await?;
+
+    Ok(())
+}
diff --git a/nextgraph/examples/persistent.rs b/nextgraph/examples/persistent.rs
index 1115bc6..753427f 100644
--- a/nextgraph/examples/persistent.rs
+++ b/nextgraph/examples/persistent.rs
@@ -7,9 +7,21 @@
 // notice may not be copied, modified, or distributed except
 // according to those terms.
 
-use nextgraph::local_broker::{init_local_broker, LocalBrokerConfig};
+use nextgraph::local_broker::{
+    doc_fetch, init_local_broker, session_start, session_stop, user_connect, user_disconnect,
+    wallet_close, wallet_create_v0, wallet_get, wallet_get_file, wallet_import,
+    wallet_open_with_pazzle_words, wallet_read_file, wallet_was_opened, LocalBrokerConfig,
+    SessionConfig,
+};
+use nextgraph::net::types::BootstrapContentV0;
+use nextgraph::repo::errors::NgError;
+use nextgraph::repo::types::PubKey;
+use nextgraph::wallet::types::CreateWalletV0;
+use nextgraph::wallet::{display_mnemonic, emojis::display_pazzle};
+
 use std::env::current_dir;
 use std::fs::create_dir_all;
+use std::fs::read;
 
 #[async_std::main]
 async fn main() -> std::io::Result<()> {
@@ -25,5 +37,115 @@ async fn main() -> std::io::Result<()> {
     }))
     .await;
 
+    // load some image that will be used as security_img
+    // we assume here for the sake of this example,
+    // that the current directory contains this demo image file
+    let security_img = read("nextgraph/examples/wallet-security-image-demo.png")?;
+
+    // the peer_id should come from somewhere else.
+    // this is just given for the sake of an example
+    #[allow(deprecated)]
+    let peer_id_of_server_broker = PubKey::nil();
+
+    // Create your wallet
+    // this will take some time !
+    println!("Creating the wallet. this will take some time...");
+
+    let wallet_result = wallet_create_v0(CreateWalletV0 {
+        security_img,
+        security_txt: "know yourself".to_string(),
+        pin: [1, 2, 1, 2],
+        pazzle_length: 9,
+        send_bootstrap: false,
+        send_wallet: false,
+        result_with_wallet_file: true,
+        local_save: true,
+        // we default to localhost:14400. this is just for the sake of an example
+        core_bootstrap: BootstrapContentV0::new_localhost(peer_id_of_server_broker),
+        core_registration: None,
+        additional_bootstrap: None,
+    })
+    .await?;
+
+    println!("Your wallet name is : {}", wallet_result.wallet_name);
+
+    let pazzle = display_pazzle(&wallet_result.pazzle);
+    let mut pazzle_words = vec![];
+    println!("Your pazzle is: {:?}", wallet_result.pazzle);
+    for emoji in pazzle {
+        println!("    {}:\t{}", emoji.0, emoji.1);
+        pazzle_words.push(emoji.1.to_string());
+    }
+    println!("Your mnemonic is:");
+    display_mnemonic(&wallet_result.mnemonic)
+        .iter()
+        .for_each(|word| print!("{} ", word.as_str()));
+    println!("");
+
+    // A session has been opened for you and you can directly use it without the need to call [wallet_was_opened] nor [session_start].
+    let user_id = wallet_result.personal_identity();
+
+    // if the user has internet access, they can now decide to connect to its Server Broker, in order to sync data
+    let status = user_connect(&user_id).await?;
+
+    // The connection cannot succeed because we miss-configured the core_bootstrap of the wallet. its Peer ID is invalid.
+    let error_reason = status[0].3.as_ref().unwrap();
+    assert!(error_reason == "NoiseHandshakeFailed" || error_reason == "ConnectionError");
+
+    // a session ID has been assigned to you in `wallet_result.session_id` you can use it to fetch a document
+    //let _ = doc_fetch(wallet_result.session_id, "ng:example".to_string(), None).await?;
+
+    // Then we should disconnect
+    user_disconnect(&user_id).await?;
+
+    // if you need the Wallet File again (if you didn't select `result_with_wallet_file` by example), you can retrieve it with:
+    let wallet_file = wallet_get_file(&wallet_result.wallet_name).await?;
+
+    // if you did ask for `result_with_wallet_file`, as we did above, then the 2 vectors should be identical
+    assert_eq!(wallet_file, wallet_result.wallet_file);
+
+    // stop the session
+    session_stop(&user_id).await?;
+
+    // closes the wallet
+    wallet_close(&wallet_result.wallet_name).await?;
+
+    // as we have saved the wallet, the next time we want to connect,
+    // we can retrieve the wallet, display the security phrase and image to the user, ask for the pazzle or mnemonic, and then open the wallet
+    let wallet = wallet_get(&wallet_result.wallet_name).await?;
+
+    // at this point, the wallet is kept in the internal memory of the LocalBroker
+    // and it hasn't been opened yet, so it is not usable right away.
+    // now let's open the wallet, by providing the pazzle and PIN code
+    let opened_wallet =
+        wallet_open_with_pazzle_words(&wallet_result.wallet, &pazzle_words, [1, 2, 1, 2])?;
+
+    // once the wallet is opened, we notify the LocalBroker that we have opened it.
+    let _client = wallet_was_opened(opened_wallet).await?;
+
+    // now that the wallet is opened, let's start a session.
+    // we pass the user_id and the wallet_name
+    let _session = session_start(SessionConfig::new_rocksdb(
+        &user_id,
+        &wallet_result.wallet_name,
+    ))
+    .await?;
+
+    // if the user has internet access, they can now decide to connect to its Server Broker, in order to sync data
+    let status = user_connect(&user_id).await?;
+
+    // The connection cannot succeed because we miss-configured the core_bootstrap of the wallet. its Peer ID is invalid.
+    let error_reason = status[0].3.as_ref().unwrap();
+    assert!(error_reason == "NoiseHandshakeFailed" || error_reason == "ConnectionError");
+
+    // Then we should disconnect
+    user_disconnect(&user_id).await?;
+
+    // stop the session
+    session_stop(&user_id).await?;
+
+    // closes the wallet
+    wallet_close(&wallet_result.wallet_name).await?;
+
     Ok(())
 }
diff --git a/nextgraph/src/local_broker.rs b/nextgraph/src/local_broker.rs
index beccc28..39fcd6e 100644
--- a/nextgraph/src/local_broker.rs
+++ b/nextgraph/src/local_broker.rs
@@ -34,7 +34,7 @@ use ng_repo::errors::NgError;
 use ng_repo::log::*;
 use ng_repo::types::*;
 use ng_repo::utils::derive_key;
-use ng_wallet::{create_wallet_v0, types::*};
+use ng_wallet::{create_wallet_first_step_v0, create_wallet_second_step_v0, types::*};
 
 #[cfg(not(target_arch = "wasm32"))]
 use ng_client_ws::remote_ws::ConnectionWebSocket;
@@ -80,14 +80,16 @@ impl JsStorageConfig {
                     }
                     Err(_) => 0,
                 };
-                let new_val = val + qty as u64;
-                let spls = SessionPeerLastSeq::V0(new_val);
-                let ser = serde_bare::to_vec(&spls)?;
-                //saving the new val
-                let encoded = base64_url::encode(&ser);
-                let r = (session_write2)(format!("ng_peer_last_seq@{}", peer_id), encoded);
-                if r.is_ok() {
-                    return Err(NgError::SerializationError);
+                if qty > 0 {
+                    let new_val = val + qty as u64;
+                    let spls = SessionPeerLastSeq::V0(new_val);
+                    let ser = serde_bare::to_vec(&spls)?;
+                    //saving the new val
+                    let encoded = base64_url::encode(&ser);
+                    let r = (session_write2)(format!("ng_peer_last_seq@{}", peer_id), encoded);
+                    if r.is_ok() {
+                        return Err(NgError::SerializationError);
+                    }
                 }
                 Ok(val)
             }),
@@ -266,6 +268,31 @@ impl SessionConfig {
         })
     }
 
+    pub fn new_for_local_broker_config(
+        user_id: &UserId,
+        wallet_name: &String,
+        local_broker_config: &LocalBrokerConfig,
+        in_memory: bool,
+    ) -> Result<SessionConfig, NgError> {
+        Ok(SessionConfig::V0(SessionConfigV0 {
+            user_id: user_id.clone(),
+            wallet_name: wallet_name.clone(),
+            verifier_type: match local_broker_config {
+                LocalBrokerConfig::InMemory => {
+                    if !in_memory {
+                        return Err(NgError::CannotSaveWhenInMemoryConfig);
+                    }
+                    VerifierType::Memory
+                }
+                LocalBrokerConfig::JsStorage(js_config) => VerifierType::Memory,
+                LocalBrokerConfig::BasePath(_) => match in_memory {
+                    true => VerifierType::Memory,
+                    false => VerifierType::RocksDb,
+                },
+            },
+        }))
+    }
+
     fn valid_verifier_config_for_local_broker_config(
         &mut self,
         local_broker_config: &LocalBrokerConfig,
@@ -283,7 +310,7 @@ impl SessionConfig {
                 },
                 LocalBrokerConfig::BasePath(_) => match v0.verifier_type {
                     VerifierType::RocksDb | VerifierType::Remote(_) => true,
-                    //VerifierType::Memory => true,
+                    VerifierType::Memory => true,
                     _ => false,
                 },
             },
@@ -366,16 +393,16 @@ impl EActor for LocalBroker {
 }
 
 impl LocalBroker {
-    fn storage_path_for_user(&self, user_id: &UserId) -> Option<PathBuf> {
-        match &self.config {
-            LocalBrokerConfig::InMemory | LocalBrokerConfig::JsStorage(_) => None,
-            LocalBrokerConfig::BasePath(base) => {
-                let mut path = base.clone();
-                path.push(user_id.to_hash_string());
-                Some(path)
-            }
-        }
-    }
+    // fn storage_path_for_user(&self, user_id: &UserId) -> Option<PathBuf> {
+    //     match &self.config {
+    //         LocalBrokerConfig::InMemory | LocalBrokerConfig::JsStorage(_) => None,
+    //         LocalBrokerConfig::BasePath(base) => {
+    //             let mut path = base.clone();
+    //             path.push(format!("user{}", user_id.to_hash_string()));
+    //             Some(path)
+    //         }
+    //     }
+    // }
 
     fn get_mut_session_for_user(&mut self, user: &UserId) -> Option<&mut Session> {
         match self.opened_sessions.get(user) {
@@ -390,9 +417,10 @@ impl LocalBroker {
     ) -> VerifierConfigType {
         match (config.verifier_type(), &self.config) {
             (VerifierType::Memory, LocalBrokerConfig::InMemory) => VerifierConfigType::Memory,
+            (VerifierType::Memory, LocalBrokerConfig::BasePath(_)) => VerifierConfigType::Memory,
             (VerifierType::RocksDb, LocalBrokerConfig::BasePath(base)) => {
                 let mut path = base.clone();
-                path.push(config.user_id().to_hash_string());
+                path.push(format!("user{}", config.user_id().to_hash_string()));
                 VerifierConfigType::RocksDb(path)
             }
             (VerifierType::Remote(to), _) => VerifierConfigType::Remote(*to),
@@ -439,6 +467,295 @@ impl LocalBroker {
         }
         Ok(())
     }
+
+    async fn wallet_was_opened(
+        &mut self,
+        mut wallet: SensitiveWallet,
+    ) -> Result<ClientV0, NgError> {
+        let broker = self;
+
+        match broker.opened_wallets.get(&wallet.id()) {
+            Some(opened_wallet) => {
+                return Ok(opened_wallet.wallet.client().to_owned().unwrap());
+            }
+            None => {} //Err(NgError::WalletAlreadyOpened);
+        }
+        let wallet_id = wallet.id();
+        let lws = match broker.wallets.get(&wallet_id) {
+            Some(lws) => {
+                if wallet.client().is_none() {
+                    // this case happens when the wallet is opened and not when it is imported (as the client is already there)
+                    wallet.set_client(lws.to_client_v0(wallet.privkey())?);
+                }
+                lws
+            }
+            None => {
+                return Err(NgError::WalletNotFound);
+            }
+        };
+        let block_storage = if lws.in_memory {
+            Arc::new(std::sync::RwLock::new(HashMapBlockStorage::new()))
+                as Arc<std::sync::RwLock<dyn BlockStorage + Send + Sync + 'static>>
+        } else {
+            #[cfg(not(target_family = "wasm"))]
+            {
+                let mut key_material = wallet
+                    .client()
+                    .as_ref()
+                    .unwrap()
+                    .sensitive_client_storage
+                    .priv_key
+                    .slice();
+                let path = broker.config.compute_path(&format!(
+                    "block{}",
+                    wallet.client().as_ref().unwrap().id.to_hash_string()
+                ))?;
+                let mut key: [u8; 32] =
+                    derive_key("NextGraph Client BlockStorage BLAKE3 key", key_material);
+                Arc::new(std::sync::RwLock::new(RocksDbBlockStorage::open(
+                    &path, key,
+                )?))
+                    as Arc<std::sync::RwLock<dyn BlockStorage + Send + Sync + 'static>>
+            }
+            #[cfg(target_family = "wasm")]
+            {
+                panic!("no RocksDB in WASM");
+            }
+        };
+        let client = wallet.client().as_ref().unwrap().clone();
+        let opened_wallet = OpenedWallet {
+            wallet,
+            block_storage,
+        };
+
+        broker.opened_wallets.insert(wallet_id, opened_wallet);
+        Ok(client)
+    }
+
+    async fn session_start(
+        &mut self,
+        mut config: SessionConfig,
+        user_priv_key: Option<PrivKey>,
+    ) -> Result<SessionInfo, NgError> {
+        let broker = self;
+
+        config.valid_verifier_config_for_local_broker_config(&broker.config)?;
+
+        let wallet_name: String = config.wallet_name();
+        let wallet_id: PubKey = (*wallet_name).try_into()?;
+        let user_id = config.user_id();
+
+        match broker.opened_sessions.get(&user_id) {
+            Some(idx) => {
+                let ses = &(broker.opened_sessions_list)[*idx as usize];
+                match ses.as_ref() {
+                    Some(sess) => {
+                        if sess.config.verifier_type() != config.verifier_type() {
+                            return Err(NgError::SessionAlreadyStarted);
+                        } else {
+                            return Ok(SessionInfo {
+                                session_id: *idx,
+                                user: user_id,
+                            });
+                        }
+                    }
+                    None => {}
+                }
+            }
+            None => {}
+        };
+
+        // log_info!("wallet_name {} {:?}", wallet_name, broker.opened_wallets);
+        match broker.opened_wallets.get(&wallet_name) {
+            None => return Err(NgError::WalletNotFound),
+            Some(opened_wallet) => {
+                let block_storage = Arc::clone(&opened_wallet.block_storage);
+                let credentials = match opened_wallet.wallet.individual_site(&user_id) {
+                    Some(creds) => creds,
+                    None => match user_priv_key {
+                        Some(user_pk) => (user_pk, None, None),
+                        None => return Err(NgError::NotFound),
+                    },
+                };
+
+                let client_storage_master_key = serde_bare::to_vec(
+                    &opened_wallet
+                        .wallet
+                        .client()
+                        .as_ref()
+                        .unwrap()
+                        .sensitive_client_storage
+                        .storage_master_key,
+                )
+                .unwrap();
+
+                let session = match broker.sessions.get(&user_id) {
+                    Some(session) => session,
+                    None => {
+                        // creating the session now
+                        let closed_wallet = broker.wallets.get(&wallet_name).unwrap();
+                        if closed_wallet.in_memory {
+                            let session = SessionPeerStorageV0::new(user_id);
+                            broker.sessions.insert(user_id, session);
+                            broker.sessions.get(&user_id).unwrap()
+                        } else {
+                            // first check if there is a saved SessionWalletStorage
+                            let mut sws = match &broker.config {
+                                LocalBrokerConfig::InMemory => panic!("cannot open saved session"),
+                                LocalBrokerConfig::JsStorage(js_config) => {
+                                    // read session wallet storage from JsStorage
+                                    let res = (js_config.session_read)(format!(
+                                        "ng_wallet@{}",
+                                        wallet_name
+                                    ));
+                                    match res {
+                                        Ok(string) => {
+                                            let decoded = base64_url::decode(&string)
+                                                .map_err(|_| NgError::SerializationError)?;
+                                            Some(SessionWalletStorageV0::dec_session(
+                                                opened_wallet.wallet.privkey(),
+                                                &decoded,
+                                            )?)
+                                        }
+                                        Err(_) => None,
+                                    }
+                                }
+                                LocalBrokerConfig::BasePath(base_path) => {
+                                    // read session wallet storage from disk
+                                    let mut path = base_path.clone();
+                                    path.push("sessions");
+                                    path.push(format!("session{}", wallet_name.clone()));
+                                    let res = read(path);
+                                    if res.is_ok() {
+                                        Some(SessionWalletStorageV0::dec_session(
+                                            opened_wallet.wallet.privkey(),
+                                            &res.unwrap(),
+                                        )?)
+                                    } else {
+                                        None
+                                    }
+                                }
+                            };
+                            let (session, new_sws) = match &mut sws {
+                                None => {
+                                    let (s, sws_ser) = SessionWalletStorageV0::create_new_session(
+                                        &wallet_id, user_id,
+                                    )?;
+                                    broker.sessions.insert(user_id, s);
+                                    (broker.sessions.get(&user_id).unwrap(), sws_ser)
+                                }
+                                Some(sws) => {
+                                    match sws.users.get(&user_id.to_string()) {
+                                        Some(sps) => {
+                                            broker.sessions.insert(user_id, sps.clone());
+                                            (broker.sessions.get(&user_id).unwrap(), vec![])
+                                        }
+                                        None => {
+                                            // the user was not found in the SWS. we need to create a SPS, add it, encrypt and serialize the new SWS,
+                                            // add the SPS to broker.sessions, and return the newly created SPS and the new SWS encrypted serialization
+                                            let sps = SessionPeerStorageV0::new(user_id);
+                                            sws.users.insert(user_id.to_string(), sps.clone());
+                                            let encrypted = sws.enc_session(&wallet_id)?;
+                                            broker.sessions.insert(user_id, sps);
+                                            (broker.sessions.get(&user_id).unwrap(), encrypted)
+                                        }
+                                    }
+                                }
+                            };
+                            // save the new sws
+                            if new_sws.len() > 0 {
+                                match &broker.config {
+                                    LocalBrokerConfig::InMemory => {
+                                        panic!("cannot save session when InMemory mode")
+                                    }
+                                    LocalBrokerConfig::JsStorage(js_config) => {
+                                        // save session wallet storage to JsStorage
+                                        let encoded = base64_url::encode(&new_sws);
+                                        (js_config.session_write)(
+                                            format!("ng_wallet@{}", wallet_name),
+                                            encoded,
+                                        )?;
+                                    }
+                                    LocalBrokerConfig::BasePath(base_path) => {
+                                        // save session wallet storage to disk
+                                        let mut path = base_path.clone();
+                                        path.push("sessions");
+                                        std::fs::create_dir_all(path.clone()).unwrap();
+                                        path.push(format!("session{}", wallet_name));
+                                        //log_debug!("{}", path.clone().display());
+                                        write(path.clone(), &new_sws)
+                                            .map_err(|_| NgError::IoError)?;
+                                    }
+                                }
+                            }
+                            session
+                        }
+                    }
+                };
+                let session = session.clone();
+
+                // derive user_master_key from client's storage_master_key
+                let user_id_ser = serde_bare::to_vec(&user_id).unwrap();
+                let mut key_material = [user_id_ser, client_storage_master_key].concat(); //
+                let mut key: [u8; 32] = derive_key(
+                    "NextGraph user_master_key BLAKE3 key",
+                    key_material.as_slice(),
+                );
+                key_material.zeroize();
+                let verifier = Verifier::new(
+                    VerifierConfig {
+                        config_type: broker.verifier_config_type_from_session_config(&config),
+                        user_master_key: key,
+                        peer_priv_key: session.peer_key.clone(),
+                        user_priv_key: credentials.0,
+                        private_store_read_cap: credentials.1,
+                        private_store_id: credentials.2,
+                    },
+                    block_storage,
+                )?;
+                key.zeroize();
+                broker.opened_sessions_list.push(Some(Session {
+                    config,
+                    peer_key: session.peer_key.clone(),
+                    last_wallet_nonce: session.last_wallet_nonce,
+                    verifier,
+                }));
+                let idx = broker.opened_sessions_list.len() - 1;
+                broker.opened_sessions.insert(user_id, idx as u8);
+                Ok(SessionInfo {
+                    session_id: idx as u8,
+                    user: user_id,
+                })
+            }
+        }
+    }
+
+    pub(crate) fn wallet_save(broker: &mut Self) -> Result<(), NgError> {
+        match &broker.config {
+            LocalBrokerConfig::JsStorage(js_config) => {
+                // JS save
+                let lws_ser = LocalWalletStorage::v0_to_vec(&broker.wallets);
+                let encoded = base64_url::encode(&lws_ser);
+                (js_config.local_write)("ng_wallets".to_string(), encoded)?;
+            }
+            LocalBrokerConfig::BasePath(base_path) => {
+                // save on disk
+                // TODO: use https://lib.rs/crates/keyring instead of AppLocalData on Tauri apps
+                let mut path = base_path.clone();
+                std::fs::create_dir_all(path.clone()).unwrap();
+                path.push("wallets");
+
+                let lws_ser = LocalWalletStorage::v0_to_vec(&broker.wallets);
+                let r = write(path.clone(), &lws_ser);
+                if r.is_err() {
+                    log_debug!("write {:?} {}", path, r.unwrap_err());
+                    return Err(NgError::IoError);
+                }
+            }
+            _ => panic!("wrong LocalBrokerConfig"),
+        }
+        Ok(())
+    }
 }
 
 static LOCAL_BROKER: OnceCell<Result<Arc<RwLock<LocalBroker>>, NgError>> = OnceCell::new();
@@ -541,20 +858,52 @@ pub async fn wallets_get_all() -> Result<HashMap<String, LocalWalletStorageV0>,
 ///
 /// Wallets are transferable to to other devices (see [wallet_get_file] and [wallet_import])
 pub async fn wallet_create_v0(params: CreateWalletV0) -> Result<CreateWalletResultV0, NgError> {
-    {
-        // entering sub-block to release the lock asap
-        let broker = match LOCAL_BROKER.get() {
-            None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
-            Some(Ok(broker)) => broker.read().await,
-        };
-        if params.local_save && broker.config.is_in_memory() {
-            return Err(NgError::CannotSaveWhenInMemoryConfig);
-        }
+    // TODO: entering sub-block to release the lock asap
+    let mut broker = match LOCAL_BROKER.get() {
+        None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
+        Some(Ok(broker)) => broker.write().await,
+    };
+    if params.local_save && broker.config.is_in_memory() {
+        return Err(NgError::CannotSaveWhenInMemoryConfig);
     }
-    let res = create_wallet_v0(params)?;
-    let lws: LocalWalletStorageV0 = (&res).into();
-    wallet_add(lws).await?;
+    let intermediate = create_wallet_first_step_v0(params)?;
+    let lws: LocalWalletStorageV0 = (&intermediate).into();
+
+    let wallet_name = intermediate.wallet_name.clone();
+    broker.wallets.insert(wallet_name, lws);
+
+    let sensitive_wallet: SensitiveWallet = (&intermediate).into();
+
+    let _client = broker.wallet_was_opened(sensitive_wallet).await?;
 
+    let session_config = SessionConfig::new_for_local_broker_config(
+        &intermediate.user_privkey.to_pub(),
+        &intermediate.wallet_name,
+        &broker.config,
+        intermediate.in_memory,
+    )?;
+
+    let session_info = broker
+        .session_start(session_config, Some(intermediate.user_privkey.clone()))
+        .await?;
+
+    let session = broker.opened_sessions_list[session_info.session_id as usize]
+        .as_mut()
+        .unwrap();
+
+    let (mut res, site, brokers) =
+        create_wallet_second_step_v0(intermediate, &mut session.verifier)?;
+
+    broker.wallets.get_mut(&res.wallet_name).unwrap().wallet = res.wallet.clone();
+    LocalBroker::wallet_save(&mut broker)?;
+    //TODO: change read_cap in verifier
+    broker
+        .opened_wallets
+        .get_mut(&res.wallet_name)
+        .unwrap()
+        .wallet
+        .complete_with_site_and_brokers(site, brokers);
+    res.session_id = session_info.session_id;
     Ok(res)
 }
 
@@ -602,29 +951,7 @@ pub async fn wallet_add(lws: LocalWalletStorageV0) -> Result<(), NgError> {
         //     (broker.config.js_config().unwrap().wallets_in_mem_changed)();
         // }
     } else {
-        match &broker.config {
-            LocalBrokerConfig::JsStorage(js_config) => {
-                // JS save
-                let lws_ser = LocalWalletStorage::v0_to_vec(&broker.wallets);
-                let encoded = base64_url::encode(&lws_ser);
-                (js_config.local_write)("ng_wallets".to_string(), encoded)?;
-            }
-            LocalBrokerConfig::BasePath(base_path) => {
-                // save on disk
-                // TODO: use https://lib.rs/crates/keyring instead of AppLocalData on Tauri apps
-                let mut path = base_path.clone();
-                std::fs::create_dir_all(path.clone()).unwrap();
-                path.push("wallets");
-
-                let lws_ser = LocalWalletStorage::v0_to_vec(&broker.wallets);
-                let r = write(path.clone(), &lws_ser);
-                if r.is_err() {
-                    log_debug!("write {:?} {}", path, r.unwrap_err());
-                    return Err(NgError::IoError);
-                }
-            }
-            _ => panic!("wrong LocalBrokerConfig"),
-        }
+        LocalBroker::wallet_save(&mut broker)?;
     }
     Ok(())
 }
@@ -653,6 +980,19 @@ pub async fn wallet_read_file(file: Vec<u8>) -> Result<Wallet, NgError> {
     }
 }
 
+/// Retrieves the the Wallet by its name, to be used for opening it
+pub async fn wallet_get(wallet_name: &String) -> Result<Wallet, NgError> {
+    let broker = match LOCAL_BROKER.get() {
+        None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
+        Some(Ok(broker)) => broker.read().await,
+    };
+    // check that the wallet exists
+    match broker.wallets.get(wallet_name) {
+        None => Err(NgError::WalletNotFound),
+        Some(lws) => Ok(lws.wallet.clone()),
+    }
+}
+
 /// Retrieves the binary content of a Wallet File for the Wallet identified by its name
 pub async fn wallet_get_file(wallet_name: &String) -> Result<Vec<u8>, NgError> {
     let broker = match LOCAL_BROKER.get() {
@@ -734,63 +1074,13 @@ pub async fn wallet_was_opened(mut wallet: SensitiveWallet) -> Result<ClientV0,
         Some(Ok(broker)) => broker.write().await,
     };
 
-    if broker.opened_wallets.get(&wallet.id()).is_some() {
-        return Err(NgError::WalletAlreadyOpened);
-    }
-    let wallet_id = wallet.id();
-
-    let lws = match broker.wallets.get(&wallet_id) {
-        Some(lws) => {
-            if wallet.client().is_none() {
-                // this case happens when the wallet is opened and not when it is imported (as the client is already there)
-                wallet.set_client(lws.to_client_v0(wallet.privkey())?);
-            }
-            lws
-        }
-        None => {
-            return Err(NgError::WalletNotFound);
-        }
-    };
-    let block_storage = if lws.in_memory {
-        Arc::new(std::sync::RwLock::new(HashMapBlockStorage::new()))
-            as Arc<std::sync::RwLock<dyn BlockStorage + Send + Sync + 'static>>
-    } else {
-        #[cfg(not(target_family = "wasm"))]
-        {
-            let mut key_material = wallet
-                .client()
-                .as_ref()
-                .unwrap()
-                .sensitive_client_storage
-                .priv_key
-                .slice();
-            let path = broker
-                .config
-                .compute_path(&wallet.client().as_ref().unwrap().id.to_hash_string())?;
-            let mut key: [u8; 32] =
-                derive_key("NextGraph Client BlockStorage BLAKE3 key", key_material);
-            Arc::new(std::sync::RwLock::new(RocksDbBlockStorage::open(
-                &path, key,
-            )?)) as Arc<std::sync::RwLock<dyn BlockStorage + Send + Sync + 'static>>
-        }
-        #[cfg(target_family = "wasm")]
-        {
-            panic!("no RocksDB in WASM");
-        }
-    };
-    let client = wallet.client().as_ref().unwrap().clone();
-    let opened_wallet = OpenedWallet {
-        wallet,
-        block_storage,
-    };
-
-    broker.opened_wallets.insert(wallet_id, opened_wallet);
-    Ok(client)
+    broker.wallet_was_opened(wallet).await
 }
 
 /// Starts a session with the LocalBroker. The type of verifier is selected at this moment.
 ///
 /// The session is valid even if there is no internet. The local data will be used in this case.
+/// wallet_creation_events should be the list of events that was returned by wallet_create_v0
 /// Return value is the index of the session, will be used in all the doc_* API calls.
 pub async fn session_start(mut config: SessionConfig) -> Result<SessionInfo, NgError> {
     let mut broker = match LOCAL_BROKER.get() {
@@ -798,167 +1088,7 @@ pub async fn session_start(mut config: SessionConfig) -> Result<SessionInfo, NgE
         Some(Ok(broker)) => broker.write().await,
     };
 
-    config.valid_verifier_config_for_local_broker_config(&broker.config)?;
-
-    let wallet_name: String = config.wallet_name();
-    let wallet_id: PubKey = (*wallet_name).try_into()?;
-    let user_id = config.user_id();
-
-    match broker.opened_wallets.get(&wallet_name) {
-        None => return Err(NgError::WalletNotFound),
-        Some(opened_wallet) => {
-            let block_storage = Arc::clone(&opened_wallet.block_storage);
-            let credentials = match opened_wallet.wallet.individual_site(&user_id) {
-                Some(creds) => creds.clone(),
-                None => return Err(NgError::NotFound),
-            };
-
-            let client_storage_master_key = serde_bare::to_vec(
-                &opened_wallet
-                    .wallet
-                    .client()
-                    .as_ref()
-                    .unwrap()
-                    .sensitive_client_storage
-                    .storage_master_key,
-            )
-            .unwrap();
-
-            let session = match broker.sessions.get(&user_id) {
-                Some(session) => session,
-                None => {
-                    // creating the session now
-                    let closed_wallet = broker.wallets.get(&wallet_name).unwrap();
-                    if closed_wallet.in_memory {
-                        let session = SessionPeerStorageV0::new(user_id);
-                        broker.sessions.insert(user_id, session);
-                        broker.sessions.get(&user_id).unwrap()
-                    } else {
-                        // first check if there is a saved SessionWalletStorage
-                        let mut sws = match &broker.config {
-                            LocalBrokerConfig::InMemory => panic!("cannot open saved session"),
-                            LocalBrokerConfig::JsStorage(js_config) => {
-                                // read session wallet storage from JsStorage
-                                let res =
-                                    (js_config.session_read)(format!("ng_wallet@{}", wallet_name));
-                                match res {
-                                    Ok(string) => {
-                                        let decoded = base64_url::decode(&string)
-                                            .map_err(|_| NgError::SerializationError)?;
-                                        Some(SessionWalletStorageV0::dec_session(
-                                            opened_wallet.wallet.privkey(),
-                                            &decoded,
-                                        )?)
-                                    }
-                                    Err(_) => None,
-                                }
-                            }
-                            LocalBrokerConfig::BasePath(base_path) => {
-                                // read session wallet storage from disk
-                                let mut path = base_path.clone();
-                                path.push("sessions");
-                                path.push(wallet_name.clone());
-                                let res = read(path);
-                                if res.is_ok() {
-                                    Some(SessionWalletStorageV0::dec_session(
-                                        opened_wallet.wallet.privkey(),
-                                        &res.unwrap(),
-                                    )?)
-                                } else {
-                                    None
-                                }
-                            }
-                        };
-                        let (session, new_sws) = match &mut sws {
-                            None => {
-                                let (s, sws_ser) = SessionWalletStorageV0::create_new_session(
-                                    &wallet_id, user_id,
-                                )?;
-                                broker.sessions.insert(user_id, s);
-                                (broker.sessions.get(&user_id).unwrap(), sws_ser)
-                            }
-                            Some(sws) => {
-                                match sws.users.get(&user_id.to_string()) {
-                                    Some(sps) => {
-                                        broker.sessions.insert(user_id, sps.clone());
-                                        (broker.sessions.get(&user_id).unwrap(), vec![])
-                                    }
-                                    None => {
-                                        // the user was not found in the SWS. we need to create a SPS, add it, encrypt and serialize the new SWS,
-                                        // add the SPS to broker.sessions, and return the newly created SPS and the new SWS encrypted serialization
-                                        let sps = SessionPeerStorageV0::new(user_id);
-                                        sws.users.insert(user_id.to_string(), sps.clone());
-                                        let encrypted = sws.enc_session(&wallet_id)?;
-                                        broker.sessions.insert(user_id, sps);
-                                        (broker.sessions.get(&user_id).unwrap(), encrypted)
-                                    }
-                                }
-                            }
-                        };
-                        // save the new sws
-                        if new_sws.len() > 0 {
-                            match &broker.config {
-                                LocalBrokerConfig::InMemory => {
-                                    panic!("cannot save session when InMemory mode")
-                                }
-                                LocalBrokerConfig::JsStorage(js_config) => {
-                                    // save session wallet storage to JsStorage
-                                    let encoded = base64_url::encode(&new_sws);
-                                    (js_config.session_write)(
-                                        format!("ng_wallet@{}", wallet_name),
-                                        encoded,
-                                    )?;
-                                }
-                                LocalBrokerConfig::BasePath(base_path) => {
-                                    // save session wallet storage to disk
-                                    let mut path = base_path.clone();
-                                    path.push("sessions");
-                                    std::fs::create_dir_all(path.clone()).unwrap();
-                                    path.push(wallet_name);
-                                    //log_debug!("{}", path.clone().display());
-                                    write(path.clone(), &new_sws).map_err(|_| NgError::IoError)?;
-                                }
-                            }
-                        }
-                        session
-                    }
-                }
-            };
-            let session = session.clone();
-
-            // derive user_master_key from client's storage_master_key
-            let user_id_ser = serde_bare::to_vec(&user_id).unwrap();
-            let mut key_material = [user_id_ser, client_storage_master_key].concat(); //
-            let mut key: [u8; 32] = derive_key(
-                "NextGraph user_master_key BLAKE3 key",
-                key_material.as_slice(),
-            );
-            key_material.zeroize();
-            let verifier = Verifier::new(
-                VerifierConfig {
-                    config_type: broker.verifier_config_type_from_session_config(&config),
-                    user_master_key: key,
-                    peer_priv_key: session.peer_key.clone(),
-                    user_priv_key: credentials.0,
-                    private_store_read_cap: credentials.1,
-                },
-                block_storage,
-            )?;
-            key.zeroize();
-            broker.opened_sessions_list.push(Some(Session {
-                config,
-                peer_key: session.peer_key.clone(),
-                last_wallet_nonce: session.last_wallet_nonce,
-                verifier,
-            }));
-            let idx = broker.opened_sessions_list.len() - 1;
-            broker.opened_sessions.insert(user_id, idx as u8);
-            Ok(SessionInfo {
-                session_id: idx as u8,
-                user: user_id,
-            })
-        }
-    }
+    broker.session_start(config, None).await
 }
 
 use web_time::SystemTime;
diff --git a/ng-app/src-tauri/src/lib.rs b/ng-app/src-tauri/src/lib.rs
index 4677289..048721b 100644
--- a/ng-app/src-tauri/src/lib.rs
+++ b/ng-app/src-tauri/src/lib.rs
@@ -21,7 +21,6 @@ use serde_json::Value;
 use std::collections::HashMap;
 use std::fs::{read, write, File, OpenOptions};
 use std::io::Write;
-use std::path::PathBuf;
 use tauri::scope::ipc::RemoteDomainAccessScope;
 use tauri::utils::config::WindowConfig;
 use tauri::{path::BaseDirectory, App, Manager, Window};
@@ -42,17 +41,6 @@ async fn test(app: tauri::AppHandle) -> Result<(), ()> {
         .unwrap();
     init_local_broker(Box::new(move || LocalBrokerConfig::BasePath(path.clone()))).await;
 
-    // init_local_broker(&Lazy::new(|| {
-    //     Box::new(move || LocalBrokerConfig::BasePath(path.clone()))
-    // }))
-    // .await;
-    //pub type LastSeqFn = dyn Fn(PubKey, u16) -> Result<u64, NgError> + 'static + Sync + Send;
-
-    // let test: Box<LastSeqFn> = Box::new(move |peer_id: PubKey, qty: u16| {
-    //     take_some_peer_last_seq_numbers(peer_id, qty, path.clone())
-    // });
-    //pub type ConfigInitFn = dyn Fn() -> LocalBrokerConfig + 'static + Sync + Send;
-
     //log_debug!("test is {}", BROKER.read().await.test());
     let path = app
         .path()
@@ -136,49 +124,6 @@ async fn wallet_create(
     Ok(cwr)
 }
 
-fn take_some_peer_last_seq_numbers(
-    peer_id: PubKey,
-    qty: u16,
-    mut path: PathBuf,
-) -> Result<u64, NgError> {
-    std::fs::create_dir_all(path.clone()).unwrap();
-    path.push(peer_id.to_string());
-    log_debug!("{}", path.display());
-
-    let file = read(path.clone());
-    let (mut file_save, val) = match file {
-        Ok(ser) => {
-            let old_val = match SessionPeerLastSeq::deser(&ser)? {
-                SessionPeerLastSeq::V0(v) => v,
-                _ => unimplemented!(),
-            };
-            (
-                OpenOptions::new()
-                    .write(true)
-                    .open(path)
-                    .map_err(|_| NgError::SerializationError)?,
-                old_val,
-            )
-        }
-        Err(_) => (
-            File::create(path).map_err(|_| NgError::SerializationError)?,
-            0,
-        ),
-    };
-    let new_val = val + qty as u64;
-    let spls = SessionPeerLastSeq::V0(new_val);
-    let ser = spls.ser()?;
-    file_save
-        .write_all(&ser)
-        .map_err(|_| NgError::SerializationError)?;
-
-    file_save
-        .sync_data()
-        .map_err(|_| NgError::SerializationError)?;
-
-    Ok(val)
-}
-
 #[tauri::command(rename_all = "snake_case")]
 async fn wallet_read_file(file: Vec<u8>, app: tauri::AppHandle) -> Result<Wallet, String> {
     nextgraph::local_broker::wallet_read_file(file)
diff --git a/ng-broker/src/server_ws.rs b/ng-broker/src/server_ws.rs
index b097910..aa96c12 100644
--- a/ng-broker/src/server_ws.rs
+++ b/ng-broker/src/server_ws.rs
@@ -734,6 +734,7 @@ pub async fn run_server_v0(
                     servers.push(BrokerServerV0 {
                         peer_id: common_peer_id.unwrap_or(peer_id),
                         can_verify: false,
+                        can_forward: !run_core,
                         server_type,
                     })
                 }
diff --git a/ng-net/src/types.rs b/ng-net/src/types.rs
index ae0209b..5baf8fc 100644
--- a/ng-net/src/types.rs
+++ b/ng-net/src/types.rs
@@ -150,6 +150,9 @@ pub struct BrokerServerV0 {
     /// is this server capable of running a verifier
     pub can_verify: bool,
 
+    /// is this server capable of forwarding client connections to another broker
+    pub can_forward: bool,
+
     /// peerId of the server
     pub peer_id: PubKey,
 }
@@ -164,6 +167,7 @@ impl BrokerServerV0 {
         BrokerServerV0 {
             server_type: BrokerServerTypeV0::Localhost(WS_PORT_ALTERNATE[0]),
             can_verify: false,
+            can_forward: true,
             peer_id,
         }
     }
@@ -3772,6 +3776,7 @@ mod test {
                 servers: vec![BrokerServerV0 {
                     server_type: BrokerServerTypeV0::Localhost(14400),
                     can_verify: false,
+                    can_forward: false,
                     peer_id: PubKey::Ed25519PubKey([
                         95, 73, 225, 250, 3, 147, 24, 164, 177, 211, 34, 244, 45, 130, 111, 136,
                         229, 145, 53, 167, 50, 168, 140, 227, 65, 111, 203, 41, 210, 186, 162, 149,
diff --git a/ng-repo/src/commit.rs b/ng-repo/src/commit.rs
index 0a72a5d..0bf2af5 100644
--- a/ng-repo/src/commit.rs
+++ b/ng-repo/src/commit.rs
@@ -402,6 +402,11 @@ impl Commit {
         }
     }
 
+    /// Get branch ID this commit is about
+    pub fn branch(&self) -> &BranchId {
+        self.content().branch()
+    }
+
     /// Get commit signature
     pub fn header(&self) -> &Option<CommitHeader> {
         match self {
@@ -701,7 +706,7 @@ impl Commit {
         }
         self.verify_sig(repo)?;
         self.verify_perm(repo)?;
-        //self.verify_full_object_refs_of_branch_at_commit(repo.store.unwrap())?;
+        self.verify_full_object_refs_of_branch_at_commit(&repo.store)?;
         Ok(())
     }
 }
diff --git a/ng-repo/src/errors.rs b/ng-repo/src/errors.rs
index 959dd77..7b172c1 100644
--- a/ng-repo/src/errors.rs
+++ b/ng-repo/src/errors.rs
@@ -44,6 +44,10 @@ pub enum NgError {
     WalletError(String),
     BrokerError,
     SessionNotFound,
+    SessionAlreadyStarted,
+    RepoNotFound,
+    BranchNotFound,
+    StoreNotFound,
 }
 
 impl Error for NgError {}
diff --git a/ng-repo/src/event.rs b/ng-repo/src/event.rs
index 65c292a..5dc55a3 100644
--- a/ng-repo/src/event.rs
+++ b/ng-repo/src/event.rs
@@ -8,13 +8,20 @@
 
 //! Event, a message sent in the PUB/SUB
 
+use zeroize::Zeroize;
+
 use crate::block_storage::*;
 use crate::errors::*;
 use crate::object::*;
+use crate::repo::Repo;
 use crate::store::Store;
 use crate::types::*;
 use crate::utils::*;
 use core::fmt;
+use std::sync::Arc;
+
+use chacha20::cipher::{KeyIvInit, StreamCipher};
+use chacha20::ChaCha20;
 
 impl fmt::Display for Event {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -54,38 +61,75 @@ impl fmt::Display for EventContentV0 {
 }
 
 impl Event {
-    pub fn new<'a>(
+    pub fn new(
         publisher: &PrivKey,
         seq: u64,
         commit: &Commit,
         additional_blocks: &Vec<BlockId>,
-        topic_id: TopicId,
-        topic_priv_key: &BranchWriteCapSecret,
-        store: &'a Store,
+        repo: &Repo,
     ) -> Result<Event, NgError> {
         Ok(Event::V0(EventV0::new(
             publisher,
             seq,
             commit,
             additional_blocks,
-            topic_id,
-            topic_priv_key,
-            store,
+            repo,
         )?))
     }
+
+    pub fn seq_num(&self) -> u64 {
+        match self {
+            Event::V0(v0) => v0.content.seq,
+        }
+    }
 }
 
 impl EventV0 {
-    pub fn new<'a>(
+    pub fn derive_key(
+        repo_id: &RepoId,
+        branch_id: &BranchId,
+        branch_secret: &ReadCapSecret,
+        publisher: &PubKey,
+    ) -> [u8; blake3::OUT_LEN] {
+        let mut key_material = match (*repo_id, *branch_id, branch_secret.clone(), *publisher) {
+            (
+                PubKey::Ed25519PubKey(repo),
+                PubKey::Ed25519PubKey(branch),
+                SymKey::ChaCha20Key(branch_sec),
+                PubKey::Ed25519PubKey(publ),
+            ) => [repo, branch, branch_sec, publ].concat(),
+            (_, _, _, _) => panic!("cannot derive key with Montgomery key"),
+        };
+        let res = blake3::derive_key(
+            "NextGraph Event Commit ObjectKey ChaCha20 key",
+            key_material.as_slice(),
+        );
+        key_material.zeroize();
+        res
+    }
+
+    pub fn new(
         publisher: &PrivKey,
         seq: u64,
         commit: &Commit,
         additional_blocks: &Vec<BlockId>,
-        topic_id: TopicId,
-        topic_priv_key: &BranchWriteCapSecret,
-        store: &'a Store,
+        repo: &Repo,
     ) -> Result<EventV0, NgError> {
-        let branch_read_cap_secret = &store.get_store_readcap().key;
+        let branch_id = commit.branch();
+        let repo_id = repo.id;
+        let store = Arc::clone(&repo.store);
+        let branch = repo.branch(branch_id)?;
+        let topic_id = &branch.topic;
+        let topic_priv_key = &branch.topic_priv_key;
+        let publisher_pubkey = publisher.to_pub();
+        let key = Self::derive_key(&repo_id, branch_id, &branch.read_cap.key, &publisher_pubkey);
+        let commit_key = commit.key().unwrap();
+        let mut encrypted_commit_key = Vec::from(commit_key.slice());
+        let mut nonce = seq.to_le_bytes().to_vec();
+        nonce.append(&mut vec![0; 4]);
+        let mut cipher = ChaCha20::new((&key).into(), (nonce.as_slice()).into());
+        cipher.apply_keystream(encrypted_commit_key.as_mut_slice());
+
         let mut blocks = vec![];
         for bid in commit.blocks().iter() {
             blocks.push(store.get(bid)?);
@@ -93,10 +137,8 @@ impl EventV0 {
         for bid in additional_blocks.iter() {
             blocks.push(store.get(bid)?);
         }
-        // (*seq) += 1;
-        let publisher_pubkey = publisher.to_pub();
         let event_content = EventContentV0 {
-            topic: topic_id,
+            topic: *topic_id,
             publisher: PeerId::Forwarded(publisher_pubkey),
             seq,
             blocks,
@@ -104,10 +146,10 @@ impl EventV0 {
                 .header()
                 .as_ref()
                 .map_or_else(|| vec![], |h| h.files().to_vec()),
-            key: vec![], // TODO
+            key: encrypted_commit_key,
         };
         let event_content_ser = serde_bare::to_vec(&event_content).unwrap();
-        let topic_sig = sign(topic_priv_key, &topic_id, &event_content_ser)?;
+        let topic_sig = sign(topic_priv_key, topic_id, &event_content_ser)?;
         let peer_sig = sign(publisher, &publisher_pubkey, &event_content_ser)?;
         Ok(EventV0 {
             content: event_content,
diff --git a/ng-repo/src/lib.rs b/ng-repo/src/lib.rs
index 41ef77e..4c472bc 100644
--- a/ng-repo/src/lib.rs
+++ b/ng-repo/src/lib.rs
@@ -22,8 +22,6 @@ pub mod branch;
 
 pub mod repo;
 
-pub mod site;
-
 pub mod store;
 
 pub mod event;
diff --git a/ng-repo/src/object.rs b/ng-repo/src/object.rs
index 4671965..7029d5d 100644
--- a/ng-repo/src/object.rs
+++ b/ng-repo/src/object.rs
@@ -60,19 +60,17 @@ pub struct Object {
 }
 
 impl Object {
-    pub(crate) fn convergence_key(
-        /*store_pubkey: &StoreRepo,
-        store_readcap_secret: &ReadCapSecret,*/
-        store: &Store,
-    ) -> [u8; blake3::OUT_LEN] {
+    // if it is a Store root repo, the key_material is derived from RepoId + RepoWriteCapSecret
+    // for a private store root repo, the repowritecapsecret is omitted (zeros)
+    pub(crate) fn convergence_key(store: &Store) -> [u8; blake3::OUT_LEN] {
         let mut key_material = match (
             *store.get_store_repo().repo_id(),
-            store.get_store_readcap_secret().clone(),
+            store.get_store_overlay_branch_readcap_secret().clone(),
         ) {
             (PubKey::Ed25519PubKey(pubkey), SymKey::ChaCha20Key(secret)) => {
                 [pubkey, secret].concat()
             }
-            (_, _) => panic!("cannot sign with Montgomery key"),
+            (_, _) => panic!("cannot derive key with Montgomery key"),
         };
         let res = blake3::derive_key("NextGraph Data BLAKE3 key", key_material.as_slice());
         key_material.zeroize();
diff --git a/ng-repo/src/repo.rs b/ng-repo/src/repo.rs
index b3bb8cf..1185ad4 100644
--- a/ng-repo/src/repo.rs
+++ b/ng-repo/src/repo.rs
@@ -74,15 +74,36 @@ impl UserInfo {
     }
 }
 
+#[derive(Debug)]
+pub struct BranchInfo {
+    pub id: BranchId,
+
+    pub branch_type: BranchType,
+
+    pub topic: TopicId,
+
+    pub topic_priv_key: BranchWriteCapSecret,
+
+    pub read_cap: ReadCap,
+}
+
 /// In memory Repository representation. With helper functions that access the underlying UserStore and keeps proxy of the values
+#[derive(Debug)]
 pub struct Repo {
     pub id: RepoId,
     /// Repo definition
     pub repo_def: Repository,
 
+    pub read_cap: Option<ReadCap>,
+
+    pub write_cap: Option<RepoWriteCapSecret>,
+
     pub signer: Option<SignerCap>,
 
     pub members: HashMap<Digest, UserInfo>,
+
+    pub branches: HashMap<BranchId, BranchInfo>,
+
     pub store: Arc<Store>,
 }
 
@@ -139,16 +160,19 @@ impl Repo {
             members,
             store,
             signer: None,
+            read_cap: None,
+            write_cap: None,
+            branches: HashMap::new(),
         }
     }
 
     pub fn verify_permission(&self, commit: &Commit) -> Result<(), NgError> {
         let content_author = commit.content_v0().author;
-        // let body = commit.load_body(self.store.unwrap())?;
-        // match self.members.get(&content_author) {
-        //     Some(info) => return info.has_any_perm(&body.required_permission()),
-        //     None => {}
-        // }
+        let body = commit.load_body(&self.store)?;
+        match self.members.get(&content_author) {
+            Some(info) => return info.has_any_perm(&body.required_permission()),
+            None => {}
+        }
         Err(NgError::PermissionDenied)
     }
 
@@ -159,6 +183,27 @@ impl Repo {
         }
     }
 
+    pub fn branch(&self, id: &BranchId) -> Result<&BranchInfo, NgError> {
+        //TODO: load the BranchInfo from storage
+        self.branches.get(id).ok_or(NgError::BranchNotFound)
+    }
+
+    pub fn overlay_branch(&self) -> Option<&BranchInfo> {
+        for (_, branch) in self.branches.iter() {
+            if branch.branch_type == BranchType::Overlay {
+                return Some(branch);
+            }
+        }
+        None
+    }
+
+    pub fn overlay_branch_read_cap(&self) -> Option<&ReadCap> {
+        match self.overlay_branch() {
+            Some(bi) => Some(&bi.read_cap),
+            None => self.read_cap.as_ref(), // this is for private stores that don't have an overlay branch
+        }
+    }
+
     // pub(crate) fn get_store(&self) -> &Store {
     //     self.store.unwrap()
     // }
diff --git a/ng-repo/src/store.rs b/ng-repo/src/store.rs
index 1a9f75a..50a64ce 100644
--- a/ng-repo/src/store.rs
+++ b/ng-repo/src/store.rs
@@ -11,30 +11,51 @@
 
 //! Store of a Site, or of a Group or Dialog
 
+use core::fmt;
 use std::collections::HashMap;
 use std::sync::{Arc, RwLock};
 
 use crate::block_storage::BlockStorage;
 use crate::errors::{NgError, StorageError};
 use crate::object::Object;
-use crate::repo::Repo;
+use crate::repo::{BranchInfo, Repo};
 use crate::types::*;
 use crate::utils::{generate_keypair, sign, verify};
 
 use crate::log::*;
 
 use rand::prelude::*;
-
 use threshold_crypto::{SecretKeySet, SecretKeyShare};
 
 pub struct Store {
     store_repo: StoreRepo,
     store_readcap: ReadCap,
+    store_overlay_branch_readcap: ReadCap,
     overlay_id: OverlayId,
     storage: Arc<RwLock<dyn BlockStorage + Send + Sync>>,
-    //repos: HashMap<RepoId, Repo>,
 }
+
+impl fmt::Debug for Store {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        writeln!(f, "Store.\nstore_repo {:?}", self.store_repo)?;
+        writeln!(f, "store_readcap {:?}", self.store_readcap)?;
+        writeln!(
+            f,
+            "store_overlay_branch_readcap {:?}",
+            self.store_overlay_branch_readcap
+        )?;
+        writeln!(f, "overlay_id {:?}", self.overlay_id)
+    }
+}
+
 impl Store {
+    pub fn set_read_caps(&mut self, read_cap: ReadCap, overlay_read_cap: Option<ReadCap>) {
+        self.store_readcap = read_cap;
+        if let Some(overlay_read_cap) = overlay_read_cap {
+            self.store_overlay_branch_readcap = overlay_read_cap;
+        }
+    }
+
     pub fn get_store_repo(&self) -> &StoreRepo {
         &self.store_repo
     }
@@ -43,6 +64,10 @@ impl Store {
         &self.store_readcap
     }
 
+    pub fn get_store_overlay_branch_readcap_secret(&self) -> &ReadCapSecret {
+        &self.store_overlay_branch_readcap.key
+    }
+
     pub fn get_store_readcap_secret(&self) -> &ReadCapSecret {
         &self.store_readcap.key
     }
@@ -83,6 +108,7 @@ impl Store {
         self: Arc<Self>,
         creator: &UserId,
         creator_priv_key: &PrivKey,
+        repo_write_cap_secret: SymKey,
     ) -> Result<(Repo, Vec<(Commit, Vec<Digest>)>), NgError> {
         let mut events = Vec::with_capacity(6);
 
@@ -118,8 +144,6 @@ impl Store {
 
         // creating the RootBranch commit, acks to Repository commit
 
-        let repo_write_cap_secret = SymKey::random();
-
         let root_branch_commit_body =
             CommitBody::V0(CommitBodyV0::RootBranch(RootBranch::V0(RootBranchV0 {
                 id: repo_pub_key,
@@ -316,7 +340,7 @@ impl Store {
             repo_pub_key,
             QuorumType::IamTheSignature,
             vec![add_branch_commit.reference().unwrap()],
-            vec![root_branch_readcap],
+            vec![root_branch_readcap.clone()],
             sync_sig_commit_body.clone(),
             &self,
         )?;
@@ -340,7 +364,7 @@ impl Store {
             main_branch_pub_key,
             QuorumType::IamTheSignature,
             vec![branch_read_cap.clone()],
-            vec![branch_read_cap],
+            vec![branch_read_cap.clone()],
             sync_sig_commit_body,
             &self,
         )?;
@@ -358,12 +382,34 @@ impl Store {
 
         // preparing the Repo
 
+        let root_branch = BranchInfo {
+            id: repo_pub_key.clone(),
+            branch_type: BranchType::Root,
+            topic: topic_pub_key,
+            topic_priv_key: topic_priv_key,
+            read_cap: root_branch_readcap.clone(),
+        };
+
+        let main_branch = BranchInfo {
+            id: main_branch_pub_key.clone(),
+            branch_type: BranchType::Main,
+            topic: main_branch_topic_pub_key,
+            topic_priv_key: main_branch_topic_priv_key,
+            read_cap: branch_read_cap,
+        };
+
         let repo = Repo {
             id: repo_pub_key,
             repo_def: repository,
             signer: Some(signer_cap),
             members: HashMap::new(),
-            store: self,
+            store: Arc::clone(&self),
+            read_cap: Some(root_branch_readcap),
+            write_cap: Some(repo_write_cap_secret),
+            branches: HashMap::from([
+                (repo_pub_key, root_branch),
+                (main_branch_pub_key, main_branch),
+            ]),
         };
 
         Ok((repo, events))
@@ -372,6 +418,7 @@ impl Store {
     pub fn new(
         store_repo: StoreRepo,
         store_readcap: ReadCap,
+        store_overlay_branch_readcap: ReadCap,
         storage: Arc<RwLock<dyn BlockStorage + Send + Sync>>,
     ) -> Self {
         Self {
@@ -379,6 +426,7 @@ impl Store {
             store_readcap,
             overlay_id: store_repo.overlay_id_for_storage_purpose(),
             storage,
+            store_overlay_branch_readcap,
         }
     }
 
@@ -388,9 +436,11 @@ impl Store {
         use crate::block_storage::HashMapBlockStorage;
         let store_repo = StoreRepo::dummy_public_v0();
         let store_readcap = ReadCap::dummy();
+        let store_overlay_branch_readcap = ReadCap::dummy();
         Arc::new(Self::new(
             store_repo,
             store_readcap,
+            store_overlay_branch_readcap,
             Arc::new(RwLock::new(HashMapBlockStorage::new()))
                 as Arc<RwLock<dyn BlockStorage + Send + Sync>>,
         ))
@@ -401,9 +451,11 @@ impl Store {
         use crate::block_storage::HashMapBlockStorage;
         let store_repo = StoreRepo::dummy_with_key(repo_pubkey);
         let store_readcap = ReadCap::dummy();
+        let store_overlay_branch_readcap = ReadCap::dummy();
         Arc::new(Self::new(
             store_repo,
             store_readcap,
+            store_overlay_branch_readcap,
             Arc::new(RwLock::new(HashMapBlockStorage::new()))
                 as Arc<RwLock<dyn BlockStorage + Send + Sync>>,
         ))
diff --git a/ng-repo/src/types.rs b/ng-repo/src/types.rs
index 7b602dd..feb0d4d 100644
--- a/ng-repo/src/types.rs
+++ b/ng-repo/src/types.rs
@@ -91,7 +91,6 @@ impl SymKey {
     pub fn from_array(array: [u8; 32]) -> Self {
         SymKey::ChaCha20Key(array)
     }
-    #[deprecated(note = "**Don't use nil method**")]
     pub fn nil() -> Self {
         SymKey::ChaCha20Key([0; 32])
     }
@@ -399,7 +398,6 @@ impl BlockId {
         Digest::Blake3Digest32([0u8; 32])
     }
 
-    #[deprecated(note = "**Don't use nil method**")]
     pub fn nil() -> Self {
         Digest::Blake3Digest32([0u8; 32])
     }
@@ -414,7 +412,6 @@ impl BlockRef {
         }
     }
 
-    #[deprecated(note = "**Don't use nil method**")]
     pub fn nil() -> Self {
         BlockRef {
             id: Digest::Blake3Digest32([0u8; 32]),
@@ -742,29 +739,6 @@ pub enum SiteName {
     Name(String),
 }
 
-/// Site V0
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct SiteV0 {
-    pub site_type: SiteType,
-
-    pub id: PubKey,
-
-    pub name: SiteName,
-
-    // Identity::OrgPublicStore or Identity::IndividualPublicStore
-    pub public: SiteStore,
-
-    // Identity::OrgProtectedStore or Identity::IndividualProtectedStore
-    pub protected: SiteStore,
-
-    // Identity::OrgPrivateStore or Identity::IndividualPrivateStore
-    pub private: SiteStore,
-
-    /// Only for IndividualSite: TODO reorganize those 2 fields
-    pub cores: Vec<(PubKey, Option<[u8; 32]>)>,
-    pub bootstraps: Vec<PubKey>,
-}
-
 /// Reduced Site (for QRcode)
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct ReducedSiteV0 {
@@ -971,9 +945,8 @@ pub enum Block {
 ///
 /// First commit published in root branch, signed by repository key
 /// For the Root repo of a store(overlay), the convergence_key should be derived from :
-/// "NextGraph Store Root Repo BLAKE3 convergence key",
-///                                     RepoId + RepoWriteCapSecret)
-/// for a private store root repo, the repowritecapsecret can be omitted
+/// "NextGraph Data BLAKE3 key", RepoId + RepoWriteCapSecret)
+/// for a private store root repo, the RepoWriteCapSecret can be omitted
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
 pub struct RepositoryV0 {
     /// Repo public key ID
@@ -1077,7 +1050,7 @@ pub struct RootBranchV0 {
 
     /// Mutable App-specific metadata
     /// when the list of owners is changed, a crypto_box containing the RepoWriteCapSecret should be included here for each owner.
-    /// this should also be done at creation time, with the UserId of the first owner, except for individual store repo, because it doesnt have a RepoWriteCapSecret
+    /// this should also be done at creation time, with the UserId of the first owner, except for individual private store repo, because it doesnt have a RepoWriteCapSecret
     #[serde(with = "serde_bytes")]
     pub metadata: Vec<u8>,
 }
@@ -1247,7 +1220,8 @@ pub enum BranchType {
     Store,
     Overlay,
     User,
-    Transactional, // this could have been called OtherTransaction, but for the sake of simplicity, we use Transaction for any branch that is not the Main one.
+    Transactional, // this could have been called OtherTransaction, but for the sake of simplicity, we use Transactional for any branch that is not the Main one.
+    Root,          // only used for BranchInfo
 }
 
 impl fmt::Display for BranchType {
@@ -1262,6 +1236,7 @@ impl fmt::Display for BranchType {
                 Self::Overlay => "Overlay",
                 Self::User => "User",
                 Self::Transactional => "Transactional",
+                Self::Root => "Root",
             }
         )
     }
@@ -2161,6 +2136,11 @@ impl CommitContent {
             CommitContent::V0(v0) => &v0.author,
         }
     }
+    pub fn branch(&self) -> &BranchId {
+        match self {
+            CommitContent::V0(v0) => &v0.branch,
+        }
+    }
 
     pub fn author_digest(author: &UserId, overlay: OverlayId) -> Digest {
         let author_id = serde_bare::to_vec(author).unwrap();
diff --git a/ng-sdk-js/src/lib.rs b/ng-sdk-js/src/lib.rs
index e9afeaf..cfdae4f 100644
--- a/ng-sdk-js/src/lib.rs
+++ b/ng-sdk-js/src/lib.rs
@@ -162,74 +162,6 @@ pub async fn get_wallets() -> Result<JsValue, JsValue> {
     Ok(JsValue::UNDEFINED)
 }
 
-fn take_some_peer_last_seq_numbers(peer_id: PubKey, qty: u16) -> Result<u64, NgError> {
-    let res = session_get(format!("ng_peer_last_seq@{}", peer_id));
-    let val = match res {
-        Some(old_str) => {
-            let decoded = base64_url::decode(&old_str).map_err(|_| NgError::SerializationError)?;
-            match serde_bare::from_slice(&decoded)? {
-                SessionPeerLastSeq::V0(old_val) => old_val,
-                _ => unimplemented!(),
-            }
-        }
-        None => 0,
-    };
-    let new_val = val + qty as u64;
-    let spls = SessionPeerLastSeq::V0(new_val);
-    let ser = serde_bare::to_vec(&spls)?;
-    //saving the new val
-    let encoded = base64_url::encode(&ser);
-    let r = session_save(format!("ng_peer_last_seq@{}", peer_id), encoded);
-    if r.is_some() {
-        return Err(NgError::SerializationError);
-    }
-    Ok(val)
-}
-
-// #[cfg(target_arch = "wasm32")]
-// #[wasm_bindgen]
-// async fn init_local_broker_persistent() -> Result<(), String> {
-//     init_local_broker_(false, None).await
-// }
-
-// #[cfg(target_arch = "wasm32")]
-// #[wasm_bindgen]
-// async fn init_local_broker_with_path(path: String) -> Result<(), String> {
-//     init_local_broker_(false, Some(path)).await
-// }
-
-// #[cfg(target_arch = "wasm32")]
-// #[wasm_bindgen]
-// async fn init_local_broker_in_memory() -> Result<(), String> {
-//     init_local_broker_(true, None).await
-// }
-
-async fn init_local_broker_(in_memory: bool, path: Option<String>) -> Result<(), String> {
-    // INIT_BROKER
-    //     .get_or_init(async {
-    //         BROKER
-    //             .write()
-    //             .await
-    //             .register_last_seq_function(Box::new(take_some_peer_last_seq_numbers));
-    //         true
-    //     })
-    //     .await;
-    Ok(())
-}
-
-async fn init_local_broker_internal() -> Result<(), String> {
-    // INIT_BROKER
-    //     .get_or_init(async {
-    //         BROKER
-    //             .write()
-    //             .await
-    //             .register_last_seq_function(Box::new(take_some_peer_last_seq_numbers));
-    //         true
-    //     })
-    //     .await;
-    Ok(())
-}
-
 #[cfg(target_arch = "wasm32")]
 #[wasm_bindgen]
 pub async fn session_start(wallet_name: String, user_js: JsValue) -> Result<JsValue, String> {
diff --git a/ng-storage-rocksdb/src/kcv_storage.rs b/ng-storage-rocksdb/src/kcv_storage.rs
index 48c39cc..0e41b26 100644
--- a/ng-storage-rocksdb/src/kcv_storage.rs
+++ b/ng-storage-rocksdb/src/kcv_storage.rs
@@ -585,7 +585,10 @@ impl RocksdbKCVStore {
         let db: TransactionDB =
             TransactionDB::open_cf(&opts, &tx_options, &path, vec!["cf0", "cf1"]).unwrap();
 
-        log_info!("created db with Rocksdb Version: {}", Env::version());
+        log_info!(
+            "created kcv storage with Rocksdb Version: {}",
+            Env::version()
+        );
 
         Ok(RocksdbKCVStore {
             db: db,
diff --git a/ng-verifier/Cargo.toml b/ng-verifier/Cargo.toml
index e6d22b0..a3dcb6f 100644
--- a/ng-verifier/Cargo.toml
+++ b/ng-verifier/Cargo.toml
@@ -15,6 +15,9 @@ rust-version.workspace = true
 [badges]
 maintenance = { status = "actively-developed" }
 
+[features]
+testing = []
+
 [dependencies]
 ng-repo = { path = "../ng-repo", version = "0.1.0" }
 ng-net = { path = "../ng-net", version = "0.1.0" }
diff --git a/ng-verifier/src/lib.rs b/ng-verifier/src/lib.rs
index 5f13f5b..afd6068 100644
--- a/ng-verifier/src/lib.rs
+++ b/ng-verifier/src/lib.rs
@@ -4,5 +4,7 @@ pub mod user_storage;
 
 pub mod verifier;
 
+pub mod site;
+
 #[cfg(not(target_family = "wasm"))]
 pub mod rocksdb_user_storage;
diff --git a/ng-repo/src/site.rs b/ng-verifier/src/site.rs
similarity index 54%
rename from ng-repo/src/site.rs
rename to ng-verifier/src/site.rs
index a284055..3880726 100644
--- a/ng-repo/src/site.rs
+++ b/ng-verifier/src/site.rs
@@ -11,9 +11,35 @@
 
 //! Site (Public, Protected, Private) of Individual and Org
 
-use crate::errors::NgError;
 use crate::types::*;
-use crate::utils::{generate_keypair, sign, verify};
+use crate::verifier::Verifier;
+use ng_repo::errors::NgError;
+use ng_repo::types::*;
+use ng_repo::utils::{generate_keypair, sign, verify};
+use serde::{Deserialize, Serialize};
+
+/// Site V0
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct SiteV0 {
+    pub site_type: SiteType,
+
+    pub id: PubKey,
+
+    pub name: SiteName,
+
+    // Identity::OrgPublicStore or Identity::IndividualPublicStore
+    pub public: SiteStore,
+
+    // Identity::OrgProtectedStore or Identity::IndividualProtectedStore
+    pub protected: SiteStore,
+
+    // Identity::OrgPrivateStore or Identity::IndividualPrivateStore
+    pub private: SiteStore,
+
+    /// Only for IndividualSite: TODO reorganize those 2 fields
+    pub cores: Vec<(PubKey, Option<[u8; 32]>)>,
+    pub bootstraps: Vec<PubKey>,
+}
 
 impl SiteV0 {
     pub fn get_individual_user_priv_key(&self) -> Option<PrivKey> {
@@ -23,9 +49,18 @@ impl SiteV0 {
         }
     }
 
-    pub fn create_personal(
+    fn site_store_to_store_repo(site_store: &SiteStore) -> StoreRepo {
+        StoreRepo::V0(match site_store.store_type {
+            SiteStoreType::Public => StoreRepoV0::PublicStore(site_store.id),
+            SiteStoreType::Protected => StoreRepoV0::ProtectedStore(site_store.id),
+            SiteStoreType::Private => StoreRepoV0::PrivateStore(site_store.id),
+        })
+    }
+
+    fn create_individual_(
         user_priv_key: PrivKey,
-        private_store_read_cap: ReadCap,
+        verifier: &mut Verifier,
+        site_name: SiteName,
     ) -> Result<Self, NgError> {
         let site_pubkey = user_priv_key.to_pub();
 
@@ -50,10 +85,31 @@ impl SiteV0 {
             store_type: SiteStoreType::Private,
         };
 
+        let public_store = Self::site_store_to_store_repo(&public);
+        let protected_store = Self::site_store_to_store_repo(&protected);
+        let private_store = Self::site_store_to_store_repo(&private);
+
+        verifier.reserve_more(18)?;
+
+        let public_repo =
+            verifier.new_store_default(&site_pubkey, &user_priv_key, &public_store, false)?;
+
+        let protected_repo =
+            verifier.new_store_default(&site_pubkey, &user_priv_key, &protected_store, false)?;
+
+        let private_repo =
+            verifier.new_store_default(&site_pubkey, &user_priv_key, &private_store, true)?;
+
+        // TODO: create user branch
+        // TODO: add the 2 commits in user branch about StoreUpdate of public and protected stores.
+
         Ok(Self {
-            site_type: SiteType::Individual((user_priv_key, private_store_read_cap)),
+            site_type: SiteType::Individual((
+                user_priv_key,
+                private_repo.read_cap.to_owned().unwrap(),
+            )),
             id: site_pubkey,
-            name: SiteName::Personal,
+            name: site_name,
             public,
             protected,
             private,
@@ -65,41 +121,16 @@ impl SiteV0 {
     pub fn create_individual(
         name: String,
         user_priv_key: PrivKey,
-        private_store_read_cap: ReadCap,
+        verifier: &mut Verifier,
     ) -> Result<Self, NgError> {
-        let site_pubkey = user_priv_key.to_pub();
-
-        let (public_store_privkey, public_store_pubkey) = generate_keypair();
-
-        let (protected_store_privkey, protected_store_pubkey) = generate_keypair();
-
-        let (private_store_privkey, private_store_pubkey) = generate_keypair();
-
-        let public = SiteStore {
-            id: public_store_pubkey,
-            store_type: SiteStoreType::Public,
-        };
-
-        let protected = SiteStore {
-            id: protected_store_pubkey,
-            store_type: SiteStoreType::Protected,
-        };
-
-        let private = SiteStore {
-            id: private_store_pubkey,
-            store_type: SiteStoreType::Private,
-        };
+        Self::create_individual_(user_priv_key, verifier, SiteName::Name(name))
+    }
 
-        Ok(Self {
-            site_type: SiteType::Individual((user_priv_key, private_store_read_cap)),
-            id: site_pubkey,
-            name: SiteName::Name(name),
-            public,
-            protected,
-            private,
-            cores: vec![],
-            bootstraps: vec![],
-        })
+    pub fn create_personal(
+        user_priv_key: PrivKey,
+        verifier: &mut Verifier,
+    ) -> Result<Self, NgError> {
+        Self::create_individual_(user_priv_key, verifier, SiteName::Personal)
     }
 
     pub fn create_org(name: String) -> Result<Self, NgError> {
diff --git a/ng-verifier/src/types.rs b/ng-verifier/src/types.rs
index cf1d7c7..6684d12 100644
--- a/ng-verifier/src/types.rs
+++ b/ng-verifier/src/types.rs
@@ -36,7 +36,22 @@ use serde::{Deserialize, Serialize};
 use web_time::SystemTime;
 //use yrs::{StateVector, Update};
 
-#[derive(Debug, Clone)]
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub enum SessionPeerLastSeq {
+    V0(u64),
+    V1((u64, Sig)),
+}
+
+impl SessionPeerLastSeq {
+    pub fn ser(&self) -> Result<Vec<u8>, NgError> {
+        Ok(serde_bare::to_vec(self)?)
+    }
+    pub fn deser(ser: &[u8]) -> Result<Self, NgError> {
+        Ok(serde_bare::from_slice(ser).map_err(|_| NgError::SerializationError)?)
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
 pub enum VerifierType {
     /// nothing will be saved on disk during the session
     Memory,
@@ -59,7 +74,7 @@ impl VerifierType {
     }
 }
 
-//type LastSeqFn = fn(PubKey, u16) -> Result<u64, NgError>;
+//type LastSeqFn = fn(peer_id: PubKey, qty: u16) -> Result<u64, NgError>;
 pub type LastSeqFn = dyn Fn(PubKey, u16) -> Result<u64, NgError> + 'static + Sync + Send;
 
 // peer_id: PubKey, seq_num:u64, event_ser: vec<u8>,
@@ -96,6 +111,15 @@ pub enum VerifierConfigType {
     WebRocksDb,
 }
 
+impl VerifierConfigType {
+    pub(crate) fn should_load_last_seq_num(&self) -> bool {
+        match self {
+            Self::JsSaveSession(_) | Self::RocksDb(_) => true,
+            _ => false,
+        }
+    }
+}
+
 #[derive(Debug)]
 pub struct VerifierConfig {
     pub config_type: VerifierConfigType,
@@ -104,7 +128,8 @@ pub struct VerifierConfig {
     /// not used for Memory
     pub peer_priv_key: PrivKey,
     pub user_priv_key: PrivKey,
-    pub private_store_read_cap: ObjectRef,
+    pub private_store_read_cap: Option<ObjectRef>,
+    pub private_store_id: Option<RepoId>,
 }
 
 pub type CancelFn = Box<dyn FnOnce()>;
diff --git a/ng-verifier/src/verifier.rs b/ng-verifier/src/verifier.rs
index 0e7a47b..d04c513 100644
--- a/ng-verifier/src/verifier.rs
+++ b/ng-verifier/src/verifier.rs
@@ -21,6 +21,9 @@ use ng_repo::{
     types::*,
     utils::{generate_keypair, sign},
 };
+use std::cmp::max;
+use std::fs::{create_dir_all, read, write, File, OpenOptions};
+use std::io::Write;
 
 use core::fmt;
 //use oxigraph::io::{RdfFormat, RdfParser, RdfSerializer};
@@ -55,6 +58,8 @@ pub struct Verifier {
     last_reservation: SystemTime,
     stores: HashMap<OverlayId, Arc<Store>>,
     repos: HashMap<RepoId, Repo>,
+    /// only used for InMemory type, to store the outbox
+    in_memory_outbox: Vec<Event>,
 }
 
 impl fmt::Debug for Verifier {
@@ -65,7 +70,8 @@ impl fmt::Debug for Verifier {
 }
 
 impl Verifier {
-    #[cfg(test)]
+    #[allow(deprecated)]
+    #[cfg(any(test, feature = "testing"))]
     pub fn new_dummy() -> Self {
         use ng_repo::block_storage::HashMapBlockStorage;
         let (peer_priv_key, peer_id) = generate_keypair();
@@ -77,7 +83,8 @@ impl Verifier {
                 user_master_key: [0; 32],
                 peer_priv_key,
                 user_priv_key: PrivKey::random_ed(),
-                private_store_read_cap: ObjectRef::nil(),
+                private_store_read_cap: None,
+                private_store_id: None,
             },
             connected_server_id: None,
             graph_dataset: None,
@@ -86,35 +93,105 @@ impl Verifier {
             last_seq_num: 0,
             peer_id,
             max_reserved_seq_num: 1,
-            last_reservation: SystemTime::now(),
+            last_reservation: SystemTime::UNIX_EPOCH,
             stores: HashMap::new(),
             repos: HashMap::new(),
+            in_memory_outbox: vec![],
         }
     }
 
-    pub fn get_store(&mut self, store_repo: &StoreRepo) -> Arc<Store> {
+    pub fn get_store_mut(&mut self, store_repo: &StoreRepo) -> Arc<Store> {
         let overlay_id = store_repo.overlay_id_for_storage_purpose();
         let store = self.stores.entry(overlay_id).or_insert_with(|| {
             // FIXME: get store_readcap from user storage
             let store_readcap = ReadCap::nil();
+            let store_overlay_branch_readcap = ReadCap::nil();
             let store = Store::new(
                 *store_repo,
                 store_readcap,
+                store_overlay_branch_readcap,
                 Arc::clone(
                     &self
                         .block_storage
                         .as_ref()
                         .ok_or(core::fmt::Error)
-                        .expect("get_store cannot be called on Remote Verifier"),
+                        .expect("get_store_mut cannot be called on Remote Verifier"),
                 ),
             );
-            //self.stores.insert(overlay_id, store);
-            //let store = self.stores.entry(overlay_id).or_insert(store);
             Arc::new(store)
         });
         Arc::clone(store)
     }
 
+    pub fn complete_site_store(
+        &mut self,
+        store_repo: &StoreRepo,
+        mut repo: Repo,
+        //read_cap: &ReadCap,
+        //overlay_read_cap: Option<&ReadCap>,
+    ) -> Result<Repo, NgError> {
+        let read_cap = repo.read_cap.to_owned().unwrap();
+        let overlay_read_cap = repo.overlay_branch_read_cap().cloned();
+
+        let overlay_id = store_repo.overlay_id_for_storage_purpose();
+        let store = self
+            .stores
+            .remove(&overlay_id)
+            .ok_or(NgError::StoreNotFound)?;
+        // let mut repo = self
+        //     .repos
+        //     .remove(store_repo.repo_id())
+        //     .ok_or(NgError::RepoNotFound)?;
+        // log_info!(
+        //     "{}",
+        //     Arc::<ng_repo::store::Store>::strong_count(&repo.store)
+        // );
+        drop(repo.store);
+        //log_info!("{}", Arc::<ng_repo::store::Store>::strong_count(&store));
+        let mut mut_store = Arc::<ng_repo::store::Store>::into_inner(store).unwrap();
+        mut_store.set_read_caps(read_cap, overlay_read_cap);
+        let new_store = Arc::new(mut_store);
+        let _ = self.stores.insert(overlay_id, Arc::clone(&new_store));
+        repo.store = new_store;
+        //let _ = self.repos.insert(*store_repo.repo_id(), repo);
+        Ok(repo)
+    }
+
+    pub fn get_store(&self, store_repo: &StoreRepo) -> Result<Arc<Store>, NgError> {
+        let overlay_id = store_repo.overlay_id_for_storage_purpose();
+        let store = self.stores.get(&overlay_id).ok_or(NgError::StoreNotFound)?;
+        Ok(Arc::clone(store))
+    }
+
+    pub fn get_repo_mut(
+        &mut self,
+        id: RepoId,
+        store_repo: &StoreRepo,
+    ) -> Result<&mut Repo, NgError> {
+        let store = self.get_store(store_repo);
+        let repo_ref = self.repos.get_mut(&id).ok_or(NgError::RepoNotFound);
+        // .or_insert_with(|| {
+        //     // load from storage
+        //     Repo {
+        //         id,
+        //         repo_def: Repository::new(&PubKey::nil(), &vec![]),
+        //         read_cap: None,
+        //         write_cap: None,
+        //         signer: None,
+        //         members: HashMap::new(),
+        //         branches: HashMap::new(),
+        //         store,
+        //     }
+        // });
+        repo_ref
+    }
+
+    pub fn get_repo(&self, id: RepoId, store_repo: &StoreRepo) -> Result<&Repo, NgError> {
+        //let store = self.get_store(store_repo);
+        let repo_ref = self.repos.get(&id).ok_or(NgError::RepoNotFound);
+        repo_ref
+    }
+
     pub fn add_store(&mut self, store: Arc<Store>) {
         let overlay_id = store.get_store_repo().overlay_id_for_storage_purpose();
         if self.stores.contains_key(&overlay_id) {
@@ -131,12 +208,13 @@ impl Verifier {
         additional_blocks: &Vec<BlockId>,
         //topic_id: TopicId,
         //topic_priv_key: &BranchWriteCapSecret,
-        store: &Store, // store could be omitted and a store repo ID would be given instead.
-    ) -> Result<Event, NgError> {
+        repo_id: RepoId,
+        store_repo: &StoreRepo,
+    ) -> Result<(), NgError> {
         if self.last_seq_num + 1 >= self.max_reserved_seq_num {
             self.reserve_more(1)?;
         }
-        self.new_event_(commit, additional_blocks, store)
+        self.new_event_(commit, additional_blocks, repo_id, store_repo)
     }
 
     fn new_event_(
@@ -147,67 +225,187 @@ impl Verifier {
         additional_blocks: &Vec<BlockId>,
         //topic_id: TopicId,
         //topic_priv_key: &BranchWriteCapSecret,
-        store: &Store, // store could be omitted and a store repo ID would be given instead.
-    ) -> Result<Event, NgError> {
-        let topic_id = TopicId::nil(); // should be fetched from user storage, based on the Commit.branch
-        let topic_priv_key = BranchWriteCapSecret::nil(); // should be fetched from user storage, based on repoId found in user storage (search by branchId)
+        // store: &Store, // store could be omitted and a store repo ID would be given instead.
+        repo_id: RepoId,
+        store_repo: &StoreRepo,
+    ) -> Result<(), NgError> {
+        //let topic_id = TopicId::nil(); // should be fetched from user storage, based on the Commit.branch
+        //let topic_priv_key = BranchWriteCapSecret::nil(); // should be fetched from user storage, based on repoId found in user storage (search by branchId)
+        //self.get_store(store_repo)
+        let publisher = self.config.peer_priv_key.clone();
+        self.last_seq_num += 1;
+        let seq_num = self.last_seq_num;
+        let repo = self.get_repo(repo_id, store_repo)?;
+
+        let event = Event::new(&publisher, seq_num, commit, additional_blocks, repo)?;
+        self.send_or_save_event_to_outbox(event)?;
+        Ok(())
+    }
+
+    fn new_event_with_repo_(
+        &mut self,
+        //publisher: &PrivKey,
+        //seq: &mut u64,
+        commit: &Commit,
+        additional_blocks: &Vec<BlockId>,
+        //topic_id: TopicId,
+        //topic_priv_key: &BranchWriteCapSecret,
+        // store: &Store, // store could be omitted and a store repo ID would be given instead.
+        repo: &Repo,
+    ) -> Result<(), NgError> {
+        //let topic_id = TopicId::nil(); // should be fetched from user storage, based on the Commit.branch
+        //let topic_priv_key = BranchWriteCapSecret::nil(); // should be fetched from user storage, based on repoId found in user storage (search by branchId)
+        //self.get_store(store_repo)
+        let publisher = self.config.peer_priv_key.clone();
         self.last_seq_num += 1;
-        Event::new(
-            &self.config.peer_priv_key,
-            self.last_seq_num,
-            commit,
-            additional_blocks,
-            topic_id,
-            &topic_priv_key,
-            store,
-        )
+        let seq_num = self.last_seq_num;
+
+        let event = Event::new(&publisher, seq_num, commit, additional_blocks, repo)?;
+        self.send_or_save_event_to_outbox(event)?;
+        Ok(())
     }
 
     pub(crate) fn last_seq_number(&mut self) -> Result<u64, NgError> {
-        if self.last_seq_num + 1 >= self.max_reserved_seq_num {
+        if self.available_seq_nums() <= 1 {
             self.reserve_more(1)?;
         }
         self.last_seq_num += 1;
         Ok(self.last_seq_num)
     }
 
+    pub(crate) fn new_events_with_repo(
+        &mut self,
+        events: Vec<(Commit, Vec<Digest>)>,
+        repo: &Repo,
+    ) -> Result<(), NgError> {
+        let missing_count = events.len() as i64 - self.available_seq_nums() as i64;
+        // this is reducing the capacity of reserver_seq_num by half (cast from u64 to i64)
+        // but we will never reach situation where so many seq_nums are reserved, neither such a big list of events to process
+        if missing_count >= 0 {
+            self.reserve_more(missing_count as u64 + 1)?;
+        }
+        for event in events {
+            self.new_event_with_repo_(&event.0, &event.1, repo)?;
+        }
+        Ok(())
+    }
+
     pub(crate) fn new_events(
         &mut self,
         events: Vec<(Commit, Vec<Digest>)>,
-        store: &Store,
-    ) -> Result<Vec<Event>, NgError> {
+        repo_id: RepoId,
+        store_repo: &StoreRepo,
+    ) -> Result<(), NgError> {
         let missing_count = events.len() as i64 - self.available_seq_nums() as i64;
         // this is reducing the capacity of reserver_seq_num by half (cast from u64 to i64)
         // but we will never reach situation where so many seq_nums are reserved, neither such a big list of events to process
         if missing_count >= 0 {
             self.reserve_more(missing_count as u64 + 1)?;
         }
-        let mut res = vec![];
         for event in events {
-            let event = self.new_event_(&event.0, &event.1, store)?;
-            res.push(event);
+            self.new_event_(&event.0, &event.1, repo_id.clone(), store_repo)?;
         }
-        Ok(res)
+        Ok(())
     }
 
     fn available_seq_nums(&self) -> u64 {
         self.max_reserved_seq_num - self.last_seq_num
     }
 
-    fn reserve_more(&mut self, at_least: u64) -> Result<(), NgError> {
-        // the qty should be calculated based on the last_reservation. the closer to now, the higher the qty.
+    pub(crate) fn reserve_more(&mut self, at_least: u64) -> Result<(), NgError> {
+        // the qty is calculated based on the last_reservation. the closer to now, the higher the qty.
         // below 1 sec, => 100
         // below 5 sec, => 10
-        // below 10 sec => 1
-        self.take_some_peer_last_seq_numbers(10)
+        // above 5 sec => 1
+        let qty = match self.last_reservation.elapsed().unwrap().as_secs() {
+            0..=1 => 100u16,
+            2..=5 => 10u16,
+            6.. => 1u16,
+        };
+        self.take_some_peer_last_seq_numbers(max(at_least as u16, qty))
     }
 
-    fn take_some_peer_last_seq_numbers(&mut self, qty: u16) -> Result<(), NgError> {
-        // TODO the magic
+    fn send_or_save_event_to_outbox<'a>(&'a mut self, event: Event) -> Result<(), NgError> {
+        log_debug!("========== EVENT {:03}: {}", event.seq_num(), event);
+
+        if self.connected_server_id.is_some() {
+            // send the events to the server already
+        } else {
+            match &self.config.config_type {
+                VerifierConfigType::JsSaveSession(js) => {
+                    (js.outbox_write_function)(
+                        self.peer_id,
+                        event.seq_num(),
+                        serde_bare::to_vec(&event)?,
+                    )?;
+                }
+                VerifierConfigType::RocksDb(path) => {}
+                VerifierConfigType::Memory => {
+                    self.in_memory_outbox.push(event);
+                }
+                _ => unimplemented!(),
+            }
+        }
+        Ok(())
+    }
 
-        self.max_reserved_seq_num += qty as u64;
+    fn take_some_peer_last_seq_numbers(&mut self, qty: u16) -> Result<(), NgError> {
+        match &self.config.config_type {
+            VerifierConfigType::JsSaveSession(js) => {
+                let res = (js.last_seq_function)(self.peer_id, qty)?;
+                self.max_reserved_seq_num = res + qty as u64;
+            }
+            VerifierConfigType::RocksDb(path) => {
+                let mut path = path.clone();
+                std::fs::create_dir_all(path.clone()).unwrap();
+                path.push(format!("lastseq{}", self.peer_id.to_string()));
+                log_debug!("last_seq path {}", path.display());
+
+                let file = read(path.clone());
+                let (mut file_save, val) = match file {
+                    Ok(ser) => {
+                        let old_val = if ser.len() > 0 {
+                            match SessionPeerLastSeq::deser(&ser)? {
+                                SessionPeerLastSeq::V0(v) => v,
+                                _ => unimplemented!(),
+                            }
+                        } else {
+                            0
+                        };
+                        (
+                            OpenOptions::new()
+                                .write(true)
+                                .open(path)
+                                .map_err(|_| NgError::SerializationError)?,
+                            old_val,
+                        )
+                    }
+                    Err(_) => (
+                        File::create(path).map_err(|_| NgError::SerializationError)?,
+                        0,
+                    ),
+                };
+                if qty > 0 {
+                    let new_val = val + qty as u64;
+                    let spls = SessionPeerLastSeq::V0(new_val);
+                    let ser = spls.ser()?;
+                    file_save
+                        .write_all(&ser)
+                        .map_err(|_| NgError::SerializationError)?;
+
+                    file_save
+                        .sync_data()
+                        .map_err(|_| NgError::SerializationError)?;
+                }
+                self.max_reserved_seq_num = val + qty as u64;
+            }
+            _ => {
+                self.max_reserved_seq_num += qty as u64;
+            }
+        }
+        self.last_reservation = SystemTime::now();
         log_debug!(
-            "reserving more seq_nums {qty}. now at {}",
+            "reserving more {qty} seq_nums. now at {}",
             self.max_reserved_seq_num
         );
         Ok(())
@@ -224,21 +422,33 @@ impl Verifier {
                 Some(block_storage),
             ),
             #[cfg(not(target_family = "wasm"))]
-            VerifierConfigType::RocksDb(path) => (
-                // FIXME BIG TIME: we are reusing the same encryption key here.
-                // this is very temporary, until we remove the code in oxi_rocksdb of oxigraph,
-                // and have oxigraph use directly the UserStorage
-                Some(oxigraph::store::Store::open_with_key(path, config.user_master_key).unwrap()),
-                Some(
-                    Box::new(RocksDbUserStorage::open(path, config.user_master_key)?)
-                        as Box<dyn UserStorage>,
-                ),
-                Some(block_storage),
-            ),
+            VerifierConfigType::RocksDb(path) => {
+                let mut path_oxi = path.clone();
+                path_oxi.push("graph");
+                create_dir_all(path_oxi.clone()).unwrap();
+                let mut path_user = path.clone();
+                path_user.push("user");
+                create_dir_all(path_user.clone()).unwrap();
+                (
+                    // FIXME BIG TIME: we are reusing the same encryption key here.
+                    // this is very temporary, until we remove the code in oxi_rocksdb of oxigraph,
+                    // and have oxigraph use directly the UserStorage
+                    Some(
+                        oxigraph::store::Store::open_with_key(path_oxi, config.user_master_key)
+                            .unwrap(),
+                    ),
+                    Some(Box::new(RocksDbUserStorage::open(
+                        &path_user,
+                        config.user_master_key,
+                    )?) as Box<dyn UserStorage>),
+                    Some(block_storage),
+                )
+            }
             VerifierConfigType::Remote(_) => (None, None, None),
             _ => unimplemented!(), // can be WebRocksDb or RocksDb on wasm platforms
         };
         let peer_id = config.peer_priv_key.to_pub();
+        let should_load_last_seq_num = config.config_type.should_load_last_seq_num();
         let mut verif = Verifier {
             config,
             connected_server_id: None,
@@ -246,13 +456,18 @@ impl Verifier {
             user_storage: user,
             block_storage: block,
             peer_id,
-            last_reservation: SystemTime::now(),
+            last_reservation: SystemTime::UNIX_EPOCH, // this is to avoid reserving 100 seq_nums at every start of a new session
             max_reserved_seq_num: 0,
             last_seq_num: 0,
             stores: HashMap::new(),
             repos: HashMap::new(),
+            in_memory_outbox: vec![],
         };
-        verif.take_some_peer_last_seq_numbers(1)?;
+        // this is important as it will load the last seq from storage
+        if should_load_last_seq_num {
+            verif.take_some_peer_last_seq_numbers(0)?;
+            verif.last_seq_num = verif.max_reserved_seq_num;
+        }
         Ok(verif)
     }
 
@@ -272,24 +487,66 @@ impl Verifier {
         unimplemented!();
     }
 
+    pub fn new_store_default<'a>(
+        &'a mut self,
+        creator: &UserId,
+        creator_priv_key: &PrivKey,
+        store_repo: &StoreRepo,
+        private: bool,
+    ) -> Result<&'a Repo, NgError> {
+        let repo_write_cap_secret = match private {
+            false => SymKey::random(),
+            true => SymKey::nil(),
+        };
+        let overlay_id = store_repo.overlay_id_for_storage_purpose();
+        let store = self.stores.entry(overlay_id).or_insert_with(|| {
+            let store_readcap = ReadCap::nil();
+            // temporarily set the store_overlay_branch_readcap to an objectRef that has an empty id, and a key = to the repo_write_cap_secret
+            let store_overlay_branch_readcap =
+                ReadCap::from_id_key(ObjectId::nil(), repo_write_cap_secret.clone());
+            let store = Store::new(
+                *store_repo,
+                store_readcap,
+                store_overlay_branch_readcap,
+                Arc::clone(
+                    &self
+                        .block_storage
+                        .as_ref()
+                        .ok_or(core::fmt::Error)
+                        .expect("get_store_mut cannot be called on Remote Verifier"),
+                ),
+            );
+            Arc::new(store)
+        });
+        let (repo, proto_events) = Arc::clone(store).create_repo_default(
+            creator,
+            creator_priv_key,
+            repo_write_cap_secret,
+        )?;
+        self.new_events_with_repo(proto_events, &repo)?;
+        let repo = self.complete_site_store(store_repo, repo)?;
+        let repo_ref = self.repos.entry(repo.id).or_insert(repo);
+        Ok(repo_ref)
+    }
+
     /// returns the Repo and the last seq_num of the peer
     pub fn new_repo_default<'a>(
         &'a mut self,
         creator: &UserId,
         creator_priv_key: &PrivKey,
         store_repo: &StoreRepo,
-    ) -> Result<(&'a Repo, Vec<Event>), NgError> {
-        let store = self.get_store(store_repo);
-        let (repo, proto_events) = store.create_repo_default(creator, creator_priv_key)?;
-
-        let events = self.new_events(proto_events, &repo.store)?;
+    ) -> Result<&'a Repo, NgError> {
+        let store = self.get_store_mut(store_repo);
+        let repo_write_cap_secret = SymKey::random();
+        let (repo, proto_events) =
+            store.create_repo_default(creator, creator_priv_key, repo_write_cap_secret)?;
+        self.new_events_with_repo(proto_events, &repo)?;
         // let mut events = vec![];
         // for event in proto_events {
         //     events.push(self.new_event(&event.0, &event.1, &repo.store)?);
         // }
-
         let repo_ref = self.repos.entry(repo.id).or_insert(repo);
-        Ok((repo_ref, events))
+        Ok(repo_ref)
     }
 }
 #[cfg(test)]
@@ -312,19 +569,12 @@ mod test {
         let mut verifier = Verifier::new_dummy();
         verifier.add_store(store);
 
-        let (repo, events) = verifier
+        let repo = verifier
             .new_repo_default(&creator_pub_key, &creator_priv_key, &store_repo)
             .expect("new_default");
 
         log_debug!("REPO OBJECT {}", repo);
 
-        log_debug!("events:     {}\n", events.len());
-        let mut i = 0;
-        for e in events {
-            log_debug!("========== EVENT {:03}: {}", i, e);
-            i += 1;
-        }
-
-        assert_eq!(verifier.last_seq_number(), Ok(6));
+        assert_eq!(verifier.last_seq_num, 5);
     }
 }
diff --git a/ng-wallet/Cargo.toml b/ng-wallet/Cargo.toml
index 0a6461b..afc99d5 100644
--- a/ng-wallet/Cargo.toml
+++ b/ng-wallet/Cargo.toml
@@ -20,6 +20,7 @@ serde_bytes = "0.11.7"
 serde-big-array = "0.5.1"
 ng-repo = { path = "../ng-repo", version = "0.1.0" }
 ng-net = { path = "../ng-net", version = "0.1.0" }
+ng-verifier = { path = "../ng-verifier", version = "0.1.0" }
 image = "0.24.6"
 getrandom = { version = "0.1.1", features = ["wasm-bindgen"] }
 rand =  { version = "0.7", features = ["getrandom"] }
@@ -35,4 +36,9 @@ web-time = "0.2.0"
 lazy_static = "1.4.0"
 zeroize = { version = "1.6.0", features = ["zeroize_derive"] }
 crypto_box = { version = "0.8.2", features = ["seal"] }
-blake3 = "1.3.1"
\ No newline at end of file
+blake3 = "1.3.1"
+
+
+[dev-dependencies]
+ng-repo = { path = "../ng-repo", version = "0.1.0", features = ["testing"] }
+ng-verifier = { path = "../ng-verifier", version = "0.1.0", features = ["testing"] }
\ No newline at end of file
diff --git a/ng-wallet/src/lib.rs b/ng-wallet/src/lib.rs
index 3e7fd5c..97d2376 100644
--- a/ng-wallet/src/lib.rs
+++ b/ng-wallet/src/lib.rs
@@ -19,6 +19,7 @@ pub mod bip39;
 
 pub mod emojis;
 
+use ng_verifier::{site::SiteV0, verifier::Verifier};
 use rand::distributions::{Distribution, Uniform};
 use std::{collections::HashMap, io::Cursor, sync::Arc};
 
@@ -46,26 +47,31 @@ impl Wallet {
     pub fn id(&self) -> WalletId {
         match self {
             Wallet::V0(v0) => v0.id,
+            _ => unimplemented!(),
         }
     }
     pub fn content_as_bytes(&self) -> Vec<u8> {
         match self {
             Wallet::V0(v0) => serde_bare::to_vec(&v0.content).unwrap(),
+            _ => unimplemented!(),
         }
     }
     pub fn sig(&self) -> Sig {
         match self {
             Wallet::V0(v0) => v0.sig,
+            _ => unimplemented!(),
         }
     }
     pub fn pazzle_length(&self) -> u8 {
         match self {
             Wallet::V0(v0) => v0.content.pazzle_length,
+            _ => unimplemented!(),
         }
     }
     pub fn name(&self) -> String {
         match self {
             Wallet::V0(v0) => base64_url::encode(&v0.id.slice()),
+            _ => unimplemented!(),
         }
     }
 
@@ -90,6 +96,7 @@ impl Wallet {
 
         let mut wallet_content = match self {
             Wallet::V0(v0) => v0.content.clone(),
+            _ => unimplemented!(),
         };
 
         wallet_content.timestamp = timestamp;
@@ -347,6 +354,7 @@ pub fn open_wallet_with_pazzle(
                 v0.id,
             )?))
         }
+        _ => unimplemented!(),
     }
 }
 
@@ -385,6 +393,7 @@ pub fn open_wallet_with_mnemonic(
                 v0.id,
             )?))
         }
+        _ => unimplemented!(),
     }
 }
 
@@ -447,9 +456,9 @@ pub fn gen_shuffle_for_pin() -> Vec<u8> {
 
 /// creates a Wallet from a pin, a security text and image (with option to send the bootstrap and wallet to nextgraph.one)
 /// and returns the Wallet, the pazzle and the mnemonic
-pub fn create_wallet_v0(mut params: CreateWalletV0) -> Result<CreateWalletResultV0, NgWalletError> {
-    let creating_pazzle = Instant::now();
-
+pub fn create_wallet_first_step_v0(
+    params: CreateWalletV0,
+) -> Result<CreateWalletIntermediaryV0, NgWalletError> {
     // pazzle_length can only be 9, 12, or 15
     if params.pazzle_length != 9
         //&& params.pazzle_length != 12
@@ -533,11 +542,53 @@ pub fn create_wallet_v0(mut params: CreateWalletV0) -> Result<CreateWalletResult
     let (wallet_privkey, wallet_id) = generate_keypair();
 
     // TODO: should be derived from  OwnershipProof
-    let user_priv_key = PrivKey::random_ed();
+    let user_privkey = PrivKey::random_ed();
+
+    let user = user_privkey.to_pub();
+
+    let client = ClientV0::new_with_auto_open(user);
+
+    let intermediary = CreateWalletIntermediaryV0 {
+        wallet_privkey,
+        wallet_name: base64_url::encode(&wallet_id.slice()),
+        client,
+        user_privkey,
+        in_memory: !params.local_save,
+        security_img: cursor.into_inner(),
+        security_txt: new_string,
+        pazzle_length: params.pazzle_length,
+        pin: params.pin,
+        send_bootstrap: params.send_bootstrap,
+        send_wallet: params.send_wallet,
+        result_with_wallet_file: params.result_with_wallet_file,
+        core_bootstrap: params.core_bootstrap.clone(),
+        core_registration: params.core_registration,
+        additional_bootstrap: params.additional_bootstrap.clone(),
+    };
+    Ok(intermediary)
+}
+
+pub fn create_wallet_second_step_v0(
+    mut params: CreateWalletIntermediaryV0,
+    verifier: &mut Verifier,
+) -> Result<
+    (
+        CreateWalletResultV0,
+        SiteV0,
+        HashMap<String, Vec<BrokerInfoV0>>,
+    ),
+    NgWalletError,
+> {
+    let creating_pazzle = Instant::now();
+
+    let mut site = SiteV0::create_personal(params.user_privkey.clone(), verifier).map_err(|e| {
+        log_err!("{e}");
+        NgWalletError::InternalError
+    })?;
 
-    // TODO: private_store_read_cap
-    let site = SiteV0::create_personal(user_priv_key.clone(), BlockRef::nil())
-        .map_err(|e| NgWalletError::InternalError)?;
+    let user = params.user_privkey.to_pub();
+
+    let wallet_id = params.wallet_privkey.to_pub();
 
     let mut ran = thread_rng();
 
@@ -565,17 +616,12 @@ pub fn create_wallet_v0(mut params: CreateWalletV0) -> Result<CreateWalletResult
     //.ok_or(NgWalletError::InternalError)?
     //.clone(),
 
-    let user = user_priv_key.to_pub();
-
-    // Creating a new client
-    let client = ClientV0::new_with_auto_open(user);
-
     let create_op = WalletOpCreateV0 {
-        wallet_privkey: wallet_privkey.clone(),
+        wallet_privkey: params.wallet_privkey.clone(),
         // pazzle: pazzle.clone(),
         // mnemonic,
         // pin: params.pin,
-        personal_site: site,
+        personal_site: site.clone(),
         save_to_ng_one: if params.send_wallet {
             SaveToNGOne::Wallet
         } else if params.send_bootstrap {
@@ -599,15 +645,20 @@ pub fn create_wallet_v0(mut params: CreateWalletV0) -> Result<CreateWalletResult
     // #[zeroize(skip)]
     // pub additional_bootstrap: Option<BootstrapContentV0>,
 
+    let mut brokers: HashMap<String, Vec<BrokerInfoV0>> = HashMap::new();
+
+    let core_pubkey = params
+        .core_bootstrap
+        .get_first_peer_id()
+        .ok_or(NgWalletError::InvalidBootstrap)?;
     wallet_log.add(WalletOperation::AddSiteCoreV0((
         user,
-        params
-            .core_bootstrap
-            .get_first_peer_id()
-            .ok_or(NgWalletError::InvalidBootstrap)?,
+        core_pubkey,
         params.core_registration,
     )));
 
+    site.cores.push((core_pubkey, params.core_registration));
+
     if let Some(additional) = &params.additional_bootstrap {
         params.core_bootstrap.merge(additional);
     }
@@ -615,6 +666,17 @@ pub fn create_wallet_v0(mut params: CreateWalletV0) -> Result<CreateWalletResult
     for server in &params.core_bootstrap.servers {
         wallet_log.add(WalletOperation::AddBrokerServerV0(server.clone()));
         wallet_log.add(WalletOperation::AddSiteBootstrapV0((user, server.peer_id)));
+        site.bootstraps.push(server.peer_id);
+
+        let broker = BrokerInfoV0::ServerV0(server.clone());
+        let key = broker.get_id().to_string();
+        let mut list = brokers.get_mut(&key);
+        if list.is_none() {
+            let new_list = vec![];
+            brokers.insert(key.clone(), new_list);
+            list = brokers.get_mut(&key);
+        }
+        list.unwrap().push(broker);
     }
 
     let mut master_key = [0u8; 32];
@@ -664,8 +726,8 @@ pub fn create_wallet_v0(mut params: CreateWalletV0) -> Result<CreateWalletResult
     master_key.zeroize();
 
     let wallet_content = WalletContentV0 {
-        security_img: cursor.into_inner(),
-        security_txt: new_string,
+        security_img: params.security_img.clone(),
+        security_txt: params.security_txt.clone(),
         pazzle_length: params.pazzle_length,
         salt_pazzle,
         salt_mnemonic,
@@ -680,7 +742,7 @@ pub fn create_wallet_v0(mut params: CreateWalletV0) -> Result<CreateWalletResult
 
     let ser_wallet = serde_bare::to_vec(&wallet_content).unwrap();
 
-    let sig = sign(&wallet_privkey, &wallet_id, &ser_wallet).unwrap();
+    let sig = sign(&params.wallet_privkey, &wallet_id, &ser_wallet).unwrap();
 
     let wallet_v0 = WalletV0 {
         /// ID
@@ -705,22 +767,27 @@ pub fn create_wallet_v0(mut params: CreateWalletV0) -> Result<CreateWalletResult
         "creating of wallet took: {} ms",
         creating_pazzle.elapsed().as_millis()
     );
+
     let wallet = Wallet::V0(wallet_v0);
     let wallet_file = match params.result_with_wallet_file {
         false => vec![],
         true => to_vec(&NgFile::V0(NgFileV0::Wallet(wallet.clone()))).unwrap(),
     };
-    Ok(CreateWalletResultV0 {
-        wallet: wallet,
-        wallet_privkey,
-        wallet_file,
-        pazzle,
-        mnemonic: mnemonic.clone(),
-        wallet_name: base64_url::encode(&wallet_id.slice()),
-        client,
-        user,
-        in_memory: !params.local_save,
-    })
+    Ok((
+        CreateWalletResultV0 {
+            wallet: wallet,
+            wallet_file,
+            pazzle,
+            mnemonic: mnemonic.clone(),
+            wallet_name: params.wallet_name.clone(),
+            client: params.client.clone(),
+            user,
+            in_memory: params.in_memory,
+            session_id: 0,
+        },
+        site,
+        brokers,
+    ))
 }
 
 #[cfg(test)]
@@ -766,7 +833,7 @@ mod test {
 
         let creation = Instant::now();
 
-        let res = create_wallet_v0(CreateWalletV0::new(
+        let res = create_wallet_first_step_v0(CreateWalletV0::new(
             img_buffer,
             "   know     yourself  ".to_string(),
             pin,
@@ -777,7 +844,11 @@ mod test {
             None,
             None,
         ))
-        .expect("create_wallet_v0");
+        .expect("create_wallet_first_step_v0");
+
+        let mut verifier = Verifier::new_dummy();
+        let (res, _, _) =
+            create_wallet_second_step_v0(res, &mut verifier).expect("create_wallet_second_step_v0");
 
         log_debug!(
             "creation of wallet took: {} ms",
diff --git a/ng-wallet/src/types.rs b/ng-wallet/src/types.rs
index 5c65bc4..5d1db05 100644
--- a/ng-wallet/src/types.rs
+++ b/ng-wallet/src/types.rs
@@ -20,6 +20,7 @@ use ng_net::types::*;
 use ng_repo::errors::NgError;
 use ng_repo::types::*;
 use ng_repo::utils::{encrypt_in_place, generate_keypair, now_timestamp, sign};
+use ng_verifier::site::SiteV0;
 
 /// WalletId is a PubKey
 pub type WalletId = PubKey;
@@ -64,21 +65,6 @@ impl Bootstrap {
     }
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
-pub enum SessionPeerLastSeq {
-    V0(u64),
-    V1((u64, Sig)),
-}
-
-impl SessionPeerLastSeq {
-    pub fn ser(&self) -> Result<Vec<u8>, NgError> {
-        Ok(serde_bare::to_vec(self)?)
-    }
-    pub fn deser(ser: &[u8]) -> Result<Self, NgError> {
-        Ok(serde_bare::from_slice(ser).map_err(|_| NgError::SerializationError)?)
-    }
-}
-
 #[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct SessionWalletStorageV0 {
     // string is base64_url encoding of userId(pubkey)
@@ -231,11 +217,11 @@ pub struct LocalWalletStorageV0 {
     pub encrypted_client_storage: Vec<u8>,
 }
 
-impl From<&CreateWalletResultV0> for LocalWalletStorageV0 {
-    fn from(res: &CreateWalletResultV0) -> Self {
+impl From<&CreateWalletIntermediaryV0> for LocalWalletStorageV0 {
+    fn from(res: &CreateWalletIntermediaryV0) -> Self {
         LocalWalletStorageV0 {
             bootstrap: BootstrapContent::V0(BootstrapContentV0::new_empty()),
-            wallet: res.wallet.clone(),
+            wallet: Wallet::TemporarilyEmpty,
             in_memory: res.in_memory,
             client_id: res.client.id,
             client_auto_open: res.client.auto_open.clone(),
@@ -249,6 +235,38 @@ impl From<&CreateWalletResultV0> for LocalWalletStorageV0 {
     }
 }
 
+impl From<&CreateWalletIntermediaryV0> for SensitiveWalletV0 {
+    fn from(res: &CreateWalletIntermediaryV0) -> Self {
+        SensitiveWalletV0 {
+            wallet_privkey: res.wallet_privkey.clone(),
+            wallet_id: res.wallet_name.clone(),
+            save_to_ng_one: if res.send_wallet {
+                SaveToNGOne::Wallet
+            } else if res.send_bootstrap {
+                SaveToNGOne::Bootstrap
+            } else {
+                SaveToNGOne::No
+            },
+            // for now, personal_site is null. will be replaced later
+            personal_site: PubKey::nil(),
+            personal_site_id: "".to_string(),
+            sites: HashMap::new(),
+            brokers: HashMap::new(),
+            overlay_core_overrides: HashMap::new(),
+            third_parties: HashMap::new(),
+            log: None,
+            master_key: None,
+            client: None,
+        }
+    }
+}
+
+impl From<&CreateWalletIntermediaryV0> for SensitiveWallet {
+    fn from(res: &CreateWalletIntermediaryV0) -> SensitiveWallet {
+        SensitiveWallet::V0(res.into())
+    }
+}
+
 impl LocalWalletStorageV0 {
     #[doc(hidden)]
     pub fn new(
@@ -468,11 +486,16 @@ impl SensitiveWallet {
             Self::V0(v0) => v0.client = Some(client),
         }
     }
-    pub fn individual_site(&self, user_id: &UserId) -> Option<&(PrivKey, ReadCap)> {
+    pub fn individual_site(
+        &self,
+        user_id: &UserId,
+    ) -> Option<(PrivKey, Option<ReadCap>, Option<RepoId>)> {
         match self {
             Self::V0(v0) => match v0.sites.get(&user_id.to_string()) {
                 Some(site) => match &site.site_type {
-                    SiteType::Individual(creds) => Some(creds),
+                    SiteType::Individual((user, readcap)) => {
+                        Some((user.clone(), Some(readcap.clone()), Some(site.private.id)))
+                    }
                     _ => None,
                 },
                 None => None,
@@ -498,6 +521,16 @@ impl SensitiveWallet {
             Self::V0(v0) => v0.import(encrypted_wallet, in_memory),
         }
     }
+
+    pub fn complete_with_site_and_brokers(
+        &mut self,
+        site: SiteV0,
+        brokers: HashMap<String, Vec<BrokerInfoV0>>,
+    ) {
+        match self {
+            Self::V0(v0) => v0.complete_with_site_and_brokers(site, brokers),
+        }
+    }
 }
 
 impl SensitiveWalletV0 {
@@ -546,6 +579,19 @@ impl SensitiveWalletV0 {
             .overlay_core_overrides
             .insert(overlay.to_string(), cores.to_vec());
     }
+
+    pub fn complete_with_site_and_brokers(
+        &mut self,
+        site: SiteV0,
+        brokers: HashMap<String, Vec<BrokerInfoV0>>,
+    ) {
+        let personal_site = site.id;
+        let personal_site_id = personal_site.to_string();
+        self.personal_site = personal_site;
+        self.personal_site_id = personal_site_id.clone();
+        self.sites.insert(personal_site_id, site);
+        self.brokers = brokers;
+    }
 }
 
 /// Wallet content Version 0
@@ -1067,6 +1113,7 @@ pub struct WalletV0 {
 #[derive(Clone, Debug, Serialize, Deserialize)]
 pub enum Wallet {
     V0(WalletV0),
+    TemporarilyEmpty,
 }
 
 /// Add Wallet Version 0
@@ -1186,16 +1233,28 @@ impl CreateWalletV0 {
     }
 }
 
+// #[derive(Clone, Zeroize, ZeroizeOnDrop, Debug, Serialize, Deserialize)]
+// pub struct WalletCreationSiteEventsV0 {
+//     store_id: RepoId,
+//     store_read_cap: ReadCap,
+//     topic_id: TopicId,
+//     topic_priv_key: BranchWriteCapSecret,
+//     events: Vec<(Commit, Vec<Digest>)>,
+// }
+
+// #[derive(Clone, Zeroize, ZeroizeOnDrop, Debug, Serialize, Deserialize)]
+// pub struct WalletCreationEventsV0 {}
+
 #[derive(Clone, Zeroize, ZeroizeOnDrop, Debug, Serialize, Deserialize)]
 pub struct CreateWalletResultV0 {
     #[zeroize(skip)]
     /// The encrypted form of the Wallet object that was created.
     /// basically the same as what the file contains.
     pub wallet: Wallet,
-    #[serde(skip)]
-    /// The private key of the Wallet. Used for signing the wallet and other internal purposes.
-    /// it is contained in the opened wallet. No need to save it anywhere.
-    pub wallet_privkey: PrivKey,
+    // #[serde(skip)]
+    // /// The private key of the Wallet. Used for signing the wallet and other internal purposes.
+    // /// it is contained in the opened wallet. No need to save it anywhere.
+    // pub wallet_privkey: PrivKey,
     #[serde(with = "serde_bytes")]
     #[zeroize(skip)]
     /// The binary file that can be saved to disk and given to the user
@@ -1216,6 +1275,53 @@ pub struct CreateWalletResultV0 {
     #[zeroize(skip)]
     /// is this an in_memory wallet that should not be saved to disk by the LocalBroker?
     pub in_memory: bool,
+
+    pub session_id: u8,
+}
+
+impl CreateWalletResultV0 {
+    pub fn personal_identity(&self) -> UserId {
+        self.user
+    }
+}
+
+#[derive(Clone, Zeroize, ZeroizeOnDrop, Debug)]
+pub struct CreateWalletIntermediaryV0 {
+    /// The private key of the Wallet. Used for signing the wallet and other internal purposes.
+    /// it is contained in the opened wallet. No need to save it anywhere.
+    pub wallet_privkey: PrivKey,
+    #[zeroize(skip)]
+    /// a string identifying uniquely the wallet
+    pub wallet_name: String,
+    /// newly created Client that uniquely identifies the device where the wallet has been created.
+    pub client: ClientV0,
+
+    /// User priv key of the "personal identity" of the user
+    pub user_privkey: PrivKey,
+    #[zeroize(skip)]
+    /// is this an in_memory wallet that should not be saved to disk by the LocalBroker?
+    pub in_memory: bool,
+
+    #[zeroize(skip)]
+    pub security_img: Vec<u8>,
+
+    pub security_txt: String,
+
+    pub pazzle_length: u8,
+
+    pub pin: [u8; 4],
+
+    #[zeroize(skip)]
+    pub send_bootstrap: bool,
+    #[zeroize(skip)]
+    pub send_wallet: bool,
+    #[zeroize(skip)]
+    pub result_with_wallet_file: bool,
+    #[zeroize(skip)]
+    pub core_bootstrap: BootstrapContentV0,
+    pub core_registration: Option<[u8; 32]>,
+    #[zeroize(skip)]
+    pub additional_bootstrap: Option<BootstrapContentV0>,
 }
 
 #[derive(Debug, Eq, PartialEq, Clone)]
diff --git a/ngd/src/main.rs b/ngd/src/main.rs
index b199a52..f48943c 100644
--- a/ngd/src/main.rs
+++ b/ngd/src/main.rs
@@ -950,6 +950,7 @@ async fn main_inner() -> Result<(), ()> {
             overlays_config.forward = vec![BrokerServerV0 {
                 server_type,
                 can_verify: false,
+                can_forward: false,
                 peer_id,
             }];
         }