Module System Architecture
Core architecture of the GoGrab Space module system
🏗️ Module System Architecture
The Module System is the backbone of GoGrab Space applications, enabling a modular, decoupled, and scalable architecture.
This document details the design and architecture of the module system, consolidating the core module-base and the orchestrating module-integrator.
🎯 Design Goals
- Strict Contracts: Define clear boundaries with
BrowserModuleContractandModuleManifest. - Auto-Discovery: Self-registration via
@ModuleDecorator. - Multi-Tenancy: Built-in support for tenant contexts and configuration.
- Orchestration: Centralized lifecycle management via
IntegratorService. - Observability: Comprehensive event emission and structured logging.
🏛️ 8-Layer Architecture
The module system is organized into 8 distinct layers to separate concerns and ensure maintainability.
graph TD
App[Application] --> Core
Core[Core Layer] --> Management
Management[Management Layer] --> Navigation
Navigation[Navigation Layer] --> Communication
Communication[Communication Layer] --> Bootstrap
Bootstrap[Bootstrap Layer] --> Validation
Validation[Validation Layer] --> Orchestration
Orchestration[Orchestration Layer]
1. Core Layer
Orchestration and Lifecycle
- IntegratorService: Central orchestrator coordinating all other services.
- ModuleRegistryService: Manages the registry of loaded modules.
- ModuleDiscoveryService: Handles auto-discovery via decorators.
- LifecycleManagerService: Manages state transitions (init -> start -> stop).
2. Management Layer
Configuration and Activation
- ModuleConfigurationService: Resolves configuration per module and tenant.
- ConfigMergerService: Merges default, environment, and tenant configs.
- ModuleActivator: Handles activation logic and permissions.
3. Navigation Layer
UI and Routing
- NavigationManagerService: Manages inter-module navigation.
- EmbeddableComponentRegistry: Registry for cross-module UI components.
- BreadcrumbService: Dynamic breadcrumb generation.
4. Communication Layer
Inter-Module Exchange
- ActionRegistryService: Registry for executable actions.
- CrossModuleActionService: Facilitates calling actions across boundaries.
- ModuleProviderRegistry: Manages shared services/providers.
5. Bootstrap Layer
Startup Sequence
- BrowserBootstrapper: Handles browser-specific initialization.
- StartupSequencer: Manages the prioritized startup sequence.
6. Validation Layer
Security and Contracts
- ContractValidator: Ensures modules meet the
BrowserModuleContract. - DependencyValidator: Checks module dependency graphs.
- SecurityValidator: Enforces CSP and security policies.
7. Orchestration Layer
Events and Workflow
- EventCoordinator: Centralizes event distribution via
EventBusService. - WorkflowCoordinator: Manages complex, multi-step operations.
8. Infrastructure Layer (Base)
- Dependencies:
@libs-core/security,@libs-core/log-system,@gograb-space/utilities.
📜 Contracts and Models
BrowserModuleContract
The mandatory interface for all modules.
export interface BrowserModuleContract {
readonly manifest: ModuleManifest;
configure<T = Record<string, unknown>>(config: T): Observable<void>;
initialize(): Observable<void>;
start(): Observable<void>;
stop(): Observable<void>;
destroy(): Observable<void>;
}
ModuleManifest
Metadata definition for modules.
export interface ModuleManifest {
id: string;
version: string;
name: string;
description?: string;
permissions?: string[];
publicActions?: any[]; // Array of action classes
embeddableComponents?: ModuleEmbeddableComponent[];
routes?: Route[];
navigation?: NavigationConfig;
}
🔄 Lifecycle Management
Modules transition through specific states managed by the IntegratorService.
- Discovering: Scanning for
@ModuleDecorator. - Registered: Added to
ModuleRegistryService. - Configuring:
configure()called with merged config. - Initializing:
initialize()called for resource setup. - Starting:
start()called to activate functionality. - Running: Module is active and serving requests.
- Stopping:
stop()called (e.g., on user logout or navigation). - Destroyed:
destroy()called for cleanup.
📝 Architecture Decision Records (ADR)
ADR-001: Configuration via Method vs. DI
Decision: Use configure(config) method.
Rationale: Simplicity and better support for dynamic multi-tenant configurations without complex DI provider scopes.
ADR-002: Native Angular Lazy Loading
Decision: Use Angular's router for lazy loading instead of Module Federation. Rationale: Reduced build complexity, better type safety, and sufficient for the monorepo structure.
ADR-003: Centralized Orchestrator
Decision: Use IntegratorService as the single point of control.
Rationale: Provides a unified view of system state and simplifies lifecycle coordination.
ADR-004: Signal-Based State
Decision: Use Angular Signals for internal state management. Rationale: Performance, fine-grained reactivity, and alignment with modern Angular best practices.
🛡️ Risks and Mitigations
- Risk: Circular dependencies between modules.
- Mitigation: Strict
DependencyValidatorand layer enforcement.
- Mitigation: Strict
- Risk: Memory leaks from dynamic modules.
- Mitigation: Strict
destroy()protocols andDestroyRefusage.
- Mitigation: Strict
- Risk: Configuration conflicts.
- Mitigation:
ConfigMergerServicewith strict precedence rules.
- Mitigation:
Status: ✅ Production Architecture Last Updated: December 3, 2025