diff --git a/pallets/distance/src/lib.rs b/pallets/distance/src/lib.rs
index 23277e89b1bda102ccab6ba2b94d2caac5c42d7b..4acdb34ef6a194534a3432422690780bb08ce1dd 100644
--- a/pallets/distance/src/lib.rs
+++ b/pallets/distance/src/lib.rs
@@ -190,6 +190,8 @@ pub mod pallet {
         TooManyEvaluators,
         /// Evaluation result has a wrong length.
         WrongResultLength,
+        /// Targeted distance evaluation request is only possible for an unvalidated identity
+        DistanceRequestNotAllowed,
     }
 
     #[pallet::hooks]
@@ -254,10 +256,10 @@ pub mod pallet {
             let target_idty =
                 pallet_identity::Identities::<T>::get(target).ok_or(Error::<T>::NoIdentity)?;
 
-            // check that target is unconfirmed
+            // check that target is unvalidated
             ensure!(
-                target_idty.status == pallet_identity::IdtyStatus::Unconfirmed,
-                Error::<T>::NoIdentity
+                target_idty.status == pallet_identity::IdtyStatus::Unvalidated,
+                Error::<T>::DistanceRequestNotAllowed
             );
 
             // check that no distance status is already there
@@ -488,29 +490,45 @@ pub mod pallet {
             > = Pallet::<T>::take_current_pool(index);
             for (idty, median_acc) in current_pool.evaluations.into_iter() {
                 if let Some(median_result) = median_acc.get_median() {
+                    // get result of the comutation
                     let median = match median_result {
                         MedianResult::One(m) => m,
                         MedianResult::Two(m1, m2) => m1 + (m2 - m1) / 2, // Avoid overflow (since max is 1)
                     };
+                    // flag to capture distance status
+                    let is_distance_status_valid = median >= T::MinAccessibleReferees::get();
+                    // mutate the distance status accordingly
                     IdentityDistanceStatus::<T>::mutate(idty, |entry| {
                         if let Some((account_id, status)) = entry.as_mut() {
-                            if median >= T::MinAccessibleReferees::get() {
+                            // result is ok
+                            if is_distance_status_valid {
+                                // unreserve price
                                 T::Currency::unreserve(
                                     account_id,
                                     <T as Config>::EvaluationPrice::get(),
                                 );
+                                // update distance status
                                 *status = DistanceStatus::Valid;
-                            } else {
+                            }
+                            // result is ko
+                            else {
+                                // slash requester
                                 T::Currency::slash_reserved(
                                     account_id,
                                     <T as Config>::EvaluationPrice::get(),
                                 );
+                                // update distance status
                                 *status = DistanceStatus::Invalid;
                             }
-                        }
+                        } // each entry should be Some((_, DistanceStatus::Pending))
                     });
+                    // consequences of valid status
+                    if is_distance_status_valid {
+                        T::OnValidDistanceStatus::on_valid_distance_status(idty);
+                    }
                 } else if let Some((account_id, _status)) = IdentityDistanceStatus::<T>::take(idty)
                 {
+                    // when no result is published, all funds are unreserved
                     <T as Config>::Currency::unreserve(
                         &account_id,
                         <T as Config>::EvaluationPrice::get(),
diff --git a/pallets/duniter-wot/src/lib.rs b/pallets/duniter-wot/src/lib.rs
index 04a02e808c373dc24b1c407abac3dc15da46297a..a33bec74339e7d07cd80ccd27d3101246535e024 100644
--- a/pallets/duniter-wot/src/lib.rs
+++ b/pallets/duniter-wot/src/lib.rs
@@ -367,7 +367,14 @@ impl<T: Config<I> + pallet_distance::Config, I: 'static>
                 IdtyStatus::Unconfirmed => { /* should not happen */ }
                 IdtyStatus::Unvalidated | IdtyStatus::NotMember => {
                     // ok to fail
-                    let _ = pallet_membership::Pallet::<T, I>::try_claim_membership(idty_index);
+                    let r = pallet_membership::Pallet::<T, I>::try_claim_membership(idty_index);
+                    sp_std::if_std! {
+                        if let Err(e) = r {
+                            print!("failed to claim identity when distance status was ok: ");
+                            println!("{:?}", idty_index);
+                            println!("reason: {:?}", e);
+                        }
+                    }
                 }
                 IdtyStatus::Member => {
                     // ok to fail
@@ -378,6 +385,9 @@ impl<T: Config<I> + pallet_distance::Config, I: 'static>
         } else {
             // identity was removed before distance status was found
             // so it's ok to do nothing
+            sp_std::if_std! {
+                println!("identity was removed before distance status was found: {:?}", idty_index);
+            }
         }
     }
 }
diff --git a/runtime/gdev/tests/integration_tests.rs b/runtime/gdev/tests/integration_tests.rs
index 442b635d69063afb821babbde3305bb9625accef..c465ff75c9a98a16d419ff53461e8baa8fb9746e 100644
--- a/runtime/gdev/tests/integration_tests.rs
+++ b/runtime/gdev/tests/integration_tests.rs
@@ -376,6 +376,99 @@ fn test_validate_identity_when_claim() {
         });
 }
 
+/// test identity creation workflow
+// with distance requested by last certifier
+#[test]
+fn test_identity_creation_workflow() {
+    ExtBuilder::new(1, 3, 4)
+        .with_initial_balances(vec![
+            (AccountKeyring::Charlie.to_account_id(), 10_000), // necessary for evalation distance reserve
+            (AccountKeyring::Eve.to_account_id(), 2_000),
+            (AccountKeyring::Ferdie.to_account_id(), 1_000),
+        ])
+        .build()
+        .execute_with(|| {
+            run_to_block(1);
+            // alice create identity for Eve
+            assert_ok!(Identity::create_identity(
+                frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
+                AccountKeyring::Eve.to_account_id(),
+            ));
+            assert_eq!(
+                Identity::identity(5),
+                Some(pallet_identity::IdtyValue {
+                    data: Default::default(),
+                    next_creatable_identity_on: 0u32.into(),
+                    old_owner_key: None,
+                    owner_key: AccountKeyring::Eve.to_account_id(),
+                    next_scheduled: 1 + 40,
+                    status: pallet_identity::IdtyStatus::Unconfirmed,
+                })
+            );
+            run_to_block(2);
+            // eve confirms her identity
+            assert_ok!(Identity::confirm_identity(
+                frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
+                "Eeeeeveeeee".into(),
+            ));
+            assert_eq!(
+                Identity::identity(5),
+                Some(pallet_identity::IdtyValue {
+                    data: Default::default(),
+                    next_creatable_identity_on: 0u32.into(),
+                    old_owner_key: None,
+                    owner_key: AccountKeyring::Eve.to_account_id(),
+                    next_scheduled: 2 + 876600,
+                    status: pallet_identity::IdtyStatus::Unvalidated,
+                })
+            );
+            run_to_block(3);
+            // eve gets certified by bob and charlie
+            assert_ok!(Cert::add_cert(
+                frame_system::RawOrigin::Signed(AccountKeyring::Bob.to_account_id()).into(),
+                2,
+                5
+            ));
+            assert_ok!(Cert::add_cert(
+                frame_system::RawOrigin::Signed(AccountKeyring::Charlie.to_account_id()).into(),
+                3,
+                5
+            ));
+            // charlie also request distance evaluation for eve
+            assert_ok!(Distance::request_distance_evaluation_for(
+                frame_system::RawOrigin::Signed(AccountKeyring::Charlie.to_account_id()).into(),
+                5
+            ));
+            assert_eq!(
+                Distance::identity_distance_status(5),
+                Some((
+                    AccountKeyring::Charlie.to_account_id(),
+                    pallet_distance::DistanceStatus::Pending
+                ))
+            );
+
+            run_to_block(51); // Pass 2 sessions
+            assert_ok!(Distance::force_update_evaluation(
+                frame_system::RawOrigin::Root.into(),
+                AccountKeyring::Alice.to_account_id(),
+                pallet_distance::ComputationResult {
+                    distances: vec![Perbill::one()],
+                }
+            ));
+            run_to_block(75); // Pass 1 session
+
+            // eve should not even have to claim her membership
+            System::assert_has_event(RuntimeEvent::Membership(
+                pallet_membership::Event::MembershipAdded {
+                    member: 5,
+                    expire_on: 75
+                        + <Runtime as pallet_membership::Config<Instance1>>::MembershipPeriod::get(
+                        ),
+                },
+            ));
+        });
+}
+
 /// test membership expiry
 #[test]
 fn test_membership_expiry() {