diff --git a/.gitignore b/.gitignore
index c8270c9..5c5e6b4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,4 +19,7 @@ target/
 
 
 # log
-*.log
\ No newline at end of file
+*.log
+
+# debug
+.vscode/
\ No newline at end of file
diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs
index 15d3a37..5cf25dd 100644
--- a/src/core/botinstance.rs
+++ b/src/core/botinstance.rs
@@ -65,6 +65,16 @@ pub mod botlog {
 
     // trace, debug, info, notice, warn, error, fatal
 
+    /*
+
+    in main : Log::debug("Checking bot actions", Some("main()".to_string()), None);
+
+    in log : 
+    [blalba@timestmp]
+    debug = "Checking bot actions",
+    
+     */
+
     pub fn trace(in_msg:&str,in_module:Option<String>,in_prvmsg:Option<&PrivmsgMessage>) -> () 
     {
 
@@ -85,6 +95,8 @@ pub mod botlog {
                 .str("Chatter",&format!("{:?}",chatter))
                 .str("Code_Module",&format!("{:?}",in_module))
         );
+
+        
         
     }
 
@@ -384,6 +396,8 @@ pub struct BotInstance
 	pub twitch_oauth : String,
 	pub bot_channels : Vec<ChType>,
     pub botmgrs : BotManagers,
+    //modesmgr : ModesManager, // Silent/Quiet , uwu , frisky/horny 
+
 }
 
 
@@ -434,7 +448,17 @@ impl BotInstance
 
 
 
-        let b = BotInstance {
+        // let b = BotInstance {
+        //     prefix : prefix,
+        //     bot_channel : Channel(login_name) ,
+        //     incoming_messages : Arc::new(RwLock::new(incoming_messages)),
+        //     botmodules : ModulesManager::init().await,
+        //     twitch_oauth : oauth_token,
+        //     bot_channels : botchannels,    
+        //     botmgrs : BotManagers::init(ratelimiters,client),
+        // };
+
+        BotInstance {
             prefix : prefix,
             bot_channel : Channel(login_name) ,
             incoming_messages : Arc::new(RwLock::new(incoming_messages)),
@@ -442,10 +466,9 @@ impl BotInstance
             twitch_oauth : oauth_token,
             bot_channels : botchannels,    
             botmgrs : BotManagers::init(ratelimiters,client),
-        };
+        }
 
-
-        b
+        // b
     }
 
     pub async fn runner(self) -> () {
diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs
index 43af6d7..86c6314 100644
--- a/src/core/botmodules.rs
+++ b/src/core/botmodules.rs
@@ -55,11 +55,12 @@ pub enum ModType {
     
 pub use ModType::BotModule;
 
-#[derive(Debug, PartialEq, Eq, Hash, Clone)]
-pub enum ChType {
-    Channel(String),
-}
+// #[derive(Debug, PartialEq, Eq, Hash, Clone)]
+// pub enum ChType {
+//     Channel(String),
+// }
 
+use botinstance::ChType;
 
 pub use ChType::Channel;
 use twitch_irc::message::PrivmsgMessage;
@@ -234,6 +235,20 @@ pub struct ModulesManager
     pub botactions: Arc<RwLock<HashMap<ModType,Vec<BotAction>>>>, 
 }
 
+/*
+
+statusdb
+    <HashMap 
+        <ModType, <-- e.g., BotModule(String::from("experiments001")) 
+        Vec<ModStatusType> <-- shows Enabled/Disabled per Status level
+
+botactions 
+    HashMap<
+        ModType, <-- e.g.,  BotModule(String::from("experiments001")) 
+        Vec<BotAction>> BotCommand, Listener
+
+*/
+
 impl ModulesManager 
 {
 
diff --git a/src/core/identity.rs b/src/core/identity.rs
index 3401bc1..7251646 100644
--- a/src/core/identity.rs
+++ b/src/core/identity.rs
@@ -6,11 +6,11 @@ use std::error::Error;
 use crate::core::botmodules::{ModulesManager,Listener,BotModule,BotActionTrait, BotCommand};
 use crate::core::botmodules::bot_actions::actions_util;
 
-use crate::core::botinstance::{self, botlog, BotInstance};
+use crate::core::botinstance::{self, botlog, BotInstance,ChType};
 use futures::lock::Mutex;
 use twitch_irc::message::{Badge, PrivmsgMessage};
 
-use crate::core::botmodules::ChType;
+// use crate::core::botmodules::ChType;
 
 use crate::core::botinstance::ArcBox;
 
@@ -29,6 +29,7 @@ use super::botmodules::bot_actions::actions_util::BotAR;
 
 fn adminvector() -> Vec<String> {
     vec![String::from("ModulatingForce")]
+    //vec![]
 }
 
 
@@ -97,6 +98,8 @@ pub async fn init(mgr:Arc<ModulesManager>)
          botinstance::botlog::trace(&format!("Twich Message > {}",msg.message_text), 
                 Some("identity.rs > cmd_promote()".to_string()), None);
 
+        let sendername = msg.clone().sender.name;
+
          let mut argv = msg.message_text.split(" ");
  
          argv.next(); // Skip the command name
@@ -115,7 +118,92 @@ pub async fn init(mgr:Arc<ModulesManager>)
              }
          }
 
+         let targetchnl = msg.channel_login.to_lowercase();
 
+         /*
+         
+            [x] 1. Get trgusr (regardless of -admin flag)
+            [x] 2. promote trguser
+            [x] 3. Output resulting change 
+
+          */
+
+        // [x] 1. Get trgusr (regardless of -admin flag)
+
+        let targetusr = if arg1 == Some("-admin") {arg2} else {arg1};
+
+
+        // [x] 2. promote trguser
+
+        // [x] Get a required lock first
+
+        let botlock = bot.read().await;
+        let id = botlock.get_identity();
+        let idlock = id.read().await;
+
+        let rslt = match targetusr {
+            Some(targetusr) => {
+
+                botinstance::botlog::debug(&format!("running promote()"), 
+                Some("identity.rs > cmd_promote()".to_string()), None);
+                Log::flush();
+
+                let target_bot_admin_role = if arg1 == Some("-admin") {Some(UserRole::BotAdmin)} else {None};
+
+                idlock.promote(
+                    sendername.clone(), 
+                    &sender_badge,
+                    targetusr.to_string(), 
+                    Some(ChType::Channel(targetchnl.clone())),
+                    target_bot_admin_role,
+                ).await
+            }
+
+            None => {
+
+                botinstance::botlog::debug(&format!("No Targer User argument"), 
+        Some("identity.rs > cmd_demote()".to_string()), None);
+                Log::flush();
+
+                ChangeResult::NoChange("No Targer User".to_string())
+
+            }
+
+        };
+
+
+
+        // [x] 3. Output resulting change 
+
+        match rslt {
+            ChangeResult::Success(a) => {
+                // println!("Succesfully promoted : {a} ;");
+                let outmsg = &format!("o7 Successfully promoted : {a}");
+                botinstance::botlog::debug(outmsg, 
+            Some("identity.rs > cmd_prommote()".to_string()), Some(&msg));
+                // let outmsg = "o7 Successfully promoted : ".to_string();
+                botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await;
+            },
+            ChangeResult::Failed(a) => {
+                // println!("Failed to promote : {a} ; ");
+                let outmsg = &format!("PoroSad failed to promote : {a}");
+                botinstance::botlog::debug(outmsg, 
+        Some("identity.rs > cmd_prommote()".to_string()), Some(&msg));
+                // let outmsg = "PoroSad failed to promote : ".to_string();
+                botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await;
+            },
+            ChangeResult::NoChange(a) => {
+                // println!("No Changes Made : {a} ; ");
+                let outmsg = &format!("uuh No Promotion Change : {a}");
+                botinstance::botlog::debug(outmsg, 
+        Some("identity.rs > cmd_prommote()".to_string()), Some(&msg));
+                // let outmsg = "uuh No Promotion Change : ".to_string();
+                botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await;
+            },
+        }
+
+
+        /* 
          match arg1 {
              Some(a1) if a1 == String::from("-admin") => {
                 // - [x] BotAdmins can promote admin to give BotAdmin UserRole 
@@ -252,7 +340,7 @@ pub async fn init(mgr:Arc<ModulesManager>)
                         },
                         ChangeResult::NoChange(a) => {
                             // println!("No Changes Made : {a} ; ");
-                            let outmsg = &format!("uuh No Change in Promotion : {a}");
+                            let outmsg = &format!("uuh Not making any changes : {a}");
                             botinstance::botlog::debug(outmsg, 
                     Some("identity.rs > cmd_prommote()".to_string()), Some(&msg));
                             Log::flush();
@@ -270,10 +358,10 @@ pub async fn init(mgr:Arc<ModulesManager>)
                     Some("identity.rs > cmd_prommote()".to_string()), Some(&msg));
                     Log::flush();
 
-                    // broadcaster & botadmins can make mods into superadmins
+                    // broadcaster & botadmins can make mods into SupMod
                     let ta = idlock.promote(arg1.to_string().to_lowercase(),
                      Some(ChType::Channel(msg.channel_login.to_lowercase())),
-                     Some(UserRole::Mod(ChType::Channel(msg.channel_login.to_lowercase())))).await;
+                     Some(UserRole::SupMod(ChType::Channel(msg.channel_login.to_lowercase())))).await;
 
                     match ta {
                         ChangeResult::Success(a) => {
@@ -367,6 +455,7 @@ pub async fn init(mgr:Arc<ModulesManager>)
  
          let targetchnl = arg2; 
 
+         */
 
 
          botinstance::botlog::trace(&format!("End of cmd_promote()"), 
@@ -406,7 +495,7 @@ pub async fn init(mgr:Arc<ModulesManager>)
     tempb.add_to_modmgr(Arc::clone(&mgr)).await;
 
     // async fn cmd_demote(mut _chat:Arc<Mutex<BotInstance>>,_msg:PrivmsgMessage) {
-    async fn cmd_demote(mut _chat:BotAR,msg:PrivmsgMessage) {
+    async fn cmd_demote(mut bot:BotAR,msg:PrivmsgMessage) {
         // println!("Called cmd demote");
         botinstance::botlog::debug("Called cmd demote", 
                     Some("identity.rs > cmd_demote()".to_string()), Some(&msg));
@@ -439,6 +528,227 @@ pub async fn init(mgr:Arc<ModulesManager>)
             
          */
 
+        // [ ] #TODO : Need to define the body that calls demote()
+
+        // [x] Unwraps arguments from message
+
+        // let mut argv = msg.message_text.split(" ");
+ 
+        // argv.next(); // Skip the command name
+
+        // let arg1 = argv.next();
+
+        
+        // let arg2 = argv.next();
+
+        
+        let (arg1,arg2) = {
+
+            let mut argv = msg.message_text.split(" ");
+ 
+            argv.next(); // Skip the command name
+    
+            let arg1 = argv.next();
+
+            let arg2 = argv.next();
+
+            (arg1,arg2)
+
+        };
+
+        /*
+        let mut sender_badge:Option<ChatBadge> = None;
+
+        for b in &msg.badges {
+            if b.name == "moderator" {
+                sender_badge = Some(ChatBadge::Mod);
+            } else if b.name == "broadcaster" {
+                sender_badge = Some(ChatBadge::Broadcaster);
+            }
+        }
+        */
+
+        // ---
+
+        /*
+            => 2024.02.15 - The business logic seems embeded straight into demote() with the following in mind : 
+                - demote() atm doesn't take sender ChatBadge <-- the assumption is canuserrun() was done
+                    for this user, and automatically assigned any roles that should get auto assigned
+                - demote() returns a ChangeResult
+
+                - [ ] So I think all I need to do here is parse out and pass input args to demote(), and output quirky messages based on ChangeResult
+                
+                -   [x] 1. Parse out the following
+                        - Sender (e.g., Name & Badge)
+                        - Target User (arg1)
+                        - Target Channel (current channel)
+                        - Msg or Msg.Message_Text (for later)
+                
+                - [x] 2. Run Demote()
+                    - within demote(), getspecialuserroles() is called on both the sender and the target
+                        - getspecialuserroles() only sends current db , while canuserrun() may change db depending on the most current state of the sender
+                        - getspecialuserroles also borrows the sender's badge to evaluate
+
+                - [ ] 3. Take ChangeResult and output response
+                
+
+         */
+
+
+        /*
+        
+                        
+        -   [x] 1. Parse out the following
+                - Sender (e.g., Name & Badge)
+                - Target User (arg1)
+                - Target Channel (current channel)
+                - (no need) Msg or Msg.Message_Text (for later)
+        
+         */
+
+
+        let sendername = msg.clone().sender.name;
+
+        let mut sender_badge_mut:Option<ChatBadge> = None;
+
+        for b in &msg.badges {
+            if b.name == "moderator" {
+                sender_badge_mut = Some(ChatBadge::Mod);
+            } else if b.name == "broadcaster" {
+                sender_badge_mut = Some(ChatBadge::Broadcaster);
+            }
+        }
+
+        let sender_badge = sender_badge_mut;
+
+        let targetusr = arg1;
+
+        let targetchnl = msg.channel_login.to_lowercase();
+
+        /*
+        
+        - [x] 2. Run Demote()
+            - within demote(), getspecialuserroles() is called on both the sender and the target
+                - getspecialuserroles() only sends current db , while canuserrun() may change db depending on the most current state of the sender
+                - getspecialuserroles also borrows the sender's badge to evaluate
+
+        
+         */
+
+         // [x] Get a required lock first
+
+         let botlock = bot.read().await;
+         let id = botlock.get_identity();
+         let idlock = id.read().await;
+
+
+
+        let rslt = match targetusr {
+            Some(targetusr) => {
+
+                botinstance::botlog::debug(&format!("running demote()"), 
+                Some("identity.rs > cmd_demote()".to_string()), None);
+                Log::flush();
+
+                idlock.demote(
+                    sendername.clone(), 
+                    &sender_badge,
+                    targetusr.to_string(), 
+                    Some(ChType::Channel(targetchnl.clone()))).await
+            }
+
+            None => {
+
+                botinstance::botlog::debug(&format!("No Targer User argument"), 
+        Some("identity.rs > cmd_demote()".to_string()), None);
+                Log::flush();
+
+                ChangeResult::NoChange("No Targer User".to_string())
+
+            }
+
+        };
+
+        /*
+        
+        - [x] 3. Take ChangeResult and output response
+        
+         */
+
+
+        // let senderUserRole = {
+
+        //     // note : getspecialuserroles will cover : 
+        //     //      - Internal roles stored at db for Mod & SupMod & BotAdmin
+        //     //      - Broadcaster (based on target hchatter & channel)
+        //     //  It MAY NOT COVER sutations where Sender has a Mod Badge, but not in DB yet as Mod
+        //     //   - So ideally this covers that (at least returns that they're a mod and go ahead and run for now)
+        //     //     - [ ] #TODO : This should also go ahead and add that mod to DB if possible as channel mod
+
+            
+
+        //     // let evalroles = vec![];
+
+        //     let evalroles = match sender_badge {
+
+        //         Some(ChatBadge::Mod) => {
+
+                    
+        //             let mut rslroles = idlock.getspecialuserroles(
+        //                 sendername.clone(), 
+        //                 Some(ChType::Channel(targetchnl.clone()))).await;
+
+        //             rslroles.push(UserRole::Mod(ChType::Channel(targetchnl)));
+
+        //             rslroles
+        //         },
+        //         _ => {
+        //             idlock.getspecialuserroles(
+        //                 sendername, 
+        //                 Some(ChType::Channel(targetchnl.clone()))).await
+        //         }
+        //     };
+
+        //     // => 02.16 - I think better would just migrate over the logic within demote 
+        //     //          - If there's business reqs to evaluate , better to keep the ChangeResult 
+        //     //           consistent and also pass ChatBadge
+
+        // }; // senderUserRole
+
+
+
+
+        match rslt {
+            ChangeResult::Success(a) => {
+                // println!("Succesfully promoted : {a} ;");
+                let outmsg = &format!("o7 Successfully demoted : {a}");
+                botinstance::botlog::debug(outmsg, 
+            Some("identity.rs > cmd_demote()".to_string()), Some(&msg));
+                // let outmsg = "o7 Successfully promoted : ".to_string();
+                botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await;
+            },
+            ChangeResult::Failed(a) => {
+                // println!("Failed to promote : {a} ; ");
+                let outmsg = &format!("PoroSad failed to demote : {a}");
+                botinstance::botlog::debug(outmsg, 
+        Some("identity.rs > cmd_demote()".to_string()), Some(&msg));
+                // let outmsg = "PoroSad failed to promote : ".to_string();
+                botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await;
+            },
+            ChangeResult::NoChange(a) => {
+                // println!("No Changes Made : {a} ; ");
+                let outmsg = &format!("uuh No Demotion Change : {a}");
+                botinstance::botlog::debug(outmsg, 
+        Some("identity.rs > cmd_demote()".to_string()), Some(&msg));
+                // let outmsg = "uuh No Promotion Change : ".to_string();
+                botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await;
+            },
+
+
+        }
+
+        // println!("tester");
+        // println!("tester2");
 
     }
 
@@ -750,7 +1060,23 @@ pub struct IdentityManager {
     // parent_mgr : Box<crate::core::botinstance::BotManagers>,
     //parent_mgr : Option<Box<crate::core::botinstance::BotManagers>>,
 } 
+/* 
+    HashMap<
+            String, <-- Chatter / Username
+         Vec<UserRole> -- <-- Vectors are basically arrays
+        >
 
+    -- [ ] 
+        let a = vec![]
+
+        modulatingforce : vec![UserRole::BotAdmin,
+                            UserRole::Mod(ChType::Channel("modulatingforcebot"))]
+        modulatingforce : vec![UserRole::BotAdmin,
+                            UserRole::Mod(ChType::Channel("modulatingforcebot"))]
+
+*/
+
+#[derive(Debug)]
 pub enum ChatBadge {
     Broadcaster,
     Mod,
@@ -876,7 +1202,9 @@ impl IdentityManager {
         ) -> (Permissible,ChangeResult) {
 
             // println!{"Checking within can_user_run()"};
-            botinstance::botlog::debug("Checking within can_user_run()", 
+            botinstance::botlog::debug(&format!("Checking within can_user_run() : 
+                            usr : {} ; channel : {:?} ; badge : {:?} ; cmdreqroles : {:?}",
+                            usr,channelname,chat_badge,cmdreqroles), 
                     Some("identity.rs > can_user_run()".to_string()), None);
             /*
             canUserRun -
@@ -918,6 +1246,8 @@ impl IdentityManager {
 
                 // let idar = Arc::new(RwLock::new(self));
 
+                let usr = usr.to_lowercase();
+
                 if cmdreqroles.len() == 0 {
                     // return Ok(Permissible::Allow)
                     return (Permissible::Allow , ChangeResult::NoChange("Command has no required cmdreqroles".to_string()))
@@ -959,7 +1289,7 @@ impl IdentityManager {
                         // match self.special_roles_users.get_mut(&usr.to_lowercase()) {
                         // match self.special_roles_users.get(&usr.to_lowercase()) {
                         // println!("Creating clone");
-                        botinstance::botlog::trace("Creating clone", 
+                        botinstance::botlog::trace("Creating arc clone", 
                         Some("identity.rs > can_user_run()".to_string()), None);
 
                         let roleslock = Arc::clone(&(*self).special_roles_users);
@@ -968,6 +1298,16 @@ impl IdentityManager {
                         botinstance::botlog::trace("Read lock on : Special_Roles_User", 
                         Some("identity.rs > can_user_run()".to_string()), None);
 
+                        {
+
+                            // If target user doesn't exist in special_roles_users , add with blank vector roles
+                            let mut srulock = self.special_roles_users.write().await;
+                            srulock.entry(usr.clone()).or_insert(Arc::new(RwLock::new(vec![])));
+                            botinstance::botlog::trace(&format!("Ensuring Chatter in Roles {:?}",srulock.entry(usr.clone())), 
+                            Some("identity.rs > promote()".to_string()), None);
+                            Log::flush();
+                        }
+
                         let mut roleslock = roleslock.write().await;
                         match (*roleslock).get(&usr.to_lowercase()) {
                             Some(usrroles) if 
@@ -1089,51 +1429,370 @@ impl IdentityManager {
 
     // pub async fn promote(&mut self,trgchatter:String,channel:Option<ChType>,trg_role:Option<UserRole>) -> ChangeResult {
     pub async fn promote(&self,
+        authorizer:String,
+        authorizer_badge:&Option<ChatBadge>,
         trgchatter:String,
         channel:Option<ChType>,
-        trg_role:Option<UserRole>) -> ChangeResult 
+        trg_role:Option<UserRole> 
+    )    -> ChangeResult 
     {
 
 
-        botinstance::botlog::trace(&format!("IN VARS for promote() : Target Chatter : {} ; Target Channel : {:?} ; Targer Role {:?}",
-                        trgchatter,channel,trg_role), 
+        botinstance::botlog::trace(&format!(
+            "IN VARS for promote() : auth : {} ; authbadge : {:?} ; trg : {} ; Channel {:?} ; {:?}",
+                        authorizer,authorizer_badge,trgchatter,channel,trg_role), 
         Some("identity.rs > promote()".to_string()), None);
         Log::flush();
-        // Note : If channel is none, getspecialuserroles() returns all roles for the user
-        
-        // let chatterroles = self.getspecialuserroles(trgchatter, channel);
 
-        // let chatterroles = self.getspecialuserroles(trgchatter.clone(), channel.clone());
-        // let chatterroles = *self.getspecialuserroles(trgchatter.clone(), channel.clone()).await;
-        // let chatterroles = chatterroles.lock().await;
-        // // let chatterroles = *chatterroles;
-        // let chatterroles = chatterroles.unwrap();
+
+        /*
+            [x] 1. Check if Authorizer Mod Badge then Auto Promote to Mod if not Mod
+            [x] 2. Get Authorizer & Target Chatter Roles with a Given Channel
+            [x] 3. If the authorizer & Target Chatters are the same, and the Authorizer is not a Admin, return no change
+            [x] 4a. If Authorizer is BotAdmin & trg_role is Some(BotAdmin) , set Target as BotAdmin and return
+            [x] 4b. If target is Broadcaster, return NoChange
+            [ ] 4c. If Authorizer is a SupMod,Broadcaster,BotAdmin , can Promote Target Chatter > Mod
+                - NOTE : We do not validate trg_role here - app logic requires you to promote 1 to Mod and 1 more to SupMod
+            [ ] 4d. If Authorizer is a Broadcaster,BotAdmin , can Promote a Target Mod > SupMod
+                - NOTE : We do not validate trg_role here - app logic requires you to promote 1 to Mod and 1 more to SupMod
+             
+         
+        */
+
+        // [x] 1. Check if Authorizer Mod Badge then Auto Promote to Mod if not Mod
+
+        let (authusrroles,trgusrroles) = if let Some(channel) = channel.clone() {
+            let mut authusrroles = self.getspecialuserroles(
+                authorizer.to_lowercase().clone(), 
+                Some(channel.clone()))
+                .await;
+            
+
+            { // mut block
+
+                // let authusrroles_mut = &mut authusrroles;
+                // [x] Add Mod(channel) to authusrroles
+                // [x] #TODO also add to DB if possible?
+                match *authorizer_badge {
+                    Some(ChatBadge::Mod) if ( !authusrroles.contains(&UserRole::Mod(channel.clone())) 
+                        && !authusrroles.contains(&UserRole::SupMod(channel.clone())))  => {
+                        // (*authusrroles_mut).push(UserRole::Mod(channel.clone()));
+                        authusrroles.push(UserRole::Mod(channel.clone()));
+
+                        let mut srulock = self.special_roles_users.write().await;
+                        srulock
+                            .get_mut(&trgchatter)
+                            .expect("Error getting roles")
+                            // !! [ ] Unsure what happens if promoting a chatter that doesn't exist at
+                            .write().await
+                            .push(UserRole::Mod(channel.clone()));
+
+                        }
+                        _ => (),
+                    }
+                } // mut block
+
+                
+                // [x] 2. Get Authorizer & Target Chatter Roles
+
+                let trgusrroles = self.getspecialuserroles(
+                    trgchatter.to_lowercase().clone(), 
+                    Some(channel.clone()))
+                    .await;
+
+                (authusrroles,trgusrroles)
+            } else {
+                let mut authusrroles = self.getspecialuserroles(
+                    authorizer.to_lowercase().clone(), 
+                    None)
+                    .await;
+                let trgusrroles = self.getspecialuserroles(
+                    trgchatter.to_lowercase().clone(), 
+                    None)
+                    .await;
+                (authusrroles,trgusrroles)
+            };
+
+
+
+
+        //  [x] 3. If the authorizer & Target Chatters are the same, and the Authorizer is not a Admin, return no change
+        if trgchatter == authorizer && !authusrroles.contains(&UserRole::BotAdmin) {
+            return ChangeResult::NoChange("Can't target yourself".to_string());
+        }
+
+
+        // [x] 4a. If Authorizer is BotAdmin & trg_role is Some(BotAdmin) , set Target as BotAdmin and return
+        if authusrroles.contains(&UserRole::BotAdmin) && trg_role == Some(UserRole::BotAdmin) {
+            if trgusrroles.contains(&UserRole::BotAdmin) {
+                return ChangeResult::NoChange("Already has the role".to_string());
+            } else {
+
+                {
+                    let mut srulock = self.special_roles_users.write().await;
+
+                    srulock.entry(trgchatter.clone()).or_insert(Arc::new(RwLock::new(vec![])));
+                    botinstance::botlog::trace(&format!("Ensuring Target Chatter in Roles > {:?}",srulock.entry(trgchatter.clone())), 
+                    Some("identity.rs > promote()".to_string()), None);
+                    Log::flush();
+                }
+
+                {
+
+                    let mut srulock = self.special_roles_users.write().await;
+
+                    srulock
+                        .get_mut(&trgchatter)
+                        .expect("Error getting roles for the user")
+                        .write().await
+                        .push(UserRole::BotAdmin); // <-- Adds the specific role
+                    botinstance::botlog::trace(&format!("Inserting Role > {:?}",srulock.entry(trgchatter.clone())), 
+                    Some("identity.rs > promote()".to_string()), None);
+                    Log::flush();
+                }
+
+                return ChangeResult::Success("Promotion Successful".to_string());
+                
+            }
+        }
+
+        // [x] 4b. If target is Broadcaster, return NoChange
+
+        if trgusrroles.contains(&UserRole::Broadcaster) {
+            return ChangeResult::NoChange("Can't target broadcaster".to_string());
+        }
+
+
+        /*
+            [ ] 4c. If Authorizer is a SupMod,Broadcaster,BotAdmin , can Promote Target Chatter > Mod
+                - NOTE : We do not validate trg_role here - app logic requires you to promote 1 to Mod and 1 more to SupMod
+            [ ] 4d. If Authorizer is a Broadcaster,BotAdmin , can Promote a Target Mod > SupMod
+                - NOTE : We do not validate trg_role here - app logic requires you to promote 1 to Mod and 1 more to SupMod
+         */
+
+
+        // let authhasnsreqroles = match channel.clone() {
+
+        //     Some(channel) => authusrroles.contains(&UserRole::SupMod(channel.clone())) || 
+        //                                 authusrroles.contains(&UserRole::BotAdmin) || 
+        //                                 authusrroles.contains(&UserRole::Broadcaster) ,
+        //     None => authusrroles.contains(&UserRole::BotAdmin),
+        // };
+
+
+        if let Some(trg_chnl) = channel.clone() {
+
+
+            if !trgusrroles.contains(&UserRole::Broadcaster) 
+                && !trgusrroles.contains(&UserRole::Mod(trg_chnl.clone())) 
+                && !trgusrroles.contains(&UserRole::SupMod(trg_chnl.clone())) {
+                // target user is neither Mod nor SupMod && not broadcaster
+                // target's Next Role would be Mod
+                // Authorizer must be SupMod,Broadcaster,BotAdmin 
+                // > Promote target to Mod
+                if authusrroles.contains(&UserRole::SupMod(trg_chnl.clone())) 
+                    || authusrroles.contains(&UserRole::Broadcaster) 
+                    || authusrroles.contains(&UserRole::BotAdmin)
+                {
+
+                    {
+
+                        // If target user doesn't exist in special_roles_users , add with blank vector roles
+                        let mut srulock = self.special_roles_users.write().await;
+                        srulock.entry(trgchatter.clone()).or_insert(Arc::new(RwLock::new(vec![])));
+                        botinstance::botlog::trace(&format!("Ensuring Chatter in Roles {:?}",srulock.entry(trgchatter.clone())), 
+                        Some("identity.rs > promote()".to_string()), None);
+                        Log::flush();
+                    }
+                    {
+                        // promote target after 
+                        let mut srulock = self.special_roles_users.write().await;
+                        srulock
+                            .get_mut(&trgchatter)
+                            .expect("Error getting roles")
+                            .write().await
+                            .push(UserRole::Mod(trg_chnl.clone())); // Role to Add
+                        botinstance::botlog::trace(&format!("Adding Roles to Chatter {:?}",srulock.entry(trgchatter.clone())), 
+                        Some("identity.rs > promote()".to_string()), None);
+                        Log::flush();
+                    }
+        
+                    return ChangeResult::Success(String::from("Promotion Successful"));
+
+                } 
+                // Other else conditions would be mostly spcecial responses like ChangeResult::NoChange or ChangeResult::Fail 
+                // related to authusrroles
+
+                else {
+                    return ChangeResult::Failed(String::from("You're not permitted to do that"));
+                }
+
+
+            } else if !trgusrroles.contains(&UserRole::Broadcaster) 
+                && trgusrroles.contains(&UserRole::Mod(trg_chnl.clone())) 
+                && !trgusrroles.contains(&UserRole::SupMod(trg_chnl.clone())) //  
+                {
+                // target user is a Mod && not broadcaster
+                // target's Next Role would be SupMod
+                // [ ] #todo Check first if target have SupMod - Optional but could be done to cleanup first
+                // Authorizer must be Broadcaster,BotAdmin 
+                // > Promote target to SupMod 
+
+                if authusrroles.contains(&UserRole::Broadcaster) 
+                    || authusrroles.contains(&UserRole::BotAdmin) 
+                {
+
+                    { // Inserts user if doesn't exist
+                        let mut srulock = self.special_roles_users.write().await;
+                        srulock.entry(trgchatter.clone()).or_insert(Arc::new(RwLock::new(vec![])));
+                        botinstance::botlog::trace(&format!("Ensuring User in Roles {:?}",srulock.entry(trgchatter.clone())), 
+                        Some("identity.rs > promote()".to_string()), None);
+                        Log::flush();
+                    }
+                    { // Adds the requested role for the user
+                        let mut srulock = self.special_roles_users.write().await;
+                        srulock
+                            .get_mut(&trgchatter)
+                            .expect("Error getting roles")
+                            // !! [ ] Unsure what happens if promoting a chatter that doesn't exist at
+                            .write().await
+                            .push(UserRole::SupMod(trg_chnl.clone()));
+                        botinstance::botlog::trace(&format!("Adding Required Role > {:?}",srulock.entry(trgchatter.clone())), 
+                        Some("identity.rs > promote()".to_string()), None);
+                        Log::flush();
+                    }
+                    {  // Removes the lower role (mod) from the user
+                        let mut srulock = self.special_roles_users.write().await;
+                        let mut uroleslock = srulock
+                                .get_mut(&trgchatter)
+                                .expect("Error getting roles")
+                                .write().await;
+                        if let Some(indx) = uroleslock.iter().position(|value| *value == UserRole::Mod(trg_chnl.clone())){
+                            uroleslock.swap_remove(indx);
+                        }
+
+                        botinstance::botlog::trace(&format!("Removing lower role > {:?}",uroleslock), 
+                        Some("identity.rs > promote()".to_string()), None);
+                        Log::flush();
+                    }
+        
+                    return ChangeResult::Success(String::from("Promotion Successful"));
+
+
+                } else {
+                    return ChangeResult::Failed(String::from("You're not permitted to do that"));
+                }
+
+            } else if !trgusrroles.contains(&UserRole::Broadcaster) 
+                 && trgusrroles.contains(&UserRole::SupMod(trg_chnl.clone()))  {
+                // target user is a SuMod && not broadcaster
+                // No Change
+                return ChangeResult::Failed(String::from("Already highest available role"));
+                
+
+            } else  {
+                // since handling for channel is already done, will be handling other trguserroles situations here
+                // other situations includes : 
+                /*
+                    [-] targetuser is broadcaster >> no need - this was done earlier in the function
+                    [?] ?
+                 */
+
+                // At the moment, without any new roles, this should not be reached 
+
+                 botinstance::botlog::warn(&format!("Code Warning : add handing for other trgusrroles"), 
+                 Some("identity.rs > promote()".to_string()), None);
+                 return ChangeResult::Failed(String::from("Code Warning"));
+                
+
+            }
+
+
+
+            // let trghasreqroles = 
+        
+            // {
+
+            //     // If target user doesn't exist in special_roles_users , add with blank vector roles
+            //     let mut srulock = self.special_roles_users.write().await;
+            //     srulock.entry(trgchatter.clone()).or_insert(Arc::new(RwLock::new(vec![])));
+            //     botinstance::botlog::trace(&format!("Ensuring Chatter in Roles {:?}",srulock.entry(trgchatter.clone())), 
+            //     Some("identity.rs > promote()".to_string()), None);
+            //     Log::flush();
+            // }
+            // {
+            //     // promote target after 
+            //     let mut srulock = self.special_roles_users.write().await;
+            //     srulock
+            //         .get_mut(&trgchatter)
+            //         .expect("Error getting roles")
+            //         // !! [ ] Unsure what happens if promoting a chatter that doesn't exist at
+            //         .write().await
+            //         .push(UserRole::Mod(trg_chnl.clone())); // Role to Add
+            //     botinstance::botlog::trace(&format!("Adding Roles to Chatter {:?}",srulock.entry(trgchatter.clone())), 
+            //     Some("identity.rs > promote()".to_string()), None);
+            //     Log::flush();
+            // }
+
+            // return ChangeResult::Success(String::from("Promotion Successful"));
+
+            
+        };
+
+        // if authhasnsreqroles {
+            
+        //     {
+
+        //         // If target user doesn't exist in special_roles_users , add with blank vector roles
+        //         let mut srulock = self.special_roles_users.write().await;
+        //         srulock.entry(trgchatter.clone()).or_insert(Arc::new(RwLock::new(vec![])));
+        //         botinstance::botlog::trace(&format!("SRLOCK - 1st write > {:?}",srulock.entry(trgchatter.clone())), 
+        //         Some("identity.rs > promote()".to_string()), None);
+        //         Log::flush();
+        //     }
+        //     {
+        //         // promote target after 
+        //         let mut srulock = self.special_roles_users.write().await;
+        //         srulock
+        //             .get_mut(&trgchatter)
+        //             .expect("Error getting roles")
+        //             // !! [ ] Unsure what happens if promoting a chatter that doesn't exist at
+        //             .write().await
+        //             .push(UserRole::Mod(trg_chnl));
+        //         botinstance::botlog::trace(&format!("SRLOCK - 2st write > {:?}",srulock.entry(trgchatter.clone())), 
+        //         Some("identity.rs > promote()".to_string()), None);
+        //         Log::flush();
+        //     }
+
+        //     return ChangeResult::Success(String::from("Promotion Successful"));
+
+        // }
+
+        // authusrroles.contains(&UserRole::Mod(()))
+
+
+
+        
+
+
+
+
+        /*
 
 
         let chatterroles = self.getspecialuserroles(trgchatter.clone(), channel.clone()).await;
-        // let chatterroles = chatterroles.lock().await;
-        // let chatterroles = *chatterroles;
-        // let chatterroles = chatterroles.unwrap();
 
-
-        // let emptyvec = vec![];
-
-        // let chatterroles = match chatterroles {
-        //     Some(a) => a,
-        //     _ => &(emptyvec),
-        // };
-
-        // let chatterroles = chatterroles.unwrap();
-        // let chatterroles = chatterroles.read().await;
-        //let rolemap = &(*chatterroles);
+        
         let rolemap = chatterroles;
         
-
-
         match trg_role {
             Some(UserRole::Mod(_)) => {
+
+                
                 if let Some(trg_chnl) = channel.clone() {
 
+                    // [ ] 1. If trg_role & trgchatter is a Mod or SupMod of the target channel, return NoChange
+
                     let chatterroles = self.getspecialuserroles(trgchatter.clone(), channel.clone()).await;
                     let rolemap = chatterroles;
                     // let rolemap = rolemap.unwrap();
@@ -1150,9 +1809,13 @@ impl IdentityManager {
                     // // let c = b.get_mut(&trgchatter);
                     // let c = (*b).;
 
+                    // [ ] 2. Ensure an entry in Special_Roles_user for trgchatter, and push Mod(Channel) for the Target User
+
                     // [x] (!!) AROUND HERE - check if the user exists first, and at least add the user as we're promoting anyway
 
                     {
+
+                        // If target user doesn't exist in special_roles_users , add with blank vector roles
                         let mut srulock = self.special_roles_users.write().await;
                         srulock.entry(trgchatter.clone()).or_insert(Arc::new(RwLock::new(vec![])));
                         botinstance::botlog::trace(&format!("SRLOCK - 1st write > {:?}",srulock.entry(trgchatter.clone())), 
@@ -1160,6 +1823,7 @@ impl IdentityManager {
                         Log::flush();
                     }
                     {
+                        // promote target after 
                         let mut srulock = self.special_roles_users.write().await;
                         srulock
                             .get_mut(&trgchatter)
@@ -1181,6 +1845,8 @@ impl IdentityManager {
             {
                     if let Some(trg_chnl) = channel.clone() {
 
+                        // [ ] 1. If trg_role & trgchatter is a Mod or SupMod of the target channel, return NoChange
+
                         let chatterroles = self.getspecialuserroles(trgchatter.clone(), channel.clone()).await;
                         let rolemap = chatterroles;
                         // let rolemap = rolemap.unwrap();
@@ -1196,6 +1862,9 @@ impl IdentityManager {
                         // // let c = b.get_mut(&trgchatter);
                         // let c = (*b).;
 
+                        
+                        // [ ] 2. Ensure an entry in Special_Roles_user for trgchatter, and push SupMod(Channel) for the Target User
+
                         // [x] (!!) AROUND HERE - check if the user exists first, and at least add the user as we're promoting anyway
 
                         {
@@ -1245,6 +1914,8 @@ impl IdentityManager {
                 } ,
             Some(UserRole::BotAdmin) => {
 
+                
+
                 let chatterroles = self.getspecialuserroles(trgchatter.clone(), channel.clone()).await;
                 let rolemap = chatterroles;
 
@@ -1308,6 +1979,7 @@ impl IdentityManager {
             },
         }
 
+        */
 
         // match chatterroles {
         //     Some(chatterroles) => {
@@ -1371,42 +2043,81 @@ impl IdentityManager {
         //     },
         //     _ => (),
         // }
-
-        ChangeResult::Success(String::from("TEST > Promotion Successful"))
+        botinstance::botlog::warn(&format!("Runtime reached undeveloped code"), 
+        Some("identity.rs > promote()".to_string()), None);
+        ChangeResult::Failed(String::from("ERROR"))
     } 
 
 
     pub async fn demote(&self,
         authorizer:String,
+        authorizer_badge:&Option<ChatBadge>,
         trgchatter:String,
         channel:Option<ChType>,
-        trg_role:Option<UserRole>) -> ChangeResult 
+        // trg_role:Option<UserRole>
+    ) -> ChangeResult 
     {
-        botinstance::botlog::trace(&format!("IN VARS for demote() : Authorizer : {:?} ; Target Chatter : {} ; Target Channel : {:?} ; Targer Role {:?}",
-                        authorizer,trgchatter,channel,trg_role), 
+        // botinstance::botlog::trace(&format!("IN VARS for demote() : Authorizer : {:?} ; Target Chatter : {} ; Target Channel : {:?} ; Targer Role {:?}",
+        //                 authorizer,trgchatter,channel,trg_role), 
+        botinstance::botlog::trace(&format!("IN VARS for demote() : Authorizer : {:?} ; Target Chatter : {} ; Target Channel : {:?}",
+                    authorizer,trgchatter,channel), 
         Some("identity.rs > demote()".to_string()), None);
         Log::flush();
 
         /*
             Check authorizer roles (if any) for the target channel 
-            Check Targer User roles (if any) for the target channel
+            Check Targer User's roles (if any) for the target channel
             Target Channel may be NONE in the case of Non-Channel related roles (FUTURE ENH)
 
             Use the roles of the above to determine whether the authorizer can demote the target user or not
          */
 
+        // [x] 1. If Authorizer's Badge is Mod, ensuring Sender is in DB as Mod(Channel)
         if let Some(channel) = channel {
-            let authusrroles = self.getspecialuserroles(
+            let mut authusrroles = self.getspecialuserroles(
                 authorizer.to_lowercase().clone(), 
                 Some(channel.clone()))
                 .await;
             // let authusrroles = authusrroles;
+            {
+
+                // let authusrroles_mut = &mut authusrroles;
+                // [x] Add Mod(channel) to authusrroles
+                // [x] #TODO also add to DB if possible?
+                match *authorizer_badge {
+                    Some(ChatBadge::Mod) if (!authusrroles.contains(&UserRole::Mod(channel.clone()))
+                        && !authusrroles.contains(&UserRole::SupMod(channel.clone()))
+                        ) => {
+                        // (*authusrroles_mut).push(UserRole::Mod(channel.clone()));
+                        authusrroles.push(UserRole::Mod(channel.clone()));
+
+                        let mut srulock = self.special_roles_users.write().await;
+                        srulock
+                            .get_mut(&trgchatter)
+                            .expect("Error getting roles")
+                            // !! [ ] Unsure what happens if promoting a chatter that doesn't exist at
+                            .write().await
+                            .push(UserRole::Mod(channel.clone()));
+
+                    }
+                    _ => (),
+                }
+            }
+
+            // [x] 2. Targer User's Vec<UserRole>
 
             let trgusrroles = self.getspecialuserroles(
                 trgchatter.to_lowercase().clone(), 
                 Some(channel.clone()))
                 .await;
 
+            // [x] 3. Return if Authorizer & Target are same chatter and Authorizer is not a BotAdmin
+            if trgchatter == authorizer && !authusrroles.contains(&UserRole::BotAdmin) {
+                return ChangeResult::NoChange("Can't target yourself".to_string())
+            }
+
+            // [x] 4a. Authorizers who are BotAdmin, Broadcaster or Supermod can demote a Mod
+
             if ( authusrroles.contains(&UserRole::BotAdmin) || 
                 authusrroles.contains(&UserRole::Broadcaster) || 
                 authusrroles.contains(&UserRole::SupMod(channel.clone())) ) && 
@@ -1422,6 +2133,8 @@ impl IdentityManager {
                         return ChangeResult::Success("Demoted successfully".to_string())
                     }
                 }
+
+            // [x] 4b. Authorizers who are BotAdmin, Broadcaster can demote a SupMod
             else if ( authusrroles.contains(&UserRole::BotAdmin) || 
                     authusrroles.contains(&UserRole::Broadcaster) ) && 
                     trgusrroles.contains(&UserRole::SupMod(channel.clone()))
@@ -1431,20 +2144,38 @@ impl IdentityManager {
                         .get_mut(&trgchatter)
                         .expect("Error getting roles")
                         .write().await;
-                    usrrolelock.push(UserRole::SupMod(channel.clone()));
+                    usrrolelock.push(UserRole::Mod(channel.clone())); // pushes Mod , and removes SupMod
                     if let Some(indx) = usrrolelock.iter().position(|value| *value == UserRole::SupMod(channel.clone())){
                         usrrolelock.swap_remove(indx);
                         return ChangeResult::Success("Demoted successfully".to_string())
                     }
                 }
+
+            // [x] 4c. When Target chatter isnt a Mod or SupMod to demote
+            else if !trgusrroles.contains(&UserRole::Mod(channel.clone())) && 
+                !trgusrroles.contains(&UserRole::SupMod(channel.clone())) {
+                    return ChangeResult::Failed("Target chatter does not have a role that can be demoted".to_string())
+                }
+            // [x] 4d. WHhen they're only a Mod
+            else if authusrroles.contains(&UserRole::Mod(channel.clone())) {
+                return ChangeResult::Failed("You're not permitted to do that".to_string())
+            }
         }
 
 
+        botinstance::botlog::warn(&format!("Potential Unhandled Demotion Condition : Consider explicitely adding in for better handling"), 
+    Some("identity.rs > demote()".to_string()), None);
+        Log::flush();
         ChangeResult::Failed(String::from("Did not meet criteria to demote succesfully"))
+
     }
 
+
+
     // pub async fn getspecialuserroles(&self,chattername:String,channel:Option<ChType>) -> Option<Arc<RwLock<Vec<UserRole>>>> {
-    pub async fn getspecialuserroles(&self,chattername:String,channel:Option<ChType>) -> Vec<UserRole> {
+    pub async fn getspecialuserroles(
+        &self,chattername:String,
+        channel:Option<ChType>) -> Vec<UserRole> {
         /*
             Note : Ideally this be called for a given chatter name ?
          */
diff --git a/src/modules/experiments.rs b/src/modules/experiments.rs
index 2c4a4e2..c75574f 100644
--- a/src/modules/experiments.rs
+++ b/src/modules/experiments.rs
@@ -14,10 +14,10 @@
 
 use std::future::Future;
 
-use crate::core::botmodules::{ModulesManager,Listener,BotModule,BotActionTrait, BotCommand,ChType};
+use crate::core::botmodules::{ModulesManager,Listener,BotModule,BotActionTrait, BotCommand};
 use crate::core::botmodules::bot_actions::actions_util::{self, BotAR};
 
-use crate::core::botinstance::{self,BotInstance};
+use crate::core::botinstance::{self,BotInstance,ChType};
 use futures::lock::Mutex;
 use twitch_irc::message::PrivmsgMessage;