From fdbe65e045d6932f85ac88992605f4a74731f38a Mon Sep 17 00:00:00 2001
From: bkioshn <35752733+bkioshn@users.noreply.github.com>
Date: Wed, 17 Jan 2024 17:49:49 +0700
Subject: [PATCH 1/4] fix: openapi info section (#209)

* feat: add openapi linter

* fix(lint): openapi linting

* fix(spectral): add version for CDN

* fix(openapi): linting openAPI files in test stage

* fix: make the info section compatible with v3.0.0

* style: format rust

* fix: remove openapi linter

* style: remove EOF line
---
 catalyst-gateway/bin/src/service/api/mod.rs | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/catalyst-gateway/bin/src/service/api/mod.rs b/catalyst-gateway/bin/src/service/api/mod.rs
index a093589b448..ed573a9ae75 100644
--- a/catalyst-gateway/bin/src/service/api/mod.rs
+++ b/catalyst-gateway/bin/src/service/api/mod.rs
@@ -31,9 +31,6 @@ fn get_api_contact() -> ContactObject {
         .url("https://projectcatalyst.io")
 }
 
-/// A summary describing the API
-const API_SUMMARY: &str = "Project Catalyst Gateway API";
-
 /// A long description of the API. Markdown is supported
 const API_DESCRIPTION: &str = r#"# Catalyst Gateway API.
 
@@ -51,9 +48,7 @@ TODO:
 
 /// Get the license details for the API
 fn get_api_license() -> LicenseObject {
-    LicenseObject::new("Apache 2.0")
-        .url("https://www.apache.org/licenses/LICENSE-2.0")
-        .identifier("Apache-2.0")
+    LicenseObject::new("Apache 2.0").url("https://www.apache.org/licenses/LICENSE-2.0")
 }
 
 /// Get the terms of service for the API
@@ -72,7 +67,6 @@ pub(crate) fn mk_api(
     .contact(get_api_contact())
     .description(API_DESCRIPTION)
     .license(get_api_license())
-    .summary(API_SUMMARY)
     .terms_of_service(TERMS_OF_SERVICE)
     .url_prefix(API_URL_PREFIX.as_str());
 

From e4dbaf675dd789a2bb3cc76b5a6a955f0bc73f2a Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 22 Jan 2024 17:30:44 +0700
Subject: [PATCH 2/4] chore(deps): bump h2 from 0.3.21 to 0.3.24 in
 /catalyst-gateway (#213)

Bumps [h2](https://github.com/hyperium/h2) from 0.3.21 to 0.3.24.
- [Release notes](https://github.com/hyperium/h2/releases)
- [Changelog](https://github.com/hyperium/h2/blob/v0.3.24/CHANGELOG.md)
- [Commits](https://github.com/hyperium/h2/compare/v0.3.21...v0.3.24)

---
updated-dependencies:
- dependency-name: h2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 catalyst-gateway/Cargo.lock | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/catalyst-gateway/Cargo.lock b/catalyst-gateway/Cargo.lock
index 94082010733..c038dc65b51 100644
--- a/catalyst-gateway/Cargo.lock
+++ b/catalyst-gateway/Cargo.lock
@@ -867,9 +867,9 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
 
 [[package]]
 name = "h2"
-version = "0.3.21"
+version = "0.3.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833"
+checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
 dependencies = [
  "bytes",
  "fnv",
@@ -877,7 +877,7 @@ dependencies = [
  "futures-sink",
  "futures-util",
  "http",
- "indexmap 1.9.3",
+ "indexmap 2.0.2",
  "slab",
  "tokio",
  "tokio-util",

From 6181d2174c2f992285bf8c58f192f60f3ed5fdc1 Mon Sep 17 00:00:00 2001
From: Oleksandr Prokhorenko <djminikin@gmail.com>
Date: Tue, 23 Jan 2024 08:50:35 +0100
Subject: [PATCH 3/4] feat(frontend): add dependencies injection configurations
 (#215)

---
 catalyst_voices/ios/Podfile.lock              |  6 ++
 catalyst_voices/lib/app/view/app_content.dart | 31 ++++++---
 catalyst_voices/lib/app/view/app_page.dart    | 56 +++++++---------
 .../lib/pages/login/login_page.dart           | 16 +----
 .../lib/src/catalyst_voices_blocs.dart        |  1 +
 .../lib/src/dependency/dependency.dart        | 46 +++++++++++++
 .../src/dependency/dependency_provider.dart   | 64 +++++++++++++++++++
 .../catalyst_voices_blocs/pubspec.yaml        |  3 +
 .../lib/src/authentication_repository.dart    | 10 +--
 melos.yaml                                    |  4 +-
 10 files changed, 173 insertions(+), 64 deletions(-)
 create mode 100644 catalyst_voices/packages/catalyst_voices_blocs/lib/src/dependency/dependency.dart
 create mode 100644 catalyst_voices/packages/catalyst_voices_blocs/lib/src/dependency/dependency_provider.dart

diff --git a/catalyst_voices/ios/Podfile.lock b/catalyst_voices/ios/Podfile.lock
index 6404e6eb675..21ca313d8b4 100644
--- a/catalyst_voices/ios/Podfile.lock
+++ b/catalyst_voices/ios/Podfile.lock
@@ -7,12 +7,15 @@ PODS:
   - path_provider_foundation (0.0.1):
     - Flutter
     - FlutterMacOS
+  - url_launcher_ios (0.0.1):
+    - Flutter
 
 DEPENDENCIES:
   - Flutter (from `Flutter`)
   - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
   - integration_test (from `.symlinks/plugins/integration_test/ios`)
   - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
+  - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
 
 EXTERNAL SOURCES:
   Flutter:
@@ -23,12 +26,15 @@ EXTERNAL SOURCES:
     :path: ".symlinks/plugins/integration_test/ios"
   path_provider_foundation:
     :path: ".symlinks/plugins/path_provider_foundation/darwin"
+  url_launcher_ios:
+    :path: ".symlinks/plugins/url_launcher_ios/ios"
 
 SPEC CHECKSUMS:
   Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
   flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
   integration_test: 13825b8a9334a850581300559b8839134b124670
   path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
+  url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b
 
 PODFILE CHECKSUM: ff9ae414ffbc80ad6f9d2058e299051a15f6eca7
 
diff --git a/catalyst_voices/lib/app/view/app_content.dart b/catalyst_voices/lib/app/view/app_content.dart
index c8b23616ee7..e2874ecec21 100644
--- a/catalyst_voices/lib/app/view/app_content.dart
+++ b/catalyst_voices/lib/app/view/app_content.dart
@@ -4,28 +4,33 @@ import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_localized_locales/flutter_localized_locales.dart';
+import 'package:go_router/go_router.dart';
+
+const _restorationScopeId = 'rootVoices';
 
 final class AppContent extends StatelessWidget {
   const AppContent({super.key});
 
+  List<LocalizationsDelegate<dynamic>> get _localizationsDelegates {
+    return const [
+      ...VoicesLocalizations.localizationsDelegates,
+      LocaleNamesLocalizationsDelegate(),
+    ];
+  }
+
   @override
   Widget build(BuildContext context) {
+    final l10n = context.l10n;
     return BlocListener<AuthenticationBloc, AuthenticationState>(
       listener: (context, state) {},
       child: MaterialApp.router(
-        restorationScopeId: 'rootVoices',
-        localizationsDelegates: const [
-          ...VoicesLocalizations.localizationsDelegates,
-          LocaleNamesLocalizationsDelegate(),
-        ],
+        restorationScopeId: _restorationScopeId,
+        localizationsDelegates: _localizationsDelegates,
         supportedLocales: VoicesLocalizations.supportedLocales,
         localeListResolutionCallback: basicLocaleListResolution,
-        routerConfig: AppRouter.init(
-          authenticationBloc: context.read<AuthenticationBloc>(),
-        ),
-        title: 'Catalyst Voices',
+        routerConfig: _routeConfig(context),
+        title: l10n.homeScreenText,
         theme: ThemeData(
-          useMaterial3: true,
           brightness: Brightness.dark,
           bottomNavigationBarTheme: const BottomNavigationBarThemeData(
             type: BottomNavigationBarType.fixed,
@@ -34,4 +39,10 @@ final class AppContent extends StatelessWidget {
       ),
     );
   }
+
+  GoRouter _routeConfig(BuildContext context) {
+    return AppRouter.init(
+      authenticationBloc: context.read<AuthenticationBloc>(),
+    );
+  }
 }
diff --git a/catalyst_voices/lib/app/view/app_page.dart b/catalyst_voices/lib/app/view/app_page.dart
index 71628b90fb1..8574fd75521 100644
--- a/catalyst_voices/lib/app/view/app_page.dart
+++ b/catalyst_voices/lib/app/view/app_page.dart
@@ -1,7 +1,7 @@
+// ignore_for_file: discarded_futures
+
 import 'package:catalyst_voices/app/view/app_content.dart';
 import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
-import 'package:catalyst_voices_repositories/catalyst_voices_repositories.dart';
-import 'package:catalyst_voices_services/catalyst_voices_services.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
@@ -13,47 +13,39 @@ final class App extends StatefulWidget {
 }
 
 final class _AppState extends State<App> {
-  late final AuthenticationRepository _authenticationRepository;
-  late final CredentialsStorageRepository _credentialsStorageRepository;
+  late final Future<void> _initFuture;
 
   @override
   Widget build(BuildContext context) {
-    return MultiRepositoryProvider(
-      providers: [
-        RepositoryProvider.value(
-          value: _authenticationRepository,
-        ),
-      ],
-      child: BlocProvider(
-        create: (_) => AuthenticationBloc(
-          authenticationRepository: _authenticationRepository,
-        ),
-        child: const AppContent(),
-      ),
+    return FutureBuilder<void>(
+      future: _initFuture,
+      builder: (context, snapshot) {
+        return MultiBlocProvider(
+          providers: _multiBlocProviders(),
+          child: const AppContent(),
+        );
+      },
     );
   }
 
-  @override
-  Future<void> dispose() async {
-    await _authenticationRepository.dispose();
-
-    super.dispose();
-  }
-
   @override
   void initState() {
     super.initState();
-
-    _configureRepositories();
+    _initFuture = _init();
   }
 
-  void _configureRepositories() {
-    _credentialsStorageRepository = CredentialsStorageRepository(
-      secureStorageService: SecureStorageService(),
-    );
+  Future<void> _init() async {
+    await Dependency.instance.init();
+  }
 
-    _authenticationRepository = AuthenticationRepository(
-      credentialsStorageRepository: _credentialsStorageRepository,
-    );
+  List<BlocProvider> _multiBlocProviders() {
+    return [
+      BlocProvider<AuthenticationBloc>(
+        create: (_) => Dependency.instance.get<AuthenticationBloc>(),
+      ),
+      BlocProvider<LoginBloc>(
+        create: (_) => Dependency.instance.get<LoginBloc>(),
+      ),
+    ];
   }
 }
diff --git a/catalyst_voices/lib/pages/login/login_page.dart b/catalyst_voices/lib/pages/login/login_page.dart
index 19ed2e06b38..f86c97f9925 100644
--- a/catalyst_voices/lib/pages/login/login_page.dart
+++ b/catalyst_voices/lib/pages/login/login_page.dart
@@ -1,8 +1,5 @@
 import 'package:catalyst_voices/pages/login/login.dart';
-import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
-import 'package:catalyst_voices_repositories/catalyst_voices_repositories.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
 
 final class LoginPage extends StatelessWidget {
   static const loginPage = Key('LoginInPage');
@@ -11,17 +8,6 @@ final class LoginPage extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return BlocProvider(
-      key: loginPage,
-      create: (context) {
-        return LoginBloc(
-          authenticationRepository:
-              RepositoryProvider.of<AuthenticationRepository>(
-            context,
-          ),
-        );
-      },
-      child: const LoginForm(),
-    );
+    return const LoginForm();
   }
 }
diff --git a/catalyst_voices/packages/catalyst_voices_blocs/lib/src/catalyst_voices_blocs.dart b/catalyst_voices/packages/catalyst_voices_blocs/lib/src/catalyst_voices_blocs.dart
index d1042742844..2e94f47c7a1 100644
--- a/catalyst_voices/packages/catalyst_voices_blocs/lib/src/catalyst_voices_blocs.dart
+++ b/catalyst_voices/packages/catalyst_voices_blocs/lib/src/catalyst_voices_blocs.dart
@@ -1,2 +1,3 @@
 export 'authentication/authentication.dart';
+export 'dependency/dependency.dart';
 export 'login/login.dart';
diff --git a/catalyst_voices/packages/catalyst_voices_blocs/lib/src/dependency/dependency.dart b/catalyst_voices/packages/catalyst_voices_blocs/lib/src/dependency/dependency.dart
new file mode 100644
index 00000000000..0c817b706e5
--- /dev/null
+++ b/catalyst_voices/packages/catalyst_voices_blocs/lib/src/dependency/dependency.dart
@@ -0,0 +1,46 @@
+import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
+import 'package:catalyst_voices_blocs/src/dependency/dependency_provider.dart';
+import 'package:catalyst_voices_repositories/catalyst_voices_repositories.dart';
+import 'package:catalyst_voices_services/catalyst_voices_services.dart';
+
+final class Dependency extends DependencyProvider {
+  static final Dependency instance = Dependency._();
+
+  Dependency._();
+
+  Future<void> init() async {
+    _registerServices();
+    _registerRepositories();
+    _registerBlocsWithDependencies();
+  }
+
+  void _registerBlocsWithDependencies() {
+    this
+      ..registerSingleton<AuthenticationBloc>(
+        AuthenticationBloc(
+          authenticationRepository: get(),
+        ),
+      )
+      ..registerLazySingleton<LoginBloc>(
+        () => LoginBloc(
+          authenticationRepository: get(),
+        ),
+      );
+  }
+
+  void _registerRepositories() {
+    this
+      ..registerSingleton<CredentialsStorageRepository>(
+        CredentialsStorageRepository(secureStorageService: get()),
+      )
+      ..registerSingleton<AuthenticationRepository>(
+        AuthenticationRepository(credentialsStorageRepository: get()),
+      );
+  }
+
+  void _registerServices() {
+    registerSingleton<SecureStorageService>(
+      SecureStorageService(),
+    );
+  }
+}
diff --git a/catalyst_voices/packages/catalyst_voices_blocs/lib/src/dependency/dependency_provider.dart b/catalyst_voices/packages/catalyst_voices_blocs/lib/src/dependency/dependency_provider.dart
new file mode 100644
index 00000000000..ac1df9dac7f
--- /dev/null
+++ b/catalyst_voices/packages/catalyst_voices_blocs/lib/src/dependency/dependency_provider.dart
@@ -0,0 +1,64 @@
+import 'package:flutter/foundation.dart';
+import 'package:get_it/get_it.dart';
+
+abstract class DependencyProvider {
+  static final getIt = GetIt.instance;
+
+  static Future<void> get reset => getIt.reset();
+
+  @protected
+  Future<void> allReady() {
+    return getIt.allReady();
+  }
+
+  T get<T extends Object>() => getIt.get<T>();
+
+  Future<T> getAsync<T extends Object>() => getIt.getAsync<T>();
+
+  T getWithParam<T extends Object, P extends Object>({P? param}) {
+    return getIt.get<T>(param1: param);
+  }
+
+  @protected
+  void registerFactory<T extends Object>(ValueGetter<T> factoryFunc) {
+    getIt.registerFactory(factoryFunc);
+  }
+
+  @protected
+  void registerLazySingleton<T extends Object>(
+    ValueGetter<T> factoryFunc, {
+    DisposingFunc<T>? dispose,
+  }) {
+    getIt.registerLazySingleton(
+      factoryFunc,
+      dispose: dispose,
+    );
+  }
+
+  @protected
+  void registerSingleton<T extends Object>(T instance) {
+    getIt.registerSingleton(instance);
+  }
+
+  @protected
+  void registerSingletonAsync<T extends Object>(
+    ValueGetter<Future<T>> factoryFunc, {
+    Iterable<Type>? dependsOn,
+  }) {
+    getIt.registerSingletonAsync(
+      factoryFunc,
+      dependsOn: dependsOn,
+    );
+  }
+
+  @protected
+  void registerSingletonWithDependencies<T extends Object>(
+    FactoryFunc<T> factoryFunc, {
+    required List<Type> dependsOn,
+  }) {
+    getIt.registerSingletonWithDependencies(
+      factoryFunc,
+      dependsOn: dependsOn,
+    );
+  }
+}
diff --git a/catalyst_voices/packages/catalyst_voices_blocs/pubspec.yaml b/catalyst_voices/packages/catalyst_voices_blocs/pubspec.yaml
index 70de129a70f..b0026effdfd 100644
--- a/catalyst_voices/packages/catalyst_voices_blocs/pubspec.yaml
+++ b/catalyst_voices/packages/catalyst_voices_blocs/pubspec.yaml
@@ -14,6 +14,8 @@ dependencies:
       path: ../catalyst_voices_models
     catalyst_voices_repositories:
      path: ../catalyst_voices_repositories
+    catalyst_voices_services:
+     path: ../catalyst_voices_services
     catalyst_voices_view_models:
      path: ../catalyst_voices_view_models
     collection: ^1.17.1
@@ -21,6 +23,7 @@ dependencies:
     flutter:
       sdk: flutter
     formz: ^0.6.1
+    get_it: ^7.6.7
     meta: ^1.10.0
     result_type: ^0.2.0
 
diff --git a/catalyst_voices/packages/catalyst_voices_repositories/lib/src/authentication_repository.dart b/catalyst_voices/packages/catalyst_voices_repositories/lib/src/authentication_repository.dart
index 496f0fc6508..b3b5afda62e 100644
--- a/catalyst_voices/packages/catalyst_voices_repositories/lib/src/authentication_repository.dart
+++ b/catalyst_voices/packages/catalyst_voices_repositories/lib/src/authentication_repository.dart
@@ -5,7 +5,7 @@ import 'package:catalyst_voices_repositories/catalyst_voices_repositories.dart';
 
 final class AuthenticationRepository {
   final CredentialsStorageRepository credentialsStorageRepository;
-  final _controller = StreamController<AuthenticationStatus>();
+  final _streamController = StreamController<AuthenticationStatus>();
 
   AuthenticationRepository({required this.credentialsStorageRepository});
 
@@ -22,10 +22,10 @@ final class AuthenticationRepository {
       yield AuthenticationStatus.unknown;
     }
 
-    yield* _controller.stream;
+    yield* _streamController.stream;
   }
 
-  Future<void> dispose() async => _controller.close();
+  Future<void> dispose() async => _streamController.close();
 
   Future<SessionData?> getSessionData() async {
     try {
@@ -43,7 +43,7 @@ final class AuthenticationRepository {
 
   void logOut() {
     credentialsStorageRepository.clearSessionData;
-    _controller.add(AuthenticationStatus.unauthenticated);
+    _streamController.add(AuthenticationStatus.unauthenticated);
   }
 
   Future<void> signIn({
@@ -60,7 +60,7 @@ final class AuthenticationRepository {
     // TODO(minikin): remove this delay after implementing real auth flow.
     await Future.delayed(
       const Duration(milliseconds: 300),
-      () => _controller.add(AuthenticationStatus.authenticated),
+      () => _streamController.add(AuthenticationStatus.authenticated),
     );
   }
 }
diff --git a/melos.yaml b/melos.yaml
index f2c4f1a6bf7..1766ac03729 100644
--- a/melos.yaml
+++ b/melos.yaml
@@ -12,8 +12,8 @@ command:
     workspaceChangelog: true
   bootstrap:
     environment:
-      sdk: '>=3.2.1 <4.0.0'
-      flutter: 3.16.5
+      sdk: '>=3.2.5 <4.0.0'
+      flutter: 3.16.8
     dependencies:
       bloc_concurrency: ^0.2.2
       bloc: ^8.1.2

From ed887e32a715e8760316df53efd5a861d3b30704 Mon Sep 17 00:00:00 2001
From: cong-or <60357579+cong-or@users.noreply.github.com>
Date: Tue, 23 Jan 2024 11:58:34 +0000
Subject: [PATCH 4/4] feat(docs): initial gateway docs (#214)

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* docs(skeleton for gateway follower): initial napkin sketches

* ci lints

* ci lints

* ci lint

* ci lints

* ci lints

* ci lints

* ci lints

* ci lints
---
 docs/src/architecture/.pages                  |   1 +
 .../08_concepts/gateway/concrete.md           | 126 ++++++++++++++++++
 .../08_concepts/gateway/mechanics.md          |  71 ++++++++++
 3 files changed, 198 insertions(+)
 create mode 100644 docs/src/architecture/08_concepts/gateway/concrete.md
 create mode 100644 docs/src/architecture/08_concepts/gateway/mechanics.md

diff --git a/docs/src/architecture/.pages b/docs/src/architecture/.pages
index 7ceda85940e..4120ce54fd7 100644
--- a/docs/src/architecture/.pages
+++ b/docs/src/architecture/.pages
@@ -12,3 +12,4 @@ nav:
   - 10_quality_requirements.md
   - 11_technical_risks.md
   - 12_glossary.md
+
diff --git a/docs/src/architecture/08_concepts/gateway/concrete.md b/docs/src/architecture/08_concepts/gateway/concrete.md
new file mode 100644
index 00000000000..6508b915fbe
--- /dev/null
+++ b/docs/src/architecture/08_concepts/gateway/concrete.md
@@ -0,0 +1,126 @@
+---
+icon: material/hub
+---
+
+# Pseudo code
+
+Building blocks in the form of *pseudo code*;
+Intended to make the conceptual design more concrete; not setting rules.
+
+## Node
+
+Restart node with new config
+
+```rust
+fn restart_node(config: Config) -> Result<(), Err>{
+    // graceful restart
+}
+```
+
+## Config
+
+Check if config exists; all orchestration is coordinated via the DB, more specifically the config.
+
+```rust
+fn config_exists(db: DBHandler) -> Option<Config> {
+    // lock db
+    // if config exists { Some(config) }
+    // else { None }
+    // Resource acquisition is initialization: drop trait -> unlock db
+}
+```
+
+Node polls for config until it exists in database
+
+```rust
+fn poll_config(db: DBHandler) -> Option<Config> {
+    loop {
+        if let Some(r) = config_exists(db) {
+            return Some(r)
+        }
+    }
+}
+```
+
+Check if config has been updated
+
+```rust
+fn config_updated(db: DBHandler) -> Option<Config> {
+    // lock db
+    // if config updated { Some(config) }
+    // else { None }
+    // Resource acquisition is initialization: drop trait -> unlock db
+}
+```
+
+## Updates
+
+Continually race to update database
+
+```rust
+fn index_follower_data(db: DBHandler, stream: FollowerIo)-> Result<(), Err> {
+        loop {
+            if database_ready_to_update(db) {
+                update_database(db, stream)
+            }
+        }
+}
+```
+
+Check most recent update on cardano update table
+If it falls within the threshold boundary, node should update db with latest data
+
+```rust
+fn database_ready_to_update(db: DBHandler) -> bool {
+    // lock db
+    // let last_updated = CardanoUpdateTable()
+    // return update_threshold(last_updated) 
+    // Resource acquisition is initialization: drop trait -> unlock db
+}
+```
+
+Update database with follower data
+
+```rust
+fn update_database(db: DBHandler, stream: FollowerIo) -> Result<(), Err> {
+    // lock db
+    while let Some(block) = stream.next().await {
+        let metadata = parse(block);
+        db.insert(metadata);
+    }
+    // Resource acquisition is initialization: drop trait -> unlock db
+}
+```
+
+Parse block
+
+```rust
+fn parse(block: Block) -> Result<MetaBlock, Err> {
+    // extract era, unspent transaction output, spent Transactions and registration metadata
+}
+```
+
+Calculate if threshold conditional has been met
+
+```rust
+fn update_threshold(last_updated: ThresholdMetric) -> bool {
+    // threshold calculation
+    // define conditional
+}
+```
+
+## Follower
+
+* Start follower with specified networks
+
+* Stream blocks from given (slot,epoch)
+
+## Syncing
+
+Nodes race to update
+
+## Contention
+
+## Multiple nodes
+
+## Roll backs
diff --git a/docs/src/architecture/08_concepts/gateway/mechanics.md b/docs/src/architecture/08_concepts/gateway/mechanics.md
new file mode 100644
index 00000000000..5c6580c57a9
--- /dev/null
+++ b/docs/src/architecture/08_concepts/gateway/mechanics.md
@@ -0,0 +1,71 @@
+---
+icon: material/airplane-cog
+---
+
+# Initial blueprint
+
+```mermaid
+  stateDiagram-v2
+    state if_state <<choice>>
+    Node -->if_state
+    if_state --> node : config exists
+    if_state --> Node: config does not exist
+
+
+    note right of node
+            Indexing blockchain data provided by follower
+        end note
+
+    
+    note left of node
+            checkConfig = thread A
+        end note
+
+    
+    note right of node
+            checkDB = thread B
+        end note
+
+    
+    note right of Node
+            Orchestration is coordinated via the config
+        end note
+
+    state Node {
+        init --> init: try until config exists
+    }
+
+    state Follower {
+        [*]
+    }
+
+    state node {
+        checkConfig-->Database: release
+        Database-->checkConfig: wait
+
+        checkDB-->Database: release
+        Database-->checkDB: wait
+
+        State checkConfig{
+            Tick --> Updated
+            Tick --> NoChange: 
+            Updated --> Restart: stop all followers cleanly
+            Restart --> Tick: Restart with new config
+            NoChange--> Tick
+        }
+        State checkDB{
+            tick --> UpdateThreshold
+            UpdateThreshold --> tick: data is fresh
+            UpdateThreshold--> Follower: data is stale
+            updateDB --> tick
+            updateDB-->Follower
+            Follower -->updateDB
+        }
+        state Database{
+            Unlocked --> Locked
+            Locked--> Unlocked
+        }
+    }
+```
+
+:construction: Design is still active and not final :construction: