# KROW Architecture Principles This document is the **AUTHORITATIVE** source of truth for the KROW engineering architecture. All agents and engineers must adhere strictly to these principles. Deviations are interpreted as errors. ## 1. High-Level Architecture The KROW platform follows a strict **Clean Architecture** implementation within a **Melos Monorepo**. Dependencies flow **inwards** towards the Domain. ```mermaid graph TD subgraph "Apps (Entry Points)" ClientApp["apps/mobile/apps/client"] StaffApp["apps/mobile/apps/staff"] end subgraph "Features" ClientFeatures["apps/mobile/packages/features/client/*"] StaffFeatures["apps/mobile/packages/features/staff/*"] end subgraph "Services" DataConnect["apps/mobile/packages/data_connect"] DesignSystem["apps/mobile/packages/design_system"] CoreLocalization["apps/mobile/packages/core_localization"] end subgraph "Core Domain" Domain["apps/mobile/packages/domain"] Core["apps/mobile/packages/core"] end %% Dependency Flow ClientApp --> ClientFeatures & DataConnect & CoreLocalization StaffApp --> StaffFeatures & DataConnect & CoreLocalization ClientFeatures & StaffFeatures --> Domain ClientFeatures & StaffFeatures --> DesignSystem ClientFeatures & StaffFeatures --> CoreLocalization ClientFeatures & StaffFeatures --> Core DataConnect --> Domain DataConnect --> Core DesignSystem --> Core CoreLocalization --> Core Domain --> Core %% Strict Barriers linkStyle default stroke-width:2px,fill:none,stroke:gray ``` ## 2. Repository Structure & Package Roles ### 2.1 Apps (`apps/mobile/apps/`) - **Role**: Application entry points and Dependency Injection (DI) roots. - **Responsibilities**: - Initialize Flutter Modular. - Assemble features into a navigation tree. - Inject concrete implementations (from `data_connect`) into Feature packages. - Configure environment-specific settings. - **RESTRICTION**: NO business logic. NO UI widgets (except `App` and `Main`). ### 2.2 Features (`apps/mobile/packages/features//`) - **Role**: Vertical slices of user-facing functionality. - **Internal Structure**: - `domain/`: Feature-specific Use Cases and Repository Interfaces. - `data/`: Repository Implementations. - `presentation/`: - Pages, BLoCs, Widgets. - For performance make the pages as `StatelessWidget` and move the state management to the BLoC or `StatefulWidget` to an external separate widget file. - **Responsibilities**: - **Presentation**: UI Pages, Modular Routes. - **State Management**: BLoCs / Cubits. - **Application Logic**: Use Cases. - **RESTRICTION**: Features MUST NOT import other features. Communication happens via shared domain events. ### 2.3 Domain (`apps/mobile/packages/domain`) - **Role**: The stable heart of the system. Pure Dart. - **Responsibilities**: - **Entities**: Immutable data models (Data Classes). - **Failures**: Domain-specific error types. - **RESTRICTION**: NO Flutter dependencies. NO `json_annotation`. NO package dependencies (except `equatable`). ### 2.4 Data Connect (`apps/mobile/packages/data_connect`) - **Role**: Interface Adapter for Backend Access (Datasource Layer). - **Responsibilities**: - Implement Firebase Data Connect connector and service layer. - Map Domain Entities to/from Data Connect generated code. - Handle Firebase exceptions and map to domain failures. - Provide centralized `DataConnectService` with session management. ### 2.5 Design System (`apps/mobile/packages/design_system`) - **Role**: Visual language and component library. - **Responsibilities**: - UI components if needed. But mostly try to modify the theme file (apps/mobile/packages/design_system/lib/src/ui_theme.dart) so we can directly use the theme in the app, to use the default material widgets. - If not possible, and if that specific widget is used in multiple features, then try to create a shared widget in the `apps/mobile/packages/design_system/widgets`. - Theme definitions (Colors, Typography). - Assets (Icons, Images). - More details on how to use this package is available in the `apps/mobile/docs/03-design-system-usage.md`. - **RESTRICTION**: - CANNOT change colours or typography. - Dumb widgets only. NO business logic. NO state management (Bloc). - More details on how to use this package is available in the `apps/mobile/docs/03-design-system-usage.md`. ### 2.6 Core Localization (`apps/mobile/packages/core_localization`) - **Role**: Centralized language and localization management. - **Responsibilities**: - Define all user-facing strings in `l10n/` with i18n tooling support - Provide `LocaleBloc` for reactive locale state management - Export `TranslationProvider` for BuildContext-based string access - Map domain failures to user-friendly localized error messages via `ErrorTranslator` - **Feature Integration**: - Features access strings via `context.strings.` in presentation layer - BLoCs don't depend on localization; they emit domain failures - Error translation happens in UI layer (pages/widgets) - **App Integration**: - Apps import `LocalizationModule()` in their module imports - Apps wrap the material app with `BlocProvider()` and `TranslationProvider` - Apps initialize `MaterialApp` with locale from `LocaleState` ### 2.7 Core (`apps/mobile/packages/core`) - **Role**: Cross-cutting concerns. - **Responsibilities**: - Extension methods. - Logger configuration. - Base classes for Use Cases or Result types (functional error handling). ## 3. Dependency Direction & Boundaries 1. **Domain Independence**: `apps/mobile/packages/domain` knows NOTHING about the outer world. It defines *what* needs to be done, not *how*. 2. **UI Agnosticism**: `apps/mobile/packages/features` depends on `apps/mobile/packages/design_system` for looks and `apps/mobile/packages/domain` for logic. It does NOT know about Firebase. 3. **Data Isolation**: `apps/mobile/packages/data_connect` depends on `apps/mobile/packages/domain` to know what interfaces to implement. It does NOT know about the UI. ## 4. Data Connect Service & Session Management All backend access is unified through `DataConnectService` with integrated session management: ### 4.1 Session Handler Mixin - **Location**: `apps/mobile/packages/data_connect/lib/src/services/mixins/session_handler_mixin.dart` - **Responsibilities**: - Automatic token refresh (triggered when token <5 minutes to expiry) - Firebase auth state listening - Role-based access validation - Session state stream emissions - 3-attempt retry logic with exponential backoff on token validation failure - **Key Method**: `initializeAuthListener(allowedRoles: [...])` - call once on app startup ### 4.2 Session Listener Widget - **Location**: `apps/mobile/apps//lib/src/widgets/session_listener.dart` - **Responsibilities**: - Wraps entire app to listen to session state changes - Shows user-friendly dialogs for session expiration/errors - Handles navigation on auth state changes - **Pattern**: `SessionListener(child: AppWidget())` ### 4.3 Repository Pattern with Data Connect 1. **Interface First**: Define `abstract interface class RepositoryInterface` in feature domain layer. 2. **Implementation**: Use `_service.run()` wrapper that automatically: - Validates user is authenticated (if required) - Ensures token is valid and refreshes if needed - Executes the Data Connect query - Handles exceptions and maps to domain failures 3. **Session Store Population**: On successful auth, session stores are populated: - Staff: `StaffSessionStore.instance.setSession(StaffSession(...))` - Client: `ClientSessionStore.instance.setSession(ClientSession(...))` 4. **Lazy Loading**: If session is null, fetch data via `getStaffById()` or `getBusinessById()` and update store. ## 5. Feature Isolation & Cross-Feature Communication - **Zero Direct Imports**: `import 'package:feature_a/...'` is FORBIDDEN inside `package:feature_b`. - Exception: Shared packages like `domain`, `core`, and `design_system` are always accessible. - **Navigation**: Use named routes via Flutter Modular: - **Pattern**: `Modular.to.navigate('route_name')` - **Configuration**: Routes defined in `module.dart` files; constants in `paths.dart` - **Data Sharing**: Features do not share state directly. Shared data accessed through: - **Domain Repositories**: Centralized data sources (e.g., `AuthRepository`) - **Session Stores**: `StaffSessionStore` and `ClientSessionStore` for app-wide user context - **Event Streams**: If needed, via `DataConnectService` streams for reactive updates ## 6. App-Specific Session Management Each app (`staff` and `client`) has different role requirements and session patterns: ### 6.1 Staff App Session - **Location**: `apps/mobile/apps/staff/lib/main.dart` - **Initialization**: `DataConnectService.instance.initializeAuthListener(allowedRoles: ['STAFF', 'BOTH'])` - **Session Store**: `StaffSessionStore` with `StaffSession(user: User, staff: Staff?, ownerId: String?)` - **Lazy Loading**: `getStaffName()` fetches via `getStaffById()` if session null - **Navigation**: On auth → `Modular.to.toStaffHome()`, on unauth → `Modular.to.toInitialPage()` ### 6.2 Client App Session - **Location**: `apps/mobile/apps/client/lib/main.dart` - **Initialization**: `DataConnectService.instance.initializeAuthListener(allowedRoles: ['CLIENT', 'BUSINESS', 'BOTH'])` - **Session Store**: `ClientSessionStore` with `ClientSession(user: User, business: ClientBusinessSession?)` - **Lazy Loading**: `getUserSessionData()` fetches via `getBusinessById()` if session null - **Navigation**: On auth → `Modular.to.toClientHome()`, on unauth → `Modular.to.toInitialPage()`