# How the Tiered Trust Mechanism in BitChat Affects Message Envelope Deposits

> Discover how BitChat's tiered trust mechanism impacts message envelope deposits. Learn how it prioritizes favorites and limits lower-trust tiers to prevent storage issues.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: deep-dive
- Published: 2026-08-19

---

**BitChat’s tiered trust system prioritizes message envelopes from mutually-vouched "favorite" peers with unlimited quotas while strictly limiting or rejecting deposits from lower-trust tiers to prevent storage exhaustion.**

The **permissionlesstech/bitchat** repository implements a store-and-forward messaging protocol where devices act as couriers for offline peers. The **tiered trust mechanism** governs how many message envelopes each peer can deposit and which messages survive when storage capacity reaches its limit. This ensures trusted contacts maintain reliable message delivery while untrusted actors cannot flood the network.

## Understanding the Three Trust Tiers

BitChat categorizes every peer into one of three logical trust levels that determine envelope deposit privileges. The trust tier evaluation occurs in components like `SecureIdentityStateManager` before reaching the storage layer.

**Favorite** – Established when two peers mutually vouch for each other (both appear in each other’s favorite lists). These deposits receive unlimited per-depositor quotas (up to 5 envelopes), are protected from eviction by lower-tier mail, and only face removal when the store fills completely with favorite-tier envelopes.

**Verified** – Assigned when a peer’s announce signature has been cryptographically verified but no mutual vouch exists. These deposits face strict caps: maximum 2 envelopes per depositor and a global pool limit of 20 verified envelopes across all peers. When storage fills, verified envelopes are evicted first.

**Untrusted** – Applies to peers with neither mutual vouch nor verified signature. The `deposit` method rejects these deposits immediately; callers must enforce this policy before invoking the store.

## How Deposit Limits and Quotas Work

The [`CourierStore.swift`](https://github.com/permissionlesstech/bitchat/blob/main/CourierStore.swift) file enforces resource caps through the `deposit(_:from:tier:)` method, which accepts a `CourierDepositTier` enum value. The store itself does not determine trust levels—it only applies the quotas associated with the tier passed to it.

**Per-depositor limits** restrict how many envelopes a single peer can store:

- **Favorite tier**: Maximum 5 envelopes per depositor (`Limits.maxPerFavoriteDepositor`)
- **Verified tier**: Maximum 2 envelopes per depositor (`Limits.maxPerVerifiedDepositor`)

**Global limits** constrain the total store capacity:

- **Total capacity**: 40 envelopes maximum (`Limits.maxEnvelopes`)
- **Verified pool cap**: 20 verified envelopes maximum across all depositors (`Limits.maxVerifiedEnvelopes`)

When the global verified pool reaches 20 envelopes, the store rejects additional verified deposits even if total capacity remains available.

## The Eviction Policy When Storage Is Full

When the store reaches its 40-envelope maximum, the eviction logic in `CourierStore` applies a strict priority hierarchy to make room for new deposits:

1. First, it searches for the oldest **verified** envelope and removes it.
2. If no verified envelopes exist and the incoming deposit is **favorite** tier, it evicts the oldest favorite envelope.
3. If no verified envelopes exist and the incoming deposit is **verified** tier, the deposit is rejected.

This policy ensures **favorite mail can always be carried** while **verified mail serves as a buffer** that absorbs storage pressure before affecting trusted communications.

## Implementation in CourierStore.swift

The deposit logic resides in [`bitchat/Services/Courier/CourierStore.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/Courier/CourierStore.swift), which defines the trust tiers and enforcement rules.

```swift
enum CourierDepositTier: String, Codable {
    case favorite        // Mutual favorites – highest priority
    case verified        // Signature-verified announce – limited quota
}

```

The `deposit` method implements the quota checks and eviction strategy:

```swift
func deposit(_ envelope: CourierEnvelope,
             from depositorNoiseKey: Data,
             tier: CourierDepositTier = .favorite) -> Bool {
    // … basic envelope validation omitted …
    return queue.sync {
        pruneExpiredLocked(at: date)

        // Per-depositor quota enforcement
        let perDepositorLimit = tier == .favorite
            ? Limits.maxPerFavoriteDepositor
            : Limits.maxPerVerifiedDepositor
        guard envelopes.filter({ $0.depositorNoiseKey == depositorNoiseKey }).count
                < perDepositorLimit else { return false }

        // Verified-tier global pool limit
        if tier == .verified,
           envelopes.filter({ $0.tier == .verified }).count >= Limits.maxVerifiedEnvelopes {
            return false
        }

        // Global capacity & eviction policy
        if envelopes.count >= Limits.maxEnvelopes {
            if let victim = envelopes.firstIndex(where: { $0.tier == .verified }) {
                envelopes.remove(at: victim)               // evict verified first
            } else if tier == .favorite {
                envelopes.removeFirst()                     // evict oldest favorite
            } else {
                return false                               // reject untrusted deposit
            }
        }

        // Store the new envelope
        envelopes.append(StoredEnvelope(..., tier: tier, ...))
        persistLocked()
        return true
    }
}

```

The `courierEnvelope` message type used for transport is defined in [`localPackages/BitFoundation/Sources/BitFoundation/MessageType.swift`](https://github.com/permissionlesstech/bitchat/blob/main/localPackages/BitFoundation/Sources/BitFoundation/MessageType.swift):

```swift
case courierEnvelope = 0x04 // Store-and-forward envelope carried by a trusted peer

```

## Integration with Identity and Vouch Systems

While `CourierStore` enforces quotas, the trust tier determination happens upstream in the identity layer. The [`SecureIdentityStateManager.swift`](https://github.com/permissionlesstech/bitchat/blob/main/SecureIdentityStateManager.swift) tracks social identities and maps peers to trust levels, while [`ChatVouchCoordinator.swift`](https://github.com/permissionlesstech/bitchat/blob/main/ChatVouchCoordinator.swift) emits notifications when trust relationships change (such as mutual vouching).

When depositing an envelope, the caller determines the tier before invoking the store:

```swift
// Determine peer trust tier based on mutual vouch status
let peerKey = somePeer.noiseStaticKey
let tier: CourierDepositTier = TrustManager.trustTier(for: peerKey)

// Attempt deposit with appropriate tier
let envelope = CourierEnvelope(
    recipientTag: recipientTag,
    expiry: expiryMs,
    ciphertext: encryptedPayload,
    copies: 4,
    prekeyID: nil)

let stored = CourierStore.shared.deposit(envelope,
                                         from: myNoiseKey,
                                         tier: tier)

```

## Summary

- BitChat uses three trust tiers (Favorite, Verified, Untrusted) to govern message envelope deposits in its courier store-and-forward system.
- **Favorite** peers receive generous quotas (5 envelopes each) and eviction protection, while **Verified** peers face strict limits (2 envelopes each, 20 global) and serve as the first eviction candidates.
- The `CourierStore.deposit(_:from:tier:)` method in [`CourierStore.swift`](https://github.com/permissionlesstech/bitchat/blob/main/CourierStore.swift) enforces these limits but does not determine trust; identity managers classify peers before deposit.
- When storage reaches its 40-envelope capacity, the system evicts verified mail first, then oldest favorite mail only if necessary, ensuring trusted communications remain prioritized.

## Frequently Asked Questions

### What happens when the courier store reaches maximum capacity?

When the store holds 40 envelopes (`Limits.maxEnvelopes`), new deposits trigger an eviction sequence. The system first removes the oldest envelope from the verified tier. If no verified envelopes remain and the incoming deposit is favorite-tier, it removes the oldest favorite envelope. Verified deposits are rejected if only favorite envelopes remain, protecting high-trust mail from eviction by lower-trust deposits.

### How does BitChat prevent untrusted peers from depositing envelopes?

Untrusted peers—those without mutual vouch or verified signatures—are rejected before reaching the storage layer. The `deposit` method returns `false` immediately for untrusted tiers, and callers typically check trust status via `SecureIdentityStateManager` before attempting deposits. This prevents malicious actors from consuming any storage resources.

### Can a verified peer upgrade to favorite tier to increase their quota?

Yes. When two peers mutually vouch for each other (tracked in [`ChatVouchCoordinator.swift`](https://github.com/permissionlesstech/bitchat/blob/main/ChatVouchCoordinator.swift)), their trust relationship upgrades to favorite tier. Subsequent deposits use `CourierDepositTier.favorite`, which increases the per-depositor quota from 2 to 5 envelopes and removes the 20-envelope global pool restriction, while also granting eviction protection.

### Where are the trust tiers defined and enforced in the codebase?

The `CourierDepositTier` enum is defined in [`bitchat/Services/Courier/CourierStore.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/Courier/CourierStore.swift), which also contains the `deposit` method that enforces quotas and eviction policies. Trust determination logic resides in [`bitchat/Identity/SecureIdentityStateManager.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Identity/SecureIdentityStateManager.swift), while trust-change notifications emit from [`bitchat/ViewModels/ChatVouchCoordinator.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/ViewModels/ChatVouchCoordinator.swift).