---
# System prepended metadata

title: Usernames Zome
tags: [Kizuna-architecture]

---

# Usernames Zome
###### tags: `Kizuna-architecture`

## User Stories
* As an agent newly entering the network, I would like to have a human-readable username that can be used by others to identify me 

## Entry Structure
```rust
// TODO: Define Path accordingly
Entry "Path" {
    struct Path(String)
}

Entry "username"
    struct Username {
        username: String
    }
    Links: {
        path->username|usernames|
        agent_pub_key->username|username|
    }
}
```

Paths will contain this:
```rust

// Path above can be sparsed adding sparsing 
// algorithm in zome (will be available in RSM) such as
// by initials of username or by time
// For example:
Path("USERNAME.a.al.ali.alic.alice");
Path("USERNAME.b.bo.bob.bobb.bobby");
```

## Entry Relationship Diagram (With path)
```mermaid
graph TD
  subgraph profile_zome
    subgraph anchors
      usernames
    end
    subgraph path
      usernames.a-->|path|usernames.aa
      usernames.a-->|path|usernames.ab
      usernames.a-->|path|usernames.al
      usernames.b-->|path|usernames.ba
      usernames.b-->|path|usernames.bb
      usernames.b-->|path|usernames.bo
    end
    subgraph username
    usernames-->|username|usernames.a
    usernames-->|username|usernames.b
    usernames.al-->|username|aliceHC
    usernames.bo-->|username|bobbyHC
    end
    subgraph agents
      alice_id-->|username|aliceHC
      bobby_id-->|username|bobbyHC
    end
  end
```

## Validation
### Entries
* `paths`:
    * Update/Delete is not valid
    * create is always valid
* `username`
    * update/delete is valid if the address of the agent committing the entry is the same with the agent address of the author of the entry
    * create is valid only once when username doesn't exist yet for the authoring agent (Currently being checked at commit time)
    * create is only valid when there is no same entry exisiting - Will be checked by making the username entry a "single author entry" and have resolution callback when there is conflict especially in network partition.
### Links
* `path->username`
    * only valid when the agent is signing
    * RemoveLink valid if the author of the entry is removing


### Additional Notes
- In RSM, you can already build a tree of create, updates, and deletes. Each agent will walk their own tree.
    - This can allow us to put those people who wanted the username but were already taken by someone else to be in queue (if we want to). 
    - When you get details on an entry, you get all the CUD details on a particular entry.
- Input validation for uniqueness in set_username will not work when the network is partitioned. This can be solved by single author mechanism. This only `detects` the conflict but does not resolve it. The resolution callback for these kinds of conflicts should be provided by the app developer.
- TODO: some sort of sybil protection mechanism.
- Path is now implemented in RSM. Adds additional hops to spread out the load linked to one anchor. This adds more dht hops in getting the desired entries, but if you know the anchor beforehand, then you can skip the middle trees and hop right into the anchor that was supposed to be fetched.

### `set_username`
```rust=
pub struct UsernameWrapper(String);
pub fn set_username(username_input: UsernameWrapper) -> ExternResult<UsernameOutput> 
```
### `get_usernames`
```rust=
pub struct AgentPubKeys(Vec<AgentPubKey>);
pub struct UsernameList(Vec<UsernameOutput>);

pub fn get_usernames(agent_pubkeys: AgentPubKeys) -> ExternResult<UsernameList>
```
### `get_my_username`
```rust=
pub struct UsernameOutput {
    username: String,
    agent_id: AgentPubKey,
    created_at: Timestamp,
    entry_header_hash: HeaderHash,
}

pub fn get_my_username_handler() -> ExternResult<UsernameOutput>
```
### `get_all_usernames`
```rust=
pub struct UsernameList(Vec<UsernameOutput>);

pub fn get_all_usernames() -> ExternResult<UsernameList>
```
### `get_agent_pubkey_from_username`
```rust=
pub struct UsernameWrapper(String);

pub(crate) fn get_agent_pubkey_from_username_handler( username_input: UsernameWrapper ) -> ExternResult<AgentPubKey>
```



