diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactComponent.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactComponent.swift
new file mode 100644
index 0000000000000000000000000000000000000000..160c671feac5b1e7bf16a221259364e7549f50c1
--- /dev/null
+++ b/Examples/xx-messenger/Sources/ContactFeature/ContactComponent.swift
@@ -0,0 +1,273 @@
+import AppCore
+import ChatFeature
+import CheckContactAuthFeature
+import ComposableArchitecture
+import ComposablePresentation
+import ConfirmRequestFeature
+import ContactLookupFeature
+import Foundation
+import ResetAuthFeature
+import SendRequestFeature
+import VerifyContactFeature
+import XCTestDynamicOverlay
+import XXClient
+import XXMessengerClient
+import XXModels
+
+public struct ContactComponent: ReducerProtocol {
+  public struct State: Equatable {
+    public init(
+      id: Data,
+      dbContact: XXModels.Contact? = nil,
+      xxContact: XXClient.Contact? = nil,
+      importUsername: Bool = true,
+      importEmail: Bool = true,
+      importPhone: Bool = true,
+      lookup: ContactLookupComponent.State? = nil,
+      sendRequest: SendRequestComponent.State? = nil,
+      verifyContact: VerifyContactComponent.State? = nil,
+      confirmRequest: ConfirmRequestComponent.State? = nil,
+      checkAuth: CheckContactAuthComponent.State? = nil,
+      resetAuth: ResetAuthComponent.State? = nil,
+      chat: ChatComponent.State? = nil
+    ) {
+      self.id = id
+      self.dbContact = dbContact
+      self.xxContact = xxContact
+      self.importUsername = importUsername
+      self.importEmail = importEmail
+      self.importPhone = importPhone
+      self.lookup = lookup
+      self.sendRequest = sendRequest
+      self.verifyContact = verifyContact
+      self.confirmRequest = confirmRequest
+      self.checkAuth = checkAuth
+      self.resetAuth = resetAuth
+      self.chat = chat
+    }
+
+    public var id: Data
+    public var dbContact: XXModels.Contact?
+    public var xxContact: XXClient.Contact?
+    @BindableState public var importUsername: Bool
+    @BindableState public var importEmail: Bool
+    @BindableState public var importPhone: Bool
+    public var lookup: ContactLookupComponent.State?
+    public var sendRequest: SendRequestComponent.State?
+    public var verifyContact: VerifyContactComponent.State?
+    public var confirmRequest: ConfirmRequestComponent.State?
+    public var checkAuth: CheckContactAuthComponent.State?
+    public var resetAuth: ResetAuthComponent.State?
+    public var chat: ChatComponent.State?
+  }
+
+  public enum Action: Equatable, BindableAction {
+    case start
+    case dbContactFetched(XXModels.Contact?)
+    case importFactsTapped
+    case lookupTapped
+    case lookupDismissed
+    case lookup(ContactLookupComponent.Action)
+    case sendRequestTapped
+    case sendRequestDismissed
+    case sendRequest(SendRequestComponent.Action)
+    case verifyContactTapped
+    case verifyContactDismissed
+    case verifyContact(VerifyContactComponent.Action)
+    case checkAuthTapped
+    case checkAuthDismissed
+    case checkAuth(CheckContactAuthComponent.Action)
+    case confirmRequestTapped
+    case confirmRequestDismissed
+    case confirmRequest(ConfirmRequestComponent.Action)
+    case resetAuthTapped
+    case resetAuthDismissed
+    case resetAuth(ResetAuthComponent.Action)
+    case chatTapped
+    case chatDismissed
+    case chat(ChatComponent.Action)
+    case binding(BindingAction<State>)
+  }
+
+  public init() {}
+
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.dbManager.getDB) var db: DBManagerGetDB
+  @Dependency(\.app.mainQueue) var mainQueue: AnySchedulerOf<DispatchQueue>
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
+
+  public var body: some ReducerProtocol<State, Action> {
+    BindingReducer()
+    Reduce { state, action in
+      enum DBFetchEffectID {}
+
+      switch action {
+      case .start:
+        return try! db().fetchContactsPublisher(.init(id: [state.id]))
+          .assertNoFailure()
+          .map(\.first)
+          .map(Action.dbContactFetched)
+          .subscribe(on: bgQueue)
+          .receive(on: mainQueue)
+          .eraseToEffect()
+          .cancellable(id: DBFetchEffectID.self, cancelInFlight: true)
+
+      case .dbContactFetched(let contact):
+        state.dbContact = contact
+        return .none
+
+      case .importFactsTapped:
+        guard let xxContact = state.xxContact else { return .none }
+        return .fireAndForget { [state] in
+          var dbContact = state.dbContact ?? XXModels.Contact(id: state.id)
+          dbContact.marshaled = xxContact.data
+          if state.importUsername {
+            dbContact.username = try? xxContact.getFact(.username)?.value
+          }
+          if state.importEmail {
+            dbContact.email = try? xxContact.getFact(.email)?.value
+          }
+          if state.importPhone {
+            dbContact.phone = try? xxContact.getFact(.phone)?.value
+          }
+          _ = try! db().saveContact(dbContact)
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+
+      case .lookupTapped:
+        state.lookup = ContactLookupComponent.State(id: state.id)
+        return .none
+
+      case .lookupDismissed:
+        state.lookup = nil
+        return .none
+
+      case .lookup(.didLookup(let xxContact)):
+        state.xxContact = xxContact
+        state.lookup = nil
+        return .none
+
+      case .sendRequestTapped:
+        if let xxContact = state.xxContact {
+          state.sendRequest = SendRequestComponent.State(contact: xxContact)
+        } else if let marshaled = state.dbContact?.marshaled {
+          state.sendRequest = SendRequestComponent.State(contact: .live(marshaled))
+        }
+        return .none
+
+      case .sendRequestDismissed:
+        state.sendRequest = nil
+        return .none
+
+      case .sendRequest(.sendSucceeded):
+        state.sendRequest = nil
+        return .none
+
+      case .verifyContactTapped:
+        if let marshaled = state.dbContact?.marshaled {
+          state.verifyContact = VerifyContactComponent.State(
+            contact: .live(marshaled)
+          )
+        }
+        return .none
+
+      case .verifyContactDismissed:
+        state.verifyContact = nil
+        return .none
+
+      case .checkAuthTapped:
+        if let marshaled = state.dbContact?.marshaled {
+          state.checkAuth = CheckContactAuthComponent.State(
+            contact: .live(marshaled)
+          )
+        }
+        return .none
+
+      case .checkAuthDismissed:
+        state.checkAuth = nil
+        return .none
+
+      case .confirmRequestTapped:
+        if let marshaled = state.dbContact?.marshaled {
+          state.confirmRequest = ConfirmRequestComponent.State(
+            contact: .live(marshaled)
+          )
+        }
+        return .none
+
+      case .confirmRequestDismissed:
+        state.confirmRequest = nil
+        return .none
+
+      case .chatTapped:
+        state.chat = ChatComponent.State(id: .contact(state.id))
+        return .none
+
+      case .chatDismissed:
+        state.chat = nil
+        return .none
+
+      case .resetAuthTapped:
+        if let marshaled = state.dbContact?.marshaled {
+          state.resetAuth = ResetAuthComponent.State(
+            partner: .live(marshaled)
+          )
+        }
+        return .none
+
+      case .resetAuthDismissed:
+        state.resetAuth = nil
+        return .none
+
+      case .binding(_), .lookup(_), .sendRequest(_),
+          .verifyContact(_), .confirmRequest(_),
+          .checkAuth(_), .resetAuth(_), .chat(_):
+        return .none
+      }
+    }
+    .presenting(
+      state: .keyPath(\.lookup),
+      id: .notNil(),
+      action: /ContactComponent.Action.lookup,
+      presented: { ContactLookupComponent() }
+    )
+    .presenting(
+      state: .keyPath(\.sendRequest),
+      id: .notNil(),
+      action: /ContactComponent.Action.sendRequest,
+      presented: { SendRequestComponent() }
+    )
+    .presenting(
+      state: .keyPath(\.verifyContact),
+      id: .notNil(),
+      action: /ContactComponent.Action.verifyContact,
+      presented: { VerifyContactComponent() }
+    )
+    .presenting(
+      state: .keyPath(\.confirmRequest),
+      id: .notNil(),
+      action: /ContactComponent.Action.confirmRequest,
+      presented: { ConfirmRequestComponent() }
+    )
+    .presenting(
+      state: .keyPath(\.checkAuth),
+      id: .notNil(),
+      action: /ContactComponent.Action.checkAuth,
+      presented: { CheckContactAuthComponent() }
+    )
+    .presenting(
+      state: .keyPath(\.resetAuth),
+      id: .notNil(),
+      action: /ContactComponent.Action.resetAuth,
+      presented: { ResetAuthComponent() }
+    )
+    .presenting(
+      state: .keyPath(\.chat),
+      id: .keyPath(\.?.id),
+      action: /ContactComponent.Action.chat,
+      presented: { ChatComponent() }
+    )
+  }
+}
diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift
deleted file mode 100644
index be66fc8dfc8f59f7f2e20e1a1899a23da10106f6..0000000000000000000000000000000000000000
--- a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift
+++ /dev/null
@@ -1,328 +0,0 @@
-import AppCore
-import ChatFeature
-import CheckContactAuthFeature
-import ComposableArchitecture
-import ComposablePresentation
-import ConfirmRequestFeature
-import ContactLookupFeature
-import Foundation
-import ResetAuthFeature
-import SendRequestFeature
-import VerifyContactFeature
-import XCTestDynamicOverlay
-import XXClient
-import XXMessengerClient
-import XXModels
-
-public struct ContactState: Equatable {
-  public init(
-    id: Data,
-    dbContact: XXModels.Contact? = nil,
-    xxContact: XXClient.Contact? = nil,
-    importUsername: Bool = true,
-    importEmail: Bool = true,
-    importPhone: Bool = true,
-    lookup: ContactLookupState? = nil,
-    sendRequest: SendRequestState? = nil,
-    verifyContact: VerifyContactState? = nil,
-    confirmRequest: ConfirmRequestState? = nil,
-    checkAuth: CheckContactAuthState? = nil,
-    resetAuth: ResetAuthState? = nil,
-    chat: ChatState? = nil
-  ) {
-    self.id = id
-    self.dbContact = dbContact
-    self.xxContact = xxContact
-    self.importUsername = importUsername
-    self.importEmail = importEmail
-    self.importPhone = importPhone
-    self.lookup = lookup
-    self.sendRequest = sendRequest
-    self.verifyContact = verifyContact
-    self.confirmRequest = confirmRequest
-    self.checkAuth = checkAuth
-    self.resetAuth = resetAuth
-    self.chat = chat
-  }
-
-  public var id: Data
-  public var dbContact: XXModels.Contact?
-  public var xxContact: XXClient.Contact?
-  @BindableState public var importUsername: Bool
-  @BindableState public var importEmail: Bool
-  @BindableState public var importPhone: Bool
-  public var lookup: ContactLookupState?
-  public var sendRequest: SendRequestState?
-  public var verifyContact: VerifyContactState?
-  public var confirmRequest: ConfirmRequestState?
-  public var checkAuth: CheckContactAuthState?
-  public var resetAuth: ResetAuthState?
-  public var chat: ChatState?
-}
-
-public enum ContactAction: Equatable, BindableAction {
-  case start
-  case dbContactFetched(XXModels.Contact?)
-  case importFactsTapped
-  case lookupTapped
-  case lookupDismissed
-  case lookup(ContactLookupAction)
-  case sendRequestTapped
-  case sendRequestDismissed
-  case sendRequest(SendRequestAction)
-  case verifyContactTapped
-  case verifyContactDismissed
-  case verifyContact(VerifyContactAction)
-  case checkAuthTapped
-  case checkAuthDismissed
-  case checkAuth(CheckContactAuthAction)
-  case confirmRequestTapped
-  case confirmRequestDismissed
-  case confirmRequest(ConfirmRequestAction)
-  case resetAuthTapped
-  case resetAuthDismissed
-  case resetAuth(ResetAuthAction)
-  case chatTapped
-  case chatDismissed
-  case chat(ChatAction)
-  case binding(BindingAction<ContactState>)
-}
-
-public struct ContactEnvironment {
-  public init(
-    messenger: Messenger,
-    db: DBManagerGetDB,
-    mainQueue: AnySchedulerOf<DispatchQueue>,
-    bgQueue: AnySchedulerOf<DispatchQueue>,
-    lookup: @escaping () -> ContactLookupEnvironment,
-    sendRequest: @escaping () -> SendRequestEnvironment,
-    verifyContact: @escaping () -> VerifyContactEnvironment,
-    confirmRequest: @escaping () -> ConfirmRequestEnvironment,
-    checkAuth: @escaping () -> CheckContactAuthEnvironment,
-    resetAuth: @escaping () -> ResetAuthEnvironment,
-    chat: @escaping () -> ChatEnvironment
-  ) {
-    self.messenger = messenger
-    self.db = db
-    self.mainQueue = mainQueue
-    self.bgQueue = bgQueue
-    self.lookup = lookup
-    self.sendRequest = sendRequest
-    self.verifyContact = verifyContact
-    self.confirmRequest = confirmRequest
-    self.checkAuth = checkAuth
-    self.resetAuth = resetAuth
-    self.chat = chat
-  }
-
-  public var messenger: Messenger
-  public var db: DBManagerGetDB
-  public var mainQueue: AnySchedulerOf<DispatchQueue>
-  public var bgQueue: AnySchedulerOf<DispatchQueue>
-  public var lookup: () -> ContactLookupEnvironment
-  public var sendRequest: () -> SendRequestEnvironment
-  public var verifyContact: () -> VerifyContactEnvironment
-  public var confirmRequest: () -> ConfirmRequestEnvironment
-  public var checkAuth: () -> CheckContactAuthEnvironment
-  public var resetAuth: () -> ResetAuthEnvironment
-  public var chat: () -> ChatEnvironment
-}
-
-#if DEBUG
-extension ContactEnvironment {
-  public static let unimplemented = ContactEnvironment(
-    messenger: .unimplemented,
-    db: .unimplemented,
-    mainQueue: .unimplemented,
-    bgQueue: .unimplemented,
-    lookup: { .unimplemented },
-    sendRequest: { .unimplemented },
-    verifyContact: { .unimplemented },
-    confirmRequest: { .unimplemented },
-    checkAuth: { .unimplemented },
-    resetAuth: { .unimplemented },
-    chat: { .unimplemented }
-  )
-}
-#endif
-
-public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironment>
-{ state, action, env in
-  enum DBFetchEffectID {}
-
-  switch action {
-  case .start:
-    return try! env.db().fetchContactsPublisher(.init(id: [state.id]))
-      .assertNoFailure()
-      .map(\.first)
-      .map(ContactAction.dbContactFetched)
-      .subscribe(on: env.bgQueue)
-      .receive(on: env.mainQueue)
-      .eraseToEffect()
-      .cancellable(id: DBFetchEffectID.self, cancelInFlight: true)
-
-  case .dbContactFetched(let contact):
-    state.dbContact = contact
-    return .none
-
-  case .importFactsTapped:
-    guard let xxContact = state.xxContact else { return .none }
-    return .fireAndForget { [state] in
-      var dbContact = state.dbContact ?? XXModels.Contact(id: state.id)
-      dbContact.marshaled = xxContact.data
-      if state.importUsername {
-        dbContact.username = try? xxContact.getFact(.username)?.value
-      }
-      if state.importEmail {
-        dbContact.email = try? xxContact.getFact(.email)?.value
-      }
-      if state.importPhone {
-        dbContact.phone = try? xxContact.getFact(.phone)?.value
-      }
-      _ = try! env.db().saveContact(dbContact)
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .lookupTapped:
-    state.lookup = ContactLookupState(id: state.id)
-    return .none
-
-  case .lookupDismissed:
-    state.lookup = nil
-    return .none
-
-  case .lookup(.didLookup(let xxContact)):
-    state.xxContact = xxContact
-    state.lookup = nil
-    return .none
-
-  case .sendRequestTapped:
-    if let xxContact = state.xxContact {
-      state.sendRequest = SendRequestState(contact: xxContact)
-    } else if let marshaled = state.dbContact?.marshaled {
-      state.sendRequest = SendRequestState(contact: .live(marshaled))
-    }
-    return .none
-
-  case .sendRequestDismissed:
-    state.sendRequest = nil
-    return .none
-
-  case .sendRequest(.sendSucceeded):
-    state.sendRequest = nil
-    return .none
-
-  case .verifyContactTapped:
-    if let marshaled = state.dbContact?.marshaled {
-      state.verifyContact = VerifyContactState(
-        contact: .live(marshaled)
-      )
-    }
-    return .none
-
-  case .verifyContactDismissed:
-    state.verifyContact = nil
-    return .none
-
-  case .checkAuthTapped:
-    if let marshaled = state.dbContact?.marshaled {
-      state.checkAuth = CheckContactAuthState(
-        contact: .live(marshaled)
-      )
-    }
-    return .none
-
-  case .checkAuthDismissed:
-    state.checkAuth = nil
-    return .none
-
-  case .confirmRequestTapped:
-    if let marshaled = state.dbContact?.marshaled {
-      state.confirmRequest = ConfirmRequestState(
-        contact: .live(marshaled)
-      )
-    }
-    return .none
-
-  case .confirmRequestDismissed:
-    state.confirmRequest = nil
-    return .none
-
-  case .chatTapped:
-    state.chat = ChatState(id: .contact(state.id))
-    return .none
-
-  case .chatDismissed:
-    state.chat = nil
-    return .none
-
-  case .resetAuthTapped:
-    if let marshaled = state.dbContact?.marshaled {
-      state.resetAuth = ResetAuthState(
-        partner: .live(marshaled)
-      )
-    }
-    return .none
-
-  case .resetAuthDismissed:
-    state.resetAuth = nil
-    return .none
-
-  case .binding(_), .lookup(_), .sendRequest(_),
-      .verifyContact(_), .confirmRequest(_),
-      .checkAuth(_), .resetAuth(_), .chat(_):
-    return .none
-  }
-}
-.binding()
-.presenting(
-  contactLookupReducer,
-  state: .keyPath(\.lookup),
-  id: .notNil(),
-  action: /ContactAction.lookup,
-  environment: { $0.lookup() }
-)
-.presenting(
-  sendRequestReducer,
-  state: .keyPath(\.sendRequest),
-  id: .notNil(),
-  action: /ContactAction.sendRequest,
-  environment: { $0.sendRequest() }
-)
-.presenting(
-  verifyContactReducer,
-  state: .keyPath(\.verifyContact),
-  id: .notNil(),
-  action: /ContactAction.verifyContact,
-  environment: { $0.verifyContact() }
-)
-.presenting(
-  confirmRequestReducer,
-  state: .keyPath(\.confirmRequest),
-  id: .notNil(),
-  action: /ContactAction.confirmRequest,
-  environment: { $0.confirmRequest() }
-)
-.presenting(
-  checkContactAuthReducer,
-  state: .keyPath(\.checkAuth),
-  id: .notNil(),
-  action: /ContactAction.checkAuth,
-  environment: { $0.checkAuth() }
-)
-.presenting(
-  resetAuthReducer,
-  state: .keyPath(\.resetAuth),
-  id: .notNil(),
-  action: /ContactAction.resetAuth,
-  environment: { $0.resetAuth() }
-)
-.presenting(
-  chatReducer,
-  state: .keyPath(\.chat),
-  id: .keyPath(\.?.id),
-  action: /ContactAction.chat,
-  environment: { $0.chat() }
-)
diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift
index 7da763e03748536aabb0cc99698c2edd0ee0fba4..1cbf0e91bdf20a090838fd770861a9120825afba 100644
--- a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift
+++ b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift
@@ -13,11 +13,11 @@ import XXClient
 import XXModels
 
 public struct ContactView: View {
-  public init(store: Store<ContactState, ContactAction>) {
+  public init(store: StoreOf<ContactComponent>) {
     self.store = store
   }
 
-  let store: Store<ContactState, ContactAction>
+  let store: StoreOf<ContactComponent>
 
   struct ViewState: Equatable {
     var dbContact: XXModels.Contact?
@@ -35,7 +35,7 @@ public struct ContactView: View {
     var canCheckAuthorization: Bool
     var canResetAuthorization: Bool
 
-    init(state: ContactState) {
+    init(state: ContactComponent.State) {
       dbContact = state.dbContact
       xxContactIsSet = state.xxContact != nil
       xxContactUsername = try? state.xxContact?.getFact(.username)?.value
@@ -217,7 +217,7 @@ public struct ContactView: View {
       .background(NavigationLinkWithStore(
         store.scope(
           state: \.lookup,
-          action: ContactAction.lookup
+          action: ContactComponent.Action.lookup
         ),
         mapState: replayNonNil(),
         onDeactivate: { viewStore.send(.lookupDismissed) },
@@ -226,7 +226,7 @@ public struct ContactView: View {
       .background(NavigationLinkWithStore(
         store.scope(
           state: \.sendRequest,
-          action: ContactAction.sendRequest
+          action: ContactComponent.Action.sendRequest
         ),
         mapState: replayNonNil(),
         onDeactivate: { viewStore.send(.sendRequestDismissed) },
@@ -235,7 +235,7 @@ public struct ContactView: View {
       .background(NavigationLinkWithStore(
         store.scope(
           state: \.verifyContact,
-          action: ContactAction.verifyContact
+          action: ContactComponent.Action.verifyContact
         ),
         onDeactivate: { viewStore.send(.verifyContactDismissed) },
         destination: VerifyContactView.init(store:)
@@ -243,7 +243,7 @@ public struct ContactView: View {
       .background(NavigationLinkWithStore(
         store.scope(
           state: \.confirmRequest,
-          action: ContactAction.confirmRequest
+          action: ContactComponent.Action.confirmRequest
         ),
         onDeactivate: { viewStore.send(.confirmRequestDismissed) },
         destination: ConfirmRequestView.init(store:)
@@ -251,7 +251,7 @@ public struct ContactView: View {
       .background(NavigationLinkWithStore(
         store.scope(
           state: \.checkAuth,
-          action: ContactAction.checkAuth
+          action: ContactComponent.Action.checkAuth
         ),
         onDeactivate: { viewStore.send(.checkAuthDismissed) },
         destination: CheckContactAuthView.init(store:)
@@ -259,7 +259,7 @@ public struct ContactView: View {
       .background(NavigationLinkWithStore(
         store.scope(
           state: \.resetAuth,
-          action: ContactAction.resetAuth
+          action: ContactComponent.Action.resetAuth
         ),
         onDeactivate: { viewStore.send(.resetAuthDismissed) },
         destination: ResetAuthView.init(store:)
@@ -267,7 +267,7 @@ public struct ContactView: View {
       .background(NavigationLinkWithStore(
         store.scope(
           state: \.chat,
-          action: ContactAction.chat
+          action: ContactComponent.Action.chat
         ),
         onDeactivate: { viewStore.send(.chatDismissed) },
         destination: ChatView.init(store:)
@@ -280,11 +280,10 @@ public struct ContactView: View {
 public struct ContactView_Previews: PreviewProvider {
   public static var previews: some View {
     ContactView(store: Store(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: "contact-id".data(using: .utf8)!
       ),
-      reducer: .empty,
-      environment: ()
+      reducer: EmptyReducer()
     ))
   }
 }
diff --git a/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactComponentTests.swift
similarity index 70%
rename from Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift
rename to Examples/xx-messenger/Tests/ContactFeatureTests/ContactComponentTests.swift
index eba41b7ab57d1dddfc0827747760a9bce224bdab..04caf49dbcb5205ee5dd081398983c72a6694011 100644
--- a/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactComponentTests.swift
@@ -16,19 +16,18 @@ import XXModels
 final class ContactFeatureTests: XCTestCase {
   func testStart() {
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: "contact-id".data(using: .utf8)!
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     var dbDidFetchContacts: [XXModels.Contact.Query] = []
     let dbContactsPublisher = PassthroughSubject<[XXModels.Contact], Error>()
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.db.run = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.dbManager.getDB.run = {
       var db: Database = .unimplemented
       db.fetchContactsPublisher.run = { query in
         dbDidFetchContacts.append(query)
@@ -68,20 +67,19 @@ final class ContactFeatureTests: XCTestCase {
     }
 
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: "contact-id".data(using: .utf8)!,
         dbContact: dbContact,
         xxContact: xxContact
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     var dbDidSaveContact: [XXModels.Contact] = []
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.db.run = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.dbManager.getDB.run = {
       var db: Database = .unimplemented
       db.saveContact.run = { contact in
         dbDidSaveContact.append(contact)
@@ -104,27 +102,25 @@ final class ContactFeatureTests: XCTestCase {
   func testLookupTapped() {
     let contactId = "contact-id".data(using: .utf8)!
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: contactId
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.lookupTapped) {
-      $0.lookup = ContactLookupState(id: contactId)
+      $0.lookup = ContactLookupComponent.State(id: contactId)
     }
   }
 
   func testLookupDismissed() {
     let contactId = "contact-id".data(using: .utf8)!
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: contactId,
-        lookup: ContactLookupState(id: contactId)
+        lookup: ContactLookupComponent.State(id: contactId)
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.lookupDismissed) {
@@ -136,12 +132,11 @@ final class ContactFeatureTests: XCTestCase {
     let contactId = "contact-id".data(using: .utf8)!
     let contact = Contact.unimplemented("contact-data".data(using: .utf8)!)
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: contactId,
-        lookup: ContactLookupState(id: contactId)
+        lookup: ContactLookupComponent.State(id: contactId)
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.lookup(.didLookup(contact))) {
@@ -155,16 +150,15 @@ final class ContactFeatureTests: XCTestCase {
     dbContact.marshaled = "contact-data".data(using: .utf8)!
 
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: dbContact.id,
         dbContact: dbContact
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.sendRequestTapped) {
-      $0.sendRequest = SendRequestState(contact: .live(dbContact.marshaled!))
+      $0.sendRequest = SendRequestComponent.State(contact: .live(dbContact.marshaled!))
     }
   }
 
@@ -172,29 +166,27 @@ final class ContactFeatureTests: XCTestCase {
     let xxContact = XXClient.Contact.unimplemented("contact-id".data(using: .utf8)!)
 
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: "contact-id".data(using: .utf8)!,
         xxContact: xxContact
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.sendRequestTapped) {
-      $0.sendRequest = SendRequestState(contact: xxContact)
+      $0.sendRequest = SendRequestComponent.State(contact: xxContact)
     }
   }
 
   func testSendRequestDismissed() {
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: "contact-id".data(using: .utf8)!,
-        sendRequest: SendRequestState(
+        sendRequest: SendRequestComponent.State(
           contact: .unimplemented("contact-id".data(using: .utf8)!)
         )
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.sendRequestDismissed) {
@@ -204,14 +196,13 @@ final class ContactFeatureTests: XCTestCase {
 
   func testSendRequestSucceeded() {
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: "contact-id".data(using: .utf8)!,
-        sendRequest: SendRequestState(
+        sendRequest: SendRequestComponent.State(
           contact: .unimplemented("contact-id".data(using: .utf8)!)
         )
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.sendRequest(.sendSucceeded)) {
@@ -222,19 +213,18 @@ final class ContactFeatureTests: XCTestCase {
   func testVerifyContactTapped() {
     let contactData = "contact-data".data(using: .utf8)!
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: Data(),
         dbContact: XXModels.Contact(
           id: Data(),
           marshaled: contactData
         )
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.verifyContactTapped) {
-      $0.verifyContact = VerifyContactState(
+      $0.verifyContact = VerifyContactComponent.State(
         contact: .unimplemented(contactData)
       )
     }
@@ -242,14 +232,13 @@ final class ContactFeatureTests: XCTestCase {
 
   func testVerifyContactDismissed() {
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: "contact-id".data(using: .utf8)!,
-        verifyContact: VerifyContactState(
+        verifyContact: VerifyContactComponent.State(
           contact: .unimplemented("contact-data".data(using: .utf8)!)
         )
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.verifyContactDismissed) {
@@ -260,19 +249,18 @@ final class ContactFeatureTests: XCTestCase {
   func testCheckAuthTapped() {
     let contactData = "contact-data".data(using: .utf8)!
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: Data(),
         dbContact: XXModels.Contact(
           id: Data(),
           marshaled: contactData
         )
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.checkAuthTapped) {
-      $0.checkAuth = CheckContactAuthState(
+      $0.checkAuth = CheckContactAuthComponent.State(
         contact: .unimplemented(contactData)
       )
     }
@@ -280,14 +268,13 @@ final class ContactFeatureTests: XCTestCase {
 
   func testCheckAuthDismissed() {
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: "contact-id".data(using: .utf8)!,
-        checkAuth: CheckContactAuthState(
+        checkAuth: CheckContactAuthComponent.State(
           contact: .unimplemented("contact-data".data(using: .utf8)!)
         )
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.checkAuthDismissed) {
@@ -298,19 +285,18 @@ final class ContactFeatureTests: XCTestCase {
   func testResetAuthTapped() {
     let contactData = "contact-data".data(using: .utf8)!
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: Data(),
         dbContact: XXModels.Contact(
           id: Data(),
           marshaled: contactData
         )
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.resetAuthTapped) {
-      $0.resetAuth = ResetAuthState(
+      $0.resetAuth = ResetAuthComponent.State(
         partner: .unimplemented(contactData)
       )
     }
@@ -318,14 +304,13 @@ final class ContactFeatureTests: XCTestCase {
 
   func testResetAuthDismissed() {
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: Data(),
-        resetAuth: ResetAuthState(
+        resetAuth: ResetAuthComponent.State(
           partner: .unimplemented(Data())
         )
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.resetAuthDismissed) {
@@ -336,19 +321,18 @@ final class ContactFeatureTests: XCTestCase {
   func testConfirmRequestTapped() {
     let contactData = "contact-data".data(using: .utf8)!
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: Data(),
         dbContact: XXModels.Contact(
           id: Data(),
           marshaled: contactData
         )
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.confirmRequestTapped) {
-      $0.confirmRequest = ConfirmRequestState(
+      $0.confirmRequest = ConfirmRequestComponent.State(
         contact: .unimplemented(contactData)
       )
     }
@@ -356,14 +340,13 @@ final class ContactFeatureTests: XCTestCase {
 
   func testConfirmRequestDismissed() {
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: "contact-id".data(using: .utf8)!,
-        confirmRequest: ConfirmRequestState(
+        confirmRequest: ConfirmRequestComponent.State(
           contact: .unimplemented("contact-data".data(using: .utf8)!)
         )
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.confirmRequestDismissed) {
@@ -374,26 +357,24 @@ final class ContactFeatureTests: XCTestCase {
   func testChatTapped() {
     let contactId = "contact-id".data(using: .utf8)!
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: contactId
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.chatTapped) {
-      $0.chat = ChatState(id: .contact(contactId))
+      $0.chat = ChatComponent.State(id: .contact(contactId))
     }
   }
 
   func testChatDismissed() {
     let store = TestStore(
-      initialState: ContactState(
+      initialState: ContactComponent.State(
         id: "contact-id".data(using: .utf8)!,
-        chat: ChatState(id: .contact("contact-id".data(using: .utf8)!))
+        chat: ChatComponent.State(id: .contact("contact-id".data(using: .utf8)!))
       ),
-      reducer: contactReducer,
-      environment: .unimplemented
+      reducer: ContactComponent()
     )
 
     store.send(.chatDismissed) {