Manifest Update Plan
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
ModuleManifest Interface Update Plan
Executive Summary
Objective: Expand the minimal ModuleManifest interface to a comprehensive module introspection and communication system that supports navigation, embeddable components, public actions, and inter-module dependencies.
Current State: Minimal interface with 4 properties (id, version, displayName, permissions)
Target State: Comprehensive manifest with navigation config, routes, embeddable components, public actions, provider/consumer contracts, and rich metadata
Strategy: Phased implementation with backward compatibility, progressive enhancement, and full Angular 20 compliance
1. Gap Analysis
Current Interface (module-manifest.interface.ts)
export interface ModuleManifest {
readonly id: string;
readonly version: string;
readonly displayName?: string;
readonly permissions?: readonly string[];
}
Properties: 4 basic metadata fields Complexity: Low Capabilities: Module identification only
Target Interface (from module-base.md)
export interface ModuleManifest {
// Core metadata (EXISTING)
id: string;
version: string;
displayName?: string; // Enhanced to required 'name'
description: string; // NEW
// Module relationships (NEW)
dependencies: ModuleDependency[];
permissions: ModulePermission[]; // Enhanced from string[]
routes: ModuleRoute[];
// Navigation and UI (NEW)
navigation: ModuleNavigationConfig;
embeddableComponents: ModuleEmbeddableComponent[];
publicActions: ModulePublicAction[];
// Configuration (NEW)
config: ModuleConfigSchema;
assets: ModuleAssets;
// Inter-module communication (NEW)
exports: ModuleExports;
imports: ModuleImports;
provides: ModuleProvider[];
consumes: ModuleConsumer[];
// Metadata (NEW)
author: string;
license: string;
tags: string[];
}
Properties: 17 comprehensive fields Complexity: High Capabilities: Full module introspection, navigation, embedding, inter-module communication
Gap Summary
| Category | Current | Target | Gap |
|---|---|---|---|
| Basic Metadata | 4 properties | 6 properties | +2 (description, name vs displayName) |
| Navigation | 0 | 3 structures | +3 (navigation config, routes, embeddable) |
| Inter-module | 0 | 6 structures | +6 (dependencies, provides, consumes, etc.) |
| Configuration | 0 | 2 structures | +2 (config schema, assets) |
| Actions | 0 | 1 structure | +1 (public actions) |
| Total | 4 | 17 | +13 new properties |
2. Architecture Impact Assessment
Affected Systems
2.1 Direct Impact (High)
ModuleRegistryService (
module-base/services/module-registry.service.ts)- Must process expanded manifest structures
- Register navigation items, routes, embeddable components
- Validate provider/consumer contracts
ModuleDiscoveryService (
module-base/services/module-discovery.service.ts)- Enhanced discovery metadata
- Component and action registration
ModuleStateService (
module-base/services/module-state.service.ts)- Track navigation state, embedded components
- Monitor provider/consumer status
2.2 Integration Impact (Medium)
@libs-core/module-integrator
- Dependency resolution with new ModuleDependency structure
- Configuration management with ModuleConfigSchema
- Provider/Consumer dependency injection
@libs-core/action-registry
- Integration with ModulePublicAction
- Action category handling (navigation, CRUD, workflow, integration)
@libs-core/security
- Enhanced permission handling (ModulePermission vs string[])
- Permission validation for navigation, components, actions
2.3 Ecosystem Impact (Low-Medium)
Navigation System (to be created)
- Process ModuleNavigationConfig
- Merge navigation from multiple modules
- Handle breadcrumbs, toolbar items
Component Embedding System (to be created)
- Dynamic component loading from ModuleEmbeddableComponent
- Component lifecycle management
- Input/output binding
3. Design Decisions
3.1 Angular 20 Compliance
Signal vs Observable
Decision: Use Signal<number> instead of Observable<number> for navigation badges
Rationale:
- Angular 20 prioritizes Signals over Observables
- Better performance with OnPush change detection
- Cleaner template syntax with automatic unwrapping
Implementation:
export interface NavigationMenuItem {
// Documentation shows: badge?: () => Observable<number>
// Angular 20 version:
badge?: Signal<number>; // Direct signal, not function returning Observable
}
Standalone Components
Decision: All Type<any> references must be standalone components
Validation:
export interface ModuleEmbeddableComponent {
componentType: Type<any>; // Must be standalone component
// Validation in ModuleRegistryService:
// - Check metadata.standalone === true
// - Throw error if NgModule-based component
}
3.2 Type Safety Enhancements
Generic Type Parameters
Problem: Documentation uses Type<any> reducing type safety
Solution: Introduce generic type parameters where possible
Before (docs):
export interface ModuleEmbeddableComponent {
componentType: Type<any>;
}
After (improved):
export interface ModuleEmbeddableComponent<T = any> {
componentType: Type<T>;
// Optional: type constraints for specific component categories
}
Strict Permission Types
Problem: Documentation shows string[] for permissions in some places, ModulePermission[] in others
Solution: Always use typed structures, never primitive arrays
Before (docs inconsistency):
permissions?: string[] // In some interfaces
permissions: ModulePermission[] // In others
After (consistent):
export interface ModuleManifest {
permissions: readonly ModulePermission[]; // Always structured, readonly
}
export interface NavigationMenuItem {
permissions?: readonly string[]; // Specific permission IDs, optional
}
3.3 Multi-Tenant Considerations
All new structures must support tenant context:
export interface ModuleNavigationConfig {
menuItems: NavigationMenuItem[];
// Each menu item can have tenant-specific permissions
}
export interface ModuleProvider {
id: string;
tenantIsolation?: 'shared' | 'isolated'; // NEW: tenant isolation strategy
// 'shared': single instance across tenants
// 'isolated': separate instance per tenant
}
3.4 Backward Compatibility Strategy
Approach: All new properties are optional with sensible defaults
export interface ModuleManifest {
// EXISTING (mandatory)
readonly id: string;
readonly version: string;
// EXISTING → ENHANCED (optional for backward compatibility)
readonly displayName?: string; // Keep optional, rename to 'name' in v2
readonly permissions?: readonly string[]; // Keep simple form, enhance to ModulePermission[] in v2
// NEW (all optional)
readonly description?: string;
readonly navigation?: ModuleNavigationConfig;
readonly routes?: ModuleRoute[];
readonly embeddableComponents?: ModuleEmbeddableComponent[];
readonly publicActions?: ModulePublicAction[];
readonly provides?: ModuleProvider[];
readonly consumes?: ModuleConsumer[];
readonly dependencies?: ModuleDependency[];
readonly config?: ModuleConfigSchema;
readonly assets?: ModuleAssets;
readonly exports?: ModuleExports;
readonly imports?: ModuleImports;
readonly author?: string;
readonly license?: string;
readonly tags?: readonly string[];
}
Migration Path:
- Phase 1: Modules with minimal manifests continue working
- Phase 2: Modules progressively adopt new properties
- Phase 3: Eventually deprecate simple forms (permissions: string[]) in favor of structured forms
4. Implementation Phases
Phase 1: Interface Foundation ✅ (Low Risk)
Goal: Define all supporting interfaces and types
Tasks:
Create supporting interfaces:
ModuleNavigationConfig+NavigationMenuItem+BreadcrumbConfig+ToolbarConfigModuleRoute(Angular Router integration)ModuleEmbeddableComponent+ComponentInputModulePublicActionModuleProvider+ModuleConsumerModuleDependencyModuleConfigSchema+ModuleAssetsModuleExports+ModuleImportsModulePermission(if not already in @libs-core/shared-models)
Expand
ModuleManifestinterface with all new optional propertiesAdd comprehensive JSDoc documentation with examples
Deliverables:
/libs/core/module-base/src/lib/contracts/module-manifest.interface.ts(updated)/libs/core/module-base/src/lib/contracts/navigation.interface.ts(new)/libs/core/module-base/src/lib/contracts/embeddable-component.interface.ts(new)/libs/core/module-base/src/lib/contracts/public-action.interface.ts(new)/libs/core/module-base/src/lib/contracts/provider-consumer.interface.ts(new)- Update barrel export
src/index.ts
Acceptance Criteria:
- All interfaces compile with strict TypeScript
- No breaking changes to existing code
- Comprehensive JSDoc with examples
- Exports updated in barrel
Estimated Effort: 4-6 hours
Phase 2: Service Integration ⚙️ (Medium Risk)
Goal: Update core services to process expanded manifest properties
Tasks:
ModuleRegistryService enhancements:
- Process navigation config → register with NavigationService
- Process routes → register with Angular Router
- Process embeddable components → register with ComponentRegistry
- Process public actions → register with ActionRegistryService
- Process providers → register with DI system
- Validate consumer requirements against available providers
ModuleDiscoveryService enhancements:
- Include navigation metadata in discovery results
- Component and action inventory
Create NavigationService (new service):
- Aggregate navigation items from all modules
- Merge menu structures
- Handle breadcrumb and toolbar items
- Permission-based filtering
- Tenant-aware navigation
Create ComponentRegistryService (new service):
- Track embeddable components from all modules
- Dynamic component loading
- Component lifecycle management
- Category-based filtering (widget, list, form, dashboard)
Deliverables:
module-registry.service.ts(updated)module-discovery.service.ts(updated)navigation.service.ts(new)component-registry.service.ts(new)- Integration tests for all services
Acceptance Criteria:
- Services handle both minimal and comprehensive manifests
- Navigation items correctly aggregated across modules
- Components dynamically loadable
- Public actions registered with ActionRegistry
- Provider/Consumer validation working
- All integration tests passing
Estimated Effort: 12-16 hours
Phase 3: Runtime Features 🚀 (High Complexity)
Goal: Implement dynamic loading and runtime capabilities
Tasks:
Dynamic Component Loading System:
- Create
DynamicComponentLoaderService - Support for lazy-loaded components
- Component instance caching
- Input/Output binding
- Lifecycle hooks (onInit, onDestroy)
- Memory management
- Create
Provider/Consumer DI System:
- Create
ModuleProviderService - Dependency injection integration with Angular's
inject() - Circular dependency detection
- Fallback handling for optional consumers
- Tenant-aware provider instances
- Create
Route Registration System:
- Create
ModuleRouterService - Dynamic route registration
- Permission-based route guards
- Lazy route loading
- Route conflict resolution (same path from multiple modules)
- Create
Navigation System:
- Menu hierarchy builder
- Breadcrumb trail generation
- Toolbar item aggregation
- Badge update mechanism (Signals)
- Active route highlighting
Deliverables:
dynamic-component-loader.service.ts(new)module-provider.service.ts(new)module-router.service.ts(new)navigation-builder.service.ts(new)- E2E tests for dynamic features
Acceptance Criteria:
- Components load dynamically from manifests
- Provider/Consumer contracts work correctly
- Routes register and navigate properly
- Navigation UI updates reactively
- Memory leaks prevented
- E2E tests passing
Estimated Effort: 20-24 hours
Phase 4: Testing & Validation ✅ (Critical)
Goal: Comprehensive test coverage for all new functionality
Tasks:
Unit Tests:
- Interface validation (all supporting interfaces)
- Service unit tests (Registry, Discovery, Navigation, ComponentRegistry)
- Type safety verification
Integration Tests:
- Multi-module manifest processing
- Navigation aggregation from multiple modules
- Provider/Consumer dependency resolution
- Action registration integration
Migration Tests:
- Backward compatibility - minimal manifests work
- Progressive enhancement - modules adopt new features incrementally
- Mixed scenarios - some modules minimal, others comprehensive
E2E Tests:
- Dynamic component embedding workflow
- Navigation interaction (menu, breadcrumbs, toolbar)
- Route navigation with permissions
- Provider/Consumer runtime behavior
Deliverables:
/libs/core/module-base/tests/manifest-interfaces.test.ts(new)/libs/core/module-base/tests/manifest-services.test.ts(updated)/libs/core/module-base/tests/manifest-integration.test.ts(new)/libs/core/module-base/tests/manifest-migration.test.ts(new)- E2E test suite
Acceptance Criteria:
- Unit test coverage ≥ 90%
- Integration tests cover all service interactions
- Migration tests verify backward compatibility
- E2E tests validate user workflows
- All tests passing
Estimated Effort: 12-16 hours
Phase 5: Documentation & Examples 📚 (Essential)
Goal: Complete documentation for developers implementing modules
Tasks:
Interface Documentation:
- JSDoc for all interfaces with detailed examples
- Type parameter explanations
- Usage guidelines
Pattern Documentation:
- Navigation patterns (menu structures, toolbar items)
- Embeddable component patterns (widgets, dashboards)
- Public action patterns (CRUD, workflow, integration)
- Provider/Consumer patterns (service interop)
Migration Guide:
- Step-by-step migration from minimal to comprehensive manifests
- Before/after code examples
- Common pitfalls and solutions
Example Modules:
- Update example modules from docs (Products, CMS)
- Real-world manifest examples
- Integration examples
Architecture Decision Records (ADRs):
- Observable → Signal decision
- Type
usage justification - Provider/Consumer pattern rationale
- Multi-tenant isolation strategies
Deliverables:
/docs/libs/module-base/manifest-guide.md(new)/docs/libs/module-base/migration-guide.md(new)/docs/libs/module-base/examples/(new directory)products-module-manifest.example.tscms-module-manifest.example.tsminimal-module-manifest.example.ts
/docs/libs/module-base/adrs/(new directory)001-signals-for-navigation.md002-provider-consumer-pattern.md003-multi-tenant-isolation.md
- Updated
module-base.mdwith accurate current state
Acceptance Criteria:
- All interfaces fully documented
- Migration guide tested by team member
- Example modules compile and demonstrate features
- ADRs explain all major decisions
- Documentation reviewed and approved
Estimated Effort: 8-12 hours
5. Risk Assessment & Mitigation
5.1 Type Safety Risks 🔴 HIGH
Risk: Extensive use of Type<any> reduces compile-time type safety
Impact: Runtime errors from incorrect component/action types
Mitigation:
- Introduce generic type parameters where possible
- Runtime validation in
ModuleRegistryServicebefore registration - Create
ModuleValidatorservice for manifest validation - Comprehensive integration tests for type mismatches
Implementation:
// Generic type parameters
export interface ModuleEmbeddableComponent<T = any> {
componentType: Type<T>;
}
// Runtime validation
class ModuleRegistryService {
registerModule(manifest: ModuleManifest): void {
this.validateManifest(manifest); // Throws if invalid
// ... registration logic
}
private validateManifest(manifest: ModuleManifest): void {
// Check component metadata, action contracts, etc.
}
}
5.2 Runtime Complexity 🟡 MEDIUM
Risk: Dynamic component loading, provider/consumer DI increase runtime complexity
Impact: Memory leaks, performance degradation, harder debugging
Mitigation:
Memory Management:
- Implement proper cleanup in
DynamicComponentLoaderService - Track component instances with WeakMap
- Unsubscribe from all subscriptions on module stop
- Implement proper cleanup in
Performance Monitoring:
- Log component load times
- Monitor memory usage
- Performance budgets in tests
Error Handling:
- Graceful degradation for missing providers
- Fallback components for failed loads
- Detailed error messages with context
Implementation:
export class DynamicComponentLoaderService {
private componentCache = new WeakMap<Type<any>, ComponentRef<any>>();
loadComponent<T>(componentType: Type<T>): ComponentRef<T> {
const cached = this.componentCache.get(componentType);
if (cached) return cached;
const componentRef = this.createComponent(componentType);
this.componentCache.set(componentType, componentRef);
// Track for cleanup
this.trackForCleanup(componentRef);
return componentRef;
}
private trackForCleanup(componentRef: ComponentRef<any>): void {
// Subscribe to module lifecycle events
// Clean up on module stop/destroy
}
}
5.3 Angular Integration Challenges 🟡 MEDIUM
Risk: Integration with Angular Router, DI system may have edge cases
Impact: Routes not working, DI conflicts, navigation issues
Mitigation:
Router Integration:
- Use Angular's
provideRouterand dynamic route configuration - Test route conflict scenarios (same path from multiple modules)
- Document route registration order guarantees
- Use Angular's
DI Integration:
- Leverage Angular's
EnvironmentInjectorfor module-specific DI - Test provider/consumer with different DI scopes
- Document DI lifetime expectations
- Leverage Angular's
Testing:
- Comprehensive E2E tests for router scenarios
- Integration tests for DI edge cases
- Test with real Angular application (not just isolated library)
5.4 Backward Compatibility Breaks 🟢 LOW (with mitigation)
Risk: Existing modules break with new manifest structure
Impact: Migration effort required for all existing modules
Mitigation:
- All new properties optional: Existing minimal manifests work unchanged
- Progressive enhancement: Services handle both minimal and comprehensive manifests
- Migration tests: Verify mixed scenarios (some modules updated, others not)
- Clear migration guide: Step-by-step with examples
Validation:
// This should continue working after update
const minimalManifest: ModuleManifest = {
id: 'legacy-module',
version: '1.0.0',
displayName: 'Legacy Module'
// All new properties omitted
};
// Services handle both:
moduleRegistryService.registerModule(minimalManifest); // Works
moduleRegistryService.registerModule(comprehensiveManifest); // Also works
5.5 Multi-Tenant Isolation 🟡 MEDIUM
Risk: Navigation, components, actions leak across tenants
Impact: Security vulnerability, data isolation breach
Mitigation:
Tenant-Aware Services:
- NavigationService filters by tenant context
- ComponentRegistry isolates components per tenant
- ActionRegistry validates permissions per tenant
Permission Validation:
- All navigation items checked against tenant permissions
- Embeddable components validated before load
- Public actions require tenant-specific authorization
Testing:
- Multi-tenant integration tests
- Permission boundary tests
- Cross-tenant isolation verification
Implementation:
export class NavigationService {
getMenuItems(tenantContext: TenantContext): NavigationMenuItem[] {
const allItems = this.aggregateMenuItems();
// Filter by tenant and permissions
return allItems.filter(item =>
this.hasAccess(item, tenantContext)
);
}
private hasAccess(item: NavigationMenuItem, context: TenantContext): boolean {
if (!item.permissions) return true;
return item.permissions.every(perm =>
this.securityService.hasPermission(perm, context)
);
}
}
6. Testing Strategy
6.1 Unit Testing
Scope: Individual interfaces, services, utilities
Framework: Vitest with Angular integration
Test Files:
/libs/core/module-base/tests/
├── interfaces/
│ ├── module-manifest.test.ts
│ ├── navigation-config.test.ts
│ ├── embeddable-component.test.ts
│ ├── public-action.test.ts
│ └── provider-consumer.test.ts
├── services/
│ ├── module-registry.test.ts
│ ├── navigation.test.ts
│ ├── component-registry.test.ts
│ ├── dynamic-component-loader.test.ts
│ └── module-provider.test.ts
└── validators/
└── module-validator.test.ts
Coverage Target: ≥ 90%
Key Test Scenarios:
- Interface validation (TypeScript compilation)
- Service unit tests with mocked dependencies
- Edge cases (empty arrays, null/undefined values)
- Error handling (invalid manifests, missing dependencies)
Example Test:
describe('ModuleManifest Interface', () => {
it('should accept minimal manifest', () => {
const manifest: ModuleManifest = {
id: 'test-module',
version: '1.0.0'
};
expect(manifest.id).toBe('test-module');
});
it('should accept comprehensive manifest', () => {
const manifest: ModuleManifest = {
id: 'test-module',
version: '1.0.0',
displayName: 'Test Module',
description: 'A test module',
navigation: {
menuItems: [{
id: 'item1',
label: 'Item 1',
route: '/item1',
order: 1
}]
},
// ... all other properties
};
expect(manifest.navigation?.menuItems).toHaveLength(1);
});
});
6.2 Integration Testing
Scope: Service interactions, cross-module scenarios
Framework: Vitest with Angular TestBed
Test Files:
/libs/core/module-base/tests/integration/
├── manifest-processing.integration.test.ts
├── navigation-aggregation.integration.test.ts
├── component-loading.integration.test.ts
├── provider-consumer.integration.test.ts
└── action-registration.integration.test.ts
Key Test Scenarios:
- Multiple modules with different manifest complexities
- Navigation aggregation from 3+ modules
- Provider/Consumer dependency resolution
- Component loading with input binding
- Action registration and execution through ActionRegistry
Example Test:
describe('Navigation Aggregation Integration', () => {
let navigationService: NavigationService;
let moduleRegistry: ModuleRegistryService;
beforeEach(() => {
// TestBed setup
});
it('should aggregate menu items from multiple modules', () => {
// Register module 1 with navigation
moduleRegistry.registerModule(productsManifest);
// Register module 2 with navigation
moduleRegistry.registerModule(cmsManifest);
// Get aggregated navigation
const menuItems = navigationService.getMenuItems(testTenantContext);
// Should contain items from both modules
expect(menuItems.length).toBeGreaterThan(0);
expect(menuItems.some(item => item.id === 'products-main')).toBe(true);
expect(menuItems.some(item => item.id === 'cms-main')).toBe(true);
});
it('should filter navigation by permissions', () => {
moduleRegistry.registerModule(productsManifest);
const contextWithoutPermission = {
...testTenantContext,
userPermissions: [] // No permissions
};
const menuItems = navigationService.getMenuItems(contextWithoutPermission);
// Should not see items requiring permissions
expect(menuItems.length).toBe(0);
});
});
6.3 Migration Testing
Scope: Backward compatibility, progressive enhancement
Framework: Vitest
Test Files:
/libs/core/module-base/tests/migration/
├── backward-compatibility.test.ts
├── progressive-enhancement.test.ts
└── mixed-scenarios.test.ts
Key Test Scenarios:
- Minimal manifest (pre-update) still works
- Services handle both minimal and comprehensive manifests
- Mixed scenario: 2 minimal modules + 2 comprehensive modules
- Gradual migration: module starts minimal, adds properties incrementally
Example Test:
describe('Backward Compatibility', () => {
it('should process minimal legacy manifest', () => {
const legacyManifest: ModuleManifest = {
id: 'legacy-module',
version: '1.0.0',
displayName: 'Legacy Module',
permissions: ['read', 'write']
};
// Should not throw
expect(() => {
moduleRegistry.registerModule(legacyManifest);
}).not.toThrow();
// Should be registered
const registered = moduleRegistry.getModule('legacy-module');
expect(registered).toBeDefined();
});
it('should handle mixed minimal and comprehensive manifests', () => {
// Register minimal module
moduleRegistry.registerModule(minimalManifest);
// Register comprehensive module
moduleRegistry.registerModule(comprehensiveManifest);
// Both should be available
expect(moduleRegistry.getModules()).toHaveLength(2);
// Navigation should work for comprehensive module
const menuItems = navigationService.getMenuItems(testTenantContext);
expect(menuItems.length).toBeGreaterThan(0);
});
});
6.4 E2E Testing
Scope: Full user workflows in real application
Framework: Playwright
Test Files:
/libs/core/module-base/e2e/
├── dynamic-component-embedding.e2e.ts
├── navigation-interaction.e2e.ts
├── route-navigation.e2e.ts
└── provider-consumer-runtime.e2e.ts
Key Test Scenarios:
- User clicks navigation menu → navigates to module route
- Module embeds component dynamically → component renders with inputs
- Module action executes → ActionRegistry invokes correct handler
- Provider/Consumer runtime behavior → consumer gets provider service
Example Test:
describe('Navigation E2E', () => {
test('should navigate through module menu items', async ({ page }) => {
// Load application with modules
await page.goto('/');
// Wait for modules to load
await page.waitForSelector('[data-testid="module-menu"]');
// Click on Products menu item
await page.click('[data-testid="menu-item-products-main"]');
// Should navigate to products route
await expect(page).toHaveURL('/products');
// Should display products component
await expect(page.locator('[data-testid="products-list"]')).toBeVisible();
});
test('should hide menu items without permission', async ({ page }) => {
// Login as user without products:read permission
await login(page, userWithoutProductsPermission);
await page.goto('/');
await page.waitForSelector('[data-testid="module-menu"]');
// Products menu item should not be visible
const productsItem = page.locator('[data-testid="menu-item-products-main"]');
await expect(productsItem).not.toBeVisible();
});
});
7. Documentation Requirements
7.1 Interface Documentation (JSDoc)
Example: ModuleManifest
/**
* Module manifest interface defining comprehensive metadata for a browser module.
*
* This interface describes all aspects of a module including:
* - Basic identification and metadata
* - Navigation structure (menus, breadcrumbs, toolbar)
* - Embeddable components that can be used by other modules
* - Public actions that other modules can invoke
* - Provider/Consumer contracts for inter-module services
* - Configuration schema and assets
*
* @example Minimal manifest (backward compatible)
* ```typescript
* const manifest: ModuleManifest = {
* id: 'simple-module',
* version: '1.0.0'
* };
* ```
*
* @example Comprehensive manifest with navigation
* ```typescript
* const manifest: ModuleManifest = {
* id: 'products',
* version: '1.0.0',
* displayName: 'Product Management',
* description: 'Comprehensive product catalog management',
*
* navigation: {
* menuItems: [
* {
* id: 'products-main',
* label: 'Products',
* icon: 'inventory',
* route: '/products',
* order: 10,
* permissions: ['products:read']
* }
* ]
* },
*
* routes: [
* { path: 'products', component: ProductListComponent, permissions: ['products:read'] }
* ],
*
* embeddableComponents: [
* {
* id: 'product-list-widget',
* componentType: ProductListWidgetComponent,
* displayName: 'Product List',
* description: 'Embeddable product list widget',
* category: 'widget',
* permissions: ['products:read']
* }
* ]
* };
* ```
*
* @see {@link NavigationConfig} for navigation structure
* @see {@link ModuleEmbeddableComponent} for embeddable components
* @see {@link ModulePublicAction} for public actions
* @see {@link ModuleProvider} for provider contracts
*/
export interface ModuleManifest {
// ... properties with detailed JSDoc
}
7.2 Migration Guide Structure
File: /docs/libs/module-base/migration-guide.md
Outline:
# ModuleManifest Migration Guide
## Overview
- What changed in the ModuleManifest interface
- Why these changes were made
- Backward compatibility guarantees
## Migration Paths
### Path 1: Continue with Minimal Manifest (No Changes Required)
- Existing minimal manifests work unchanged
- Example: keeping legacy modules as-is
### Path 2: Progressive Enhancement (Recommended)
- Add properties incrementally
- Step-by-step guide for each property category
- Examples for each step
### Path 3: Full Migration (Advanced Features)
- Complete migration to comprehensive manifest
- Full example modules (Products, CMS)
- Integration with Navigation, ComponentRegistry, ActionRegistry
## Step-by-Step: Adding Navigation
1. Define navigation structure
2. Add navigation property to manifest
3. Test navigation rendering
4. Add permission-based filtering
## Step-by-Step: Adding Embeddable Components
1. Create standalone component
2. Define component metadata
3. Add to manifest
4. Test dynamic loading
## Common Pitfalls
- Forgetting standalone: true on components
- Using Observable instead of Signal for badges
- Permission mismatches
- Provider/Consumer circular dependencies
## Before/After Examples
- Minimal → Navigation
- Minimal → Embeddable Components
- Minimal → Full Comprehensive
## Testing Your Migration
- Unit test checklist
- Integration test checklist
- E2E verification steps
7.3 Architecture Decision Records (ADRs)
ADR 001: Signals for Navigation Badges
File: /docs/libs/module-base/adrs/001-signals-for-navigation.md
# ADR 001: Use Signals Instead of Observables for Navigation Badges
## Status
Accepted
## Context
The documentation shows navigation menu items with badges using `Observable<number>`:
```typescript
badge?: () => Observable<number>
Angular 20 prioritizes Signals over Observables for reactive state management.
Decision
Use Signal<number> instead of Observable<number> for navigation badges.
New Interface:
export interface NavigationMenuItem {
badge?: Signal<number>; // Direct signal, not function returning Observable
}
Consequences
Positive
- Better performance with OnPush change detection
- Cleaner template syntax (automatic unwrapping)
- Aligns with Angular 20 best practices
- Simpler API (direct Signal, not factory function)
Negative
- Requires migration for modules using Observables
- Need conversion utilities for existing Observable-based badge logic
Migration Path
For modules with Observable-based badges:
// Before (Observable)
const badgeCount$ = this.productService.getUnreadCount();
// After (Signal)
const badgeCount = toSignal(this.productService.getUnreadCount(), { initialValue: 0 });
References
- Angular Signals Documentation
- Angular 20 Migration Guide
---
#### ADR 002: Provider/Consumer Pattern for Inter-Module Services
**File**: `/docs/libs/module-base/adrs/002-provider-consumer-pattern.md`
```markdown
# ADR 002: Provider/Consumer Pattern for Inter-Module Services
## Status
Accepted
## Context
Modules need to share services and data with each other. Options:
1. **Global DI**: All modules inject from root injector
2. **Event System**: Communication via events only
3. **Provider/Consumer Pattern**: Explicit contracts in manifest
## Decision
Implement Provider/Consumer pattern with explicit manifest declarations.
**Structure**:
```typescript
export interface ModuleProvider {
id: string;
type: 'service' | 'data' | 'component' | 'asset';
interface: string;
implementation: Type<any> | string;
permissions?: readonly string[];
}
export interface ModuleConsumer {
moduleId: string;
providerId: string;
required: boolean;
fallback?: any;
}
Consequences
Positive
- Explicit Dependencies: Manifest clearly shows module dependencies
- Validation: Registry can validate all consumers have matching providers
- Documentation: Self-documenting inter-module contracts
- Type Safety: Interface names enable type checking
Negative
- Complexity: More manifest boilerplate
- Indirection: Extra layer vs direct DI
- Runtime Resolution: Providers resolved at runtime, not compile-time
Implementation
ModuleProviderService will:
- Collect all providers from module manifests
- Validate all consumers have matching providers
- Create DI tokens for each provider interface
- Inject correct provider implementation into consumer modules
Alternatives Considered
Global DI (Rejected)
- Pros: Simple, native Angular
- Cons: No visibility into dependencies, no validation, tight coupling
Event System Only (Rejected)
- Pros: Loose coupling
- Cons: No type safety, harder to trace data flow, performance overhead
References
- Module Federation Documentation
- Micro Frontend Architecture Patterns
---
## 8. Success Criteria
### 8.1 Functional Success Criteria
✅ **Interface Completeness**
- [ ] All 17 properties from documentation implemented
- [ ] All supporting interfaces created (NavigationConfig, ModuleRoute, etc.)
- [ ] All interfaces compile with strict TypeScript
- [ ] Comprehensive JSDoc documentation with examples
✅ **Backward Compatibility**
- [ ] Existing minimal manifests work without changes
- [ ] Services handle both minimal and comprehensive manifests
- [ ] Migration tests verify mixed scenarios
✅ **Service Integration**
- [ ] ModuleRegistryService processes all manifest properties
- [ ] NavigationService aggregates navigation from all modules
- [ ] ComponentRegistryService tracks embeddable components
- [ ] ActionRegistry integrates with public actions
- [ ] ModuleProviderService resolves provider/consumer contracts
✅ **Runtime Features**
- [ ] Dynamic component loading works correctly
- [ ] Navigation renders and filters by permissions
- [ ] Routes register and navigate properly
- [ ] Provider/Consumer DI functions correctly
---
### 8.2 Quality Success Criteria
✅ **Type Safety**
- [ ] No `any` types except `Type<any>` for component references
- [ ] Generic type parameters used where appropriate
- [ ] Runtime validation for all manifest structures
- [ ] ModuleValidator service functional
✅ **Testing Coverage**
- [ ] Unit test coverage ≥ 90%
- [ ] Integration tests for all service interactions
- [ ] Migration tests for backward compatibility
- [ ] E2E tests for user workflows
- [ ] All tests passing in CI/CD
✅ **Performance**
- [ ] Component loading <100ms (95th percentile)
- [ ] Navigation rendering <50ms
- [ ] No memory leaks in dynamic loading
- [ ] Performance tests passing
✅ **Security**
- [ ] Permission validation for all navigation items
- [ ] Embeddable components require permissions
- [ ] Public actions validate permissions
- [ ] Multi-tenant isolation verified
---
### 8.3 Documentation Success Criteria
✅ **Interface Documentation**
- [ ] All interfaces have comprehensive JSDoc
- [ ] Code examples for all major interfaces
- [ ] Type parameter explanations included
✅ **Developer Guides**
- [ ] Migration guide complete with examples
- [ ] Pattern documentation for navigation, components, actions
- [ ] Example modules (Products, CMS) implemented
✅ **Architecture Decisions**
- [ ] ADR for Signals vs Observables
- [ ] ADR for Provider/Consumer pattern
- [ ] ADR for multi-tenant isolation
- [ ] All ADRs reviewed and approved
---
## 9. Timeline Estimate
| Phase | Tasks | Estimated Effort | Dependencies |
|-------|-------|------------------|--------------|
| **Phase 1: Interface Foundation** | Define all supporting interfaces | 4-6 hours | None |
| **Phase 2: Service Integration** | Update core services | 12-16 hours | Phase 1 |
| **Phase 3: Runtime Features** | Dynamic loading, DI, routing | 20-24 hours | Phase 2 |
| **Phase 4: Testing & Validation** | Comprehensive test suite | 12-16 hours | Phase 3 |
| **Phase 5: Documentation** | Guides, examples, ADRs | 8-12 hours | Phase 4 |
| **Total** | | **56-74 hours** | **~2 weeks** |
**Assumptions**:
- 1 developer full-time
- No major blockers or scope changes
- Reviews and feedback integrated continuously
**Milestones**:
- **Week 1 End**: Phase 1 + Phase 2 complete (interfaces + service integration)
- **Week 2 Mid**: Phase 3 complete (runtime features)
- **Week 2 End**: Phase 4 + Phase 5 complete (testing + documentation)
---
## 10. Next Steps
### Immediate Actions (Before Implementation)
1. **Review this plan** with team and stakeholders
2. **Clarify questions**:
- Observable vs Signal for badges (confirm decision)
- Type<any> vs generic parameters (determine preference)
- Provider/Consumer pattern vs alternatives (validate approach)
3. **Create implementation branch**: `feature/manifest-update`
4. **Set up project tracking**: Create tasks in project management tool
5. **Schedule review sessions**: Mid-phase and end-phase reviews
### Implementation Kickoff
1. **Phase 1 Start**:
- Create feature branch
- Set up test infrastructure
- Begin interface definitions
- Update TodoWrite with Phase 1 tasks
2. **Continuous Integration**:
- Commit interfaces as they're completed
- Run tests on every commit
- Update documentation alongside code
- Request reviews for major interfaces
3. **Risk Monitoring**:
- Track type safety issues
- Monitor test coverage
- Validate performance benchmarks
- Document any scope changes
---
## 11. Appendix
### A. Interface Dependency Graph
ModuleManifest ├── NavigationConfig │ ├── NavigationMenuItem │ ├── BreadcrumbConfig │ └── ToolbarConfig ├── ModuleRoute ├── ModuleEmbeddableComponent │ └── ComponentInput ├── ModulePublicAction ├── ModuleProvider ├── ModuleConsumer ├── ModuleDependency ├── ModuleConfigSchema ├── ModuleAssets ├── ModuleExports └── ModuleImports
### B. Service Interaction Diagram
ModuleRegistryService ├── processes → ModuleManifest ├── registers navigation → NavigationService ├── registers components → ComponentRegistryService ├── registers actions → ActionRegistryService (from @libs-core/action-registry) └── registers providers → ModuleProviderService
NavigationService ├── aggregates navigation from all modules ├── filters by permissions → SecurityService └── renders UI → NavigationComponent
ComponentRegistryService ├── tracks embeddable components ├── loads dynamically → DynamicComponentLoaderService └── manages lifecycle
ModuleProviderService ├── collects providers from all modules ├── validates consumers have providers ├── creates DI tokens └── injects implementations
### C. Key Files to Create/Modify
**New Files** (to be created):
/libs/core/module-base/src/lib/contracts/ ├── navigation.interface.ts ├── embeddable-component.interface.ts ├── public-action.interface.ts ├── provider-consumer.interface.ts ├── module-config.interface.ts └── module-assets.interface.ts
/libs/core/module-base/src/lib/services/ ├── navigation.service.ts ├── component-registry.service.ts ├── dynamic-component-loader.service.ts ├── module-provider.service.ts └── module-router.service.ts
/libs/core/module-base/src/lib/validators/ └── module-validator.service.ts
/libs/core/module-base/tests/ ├── interfaces/ (multiple test files) ├── services/ (multiple test files) ├── integration/ (multiple test files) └── migration/ (multiple test files)
/docs/libs/module-base/ ├── manifest-guide.md ├── migration-guide.md ├── examples/ │ ├── products-module-manifest.example.ts │ ├── cms-module-manifest.example.ts │ └── minimal-module-manifest.example.ts └── adrs/ ├── 001-signals-for-navigation.md ├── 002-provider-consumer-pattern.md └── 003-multi-tenant-isolation.md
**Modified Files**:
/libs/core/module-base/src/lib/contracts/ └── module-manifest.interface.ts (EXPAND)
/libs/core/module-base/src/lib/services/ ├── module-registry.service.ts (UPDATE) ├── module-discovery.service.ts (UPDATE) └── module-state.service.ts (UPDATE)
/libs/core/module-base/src/index.ts (UPDATE barrel exports)
/docs/libs/module-base.md (UPDATE with accurate current state)
---
## Conclusion
This comprehensive plan provides a structured, phased approach to updating the `ModuleManifest` interface from a minimal identification structure to a comprehensive module introspection and communication system.
**Key Strengths**:
- ✅ Backward compatible - existing code continues working
- ✅ Phased implementation - reduce risk through incremental delivery
- ✅ Comprehensive testing - unit, integration, migration, E2E
- ✅ Full documentation - guides, examples, ADRs
- ✅ Angular 20 compliant - Signals, standalone, modern patterns
- ✅ Multi-tenant ready - all structures support tenant isolation
**Next Step**: Review this plan with the team, clarify any questions, and proceed with Phase 1 implementation.
---
**Plan Version**: 1.0
**Created**: 2025-10-09
**Status**: Draft - Awaiting Review