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)

2.2 Integration Impact (Medium)

2.3 Ecosystem Impact (Low-Medium)


3. Design Decisions

3.1 Angular 20 Compliance

Signal vs Observable

Decision: Use Signal<number> instead of Observable<number> for navigation badges

Rationale:

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:


4. Implementation Phases

Phase 1: Interface Foundation ✅ (Low Risk)

Goal: Define all supporting interfaces and types

Tasks:

  1. Create supporting interfaces:

    • ModuleNavigationConfig + NavigationMenuItem + BreadcrumbConfig + ToolbarConfig
    • ModuleRoute (Angular Router integration)
    • ModuleEmbeddableComponent + ComponentInput
    • ModulePublicAction
    • ModuleProvider + ModuleConsumer
    • ModuleDependency
    • ModuleConfigSchema + ModuleAssets
    • ModuleExports + ModuleImports
    • ModulePermission (if not already in @libs-core/shared-models)
  2. Expand ModuleManifest interface with all new optional properties

  3. Add comprehensive JSDoc documentation with examples

Deliverables:

Acceptance Criteria:

Estimated Effort: 4-6 hours


Phase 2: Service Integration ⚙️ (Medium Risk)

Goal: Update core services to process expanded manifest properties

Tasks:

  1. 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
  2. ModuleDiscoveryService enhancements:

    • Include navigation metadata in discovery results
    • Component and action inventory
  3. Create NavigationService (new service):

    • Aggregate navigation items from all modules
    • Merge menu structures
    • Handle breadcrumb and toolbar items
    • Permission-based filtering
    • Tenant-aware navigation
  4. Create ComponentRegistryService (new service):

    • Track embeddable components from all modules
    • Dynamic component loading
    • Component lifecycle management
    • Category-based filtering (widget, list, form, dashboard)

Deliverables:

Acceptance Criteria:

Estimated Effort: 12-16 hours


Phase 3: Runtime Features 🚀 (High Complexity)

Goal: Implement dynamic loading and runtime capabilities

Tasks:

  1. Dynamic Component Loading System:

    • Create DynamicComponentLoaderService
    • Support for lazy-loaded components
    • Component instance caching
    • Input/Output binding
    • Lifecycle hooks (onInit, onDestroy)
    • Memory management
  2. 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
  3. Route Registration System:

    • Create ModuleRouterService
    • Dynamic route registration
    • Permission-based route guards
    • Lazy route loading
    • Route conflict resolution (same path from multiple modules)
  4. Navigation System:

    • Menu hierarchy builder
    • Breadcrumb trail generation
    • Toolbar item aggregation
    • Badge update mechanism (Signals)
    • Active route highlighting

Deliverables:

Acceptance Criteria:

Estimated Effort: 20-24 hours


Phase 4: Testing & Validation ✅ (Critical)

Goal: Comprehensive test coverage for all new functionality

Tasks:

  1. Unit Tests:

    • Interface validation (all supporting interfaces)
    • Service unit tests (Registry, Discovery, Navigation, ComponentRegistry)
    • Type safety verification
  2. Integration Tests:

    • Multi-module manifest processing
    • Navigation aggregation from multiple modules
    • Provider/Consumer dependency resolution
    • Action registration integration
  3. Migration Tests:

    • Backward compatibility - minimal manifests work
    • Progressive enhancement - modules adopt new features incrementally
    • Mixed scenarios - some modules minimal, others comprehensive
  4. E2E Tests:

    • Dynamic component embedding workflow
    • Navigation interaction (menu, breadcrumbs, toolbar)
    • Route navigation with permissions
    • Provider/Consumer runtime behavior

Deliverables:

Acceptance Criteria:

Estimated Effort: 12-16 hours


Phase 5: Documentation & Examples 📚 (Essential)

Goal: Complete documentation for developers implementing modules

Tasks:

  1. Interface Documentation:

    • JSDoc for all interfaces with detailed examples
    • Type parameter explanations
    • Usage guidelines
  2. Pattern Documentation:

    • Navigation patterns (menu structures, toolbar items)
    • Embeddable component patterns (widgets, dashboards)
    • Public action patterns (CRUD, workflow, integration)
    • Provider/Consumer patterns (service interop)
  3. Migration Guide:

    • Step-by-step migration from minimal to comprehensive manifests
    • Before/after code examples
    • Common pitfalls and solutions
  4. Example Modules:

    • Update example modules from docs (Products, CMS)
    • Real-world manifest examples
    • Integration examples
  5. Architecture Decision Records (ADRs):

    • Observable → Signal decision
    • Type usage justification
    • Provider/Consumer pattern rationale
    • Multi-tenant isolation strategies

Deliverables:

Acceptance Criteria:

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:

  1. Introduce generic type parameters where possible
  2. Runtime validation in ModuleRegistryService before registration
  3. Create ModuleValidator service for manifest validation
  4. 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:

  1. Memory Management:

    • Implement proper cleanup in DynamicComponentLoaderService
    • Track component instances with WeakMap
    • Unsubscribe from all subscriptions on module stop
  2. Performance Monitoring:

    • Log component load times
    • Monitor memory usage
    • Performance budgets in tests
  3. 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:

  1. Router Integration:

    • Use Angular's provideRouter and dynamic route configuration
    • Test route conflict scenarios (same path from multiple modules)
    • Document route registration order guarantees
  2. DI Integration:

    • Leverage Angular's EnvironmentInjector for module-specific DI
    • Test provider/consumer with different DI scopes
    • Document DI lifetime expectations
  3. 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:

  1. All new properties optional: Existing minimal manifests work unchanged
  2. Progressive enhancement: Services handle both minimal and comprehensive manifests
  3. Migration tests: Verify mixed scenarios (some modules updated, others not)
  4. 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:

  1. Tenant-Aware Services:

    • NavigationService filters by tenant context
    • ComponentRegistry isolates components per tenant
    • ActionRegistry validates permissions per tenant
  2. Permission Validation:

    • All navigation items checked against tenant permissions
    • Embeddable components validated before load
    • Public actions require tenant-specific authorization
  3. 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:

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:

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:

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:

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

Negative

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


---

#### 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

Negative

Implementation

ModuleProviderService will:

  1. Collect all providers from module manifests
  2. Validate all consumers have matching providers
  3. Create DI tokens for each provider interface
  4. Inject correct provider implementation into consumer modules

Alternatives Considered

Global DI (Rejected)

Event System Only (Rejected)

References


---

## 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