gateway/import_map_analysis.md
2025-12-07 13:48:39 +01:00

11 KiB

Import Map Analysis: interfaces ↔ connectors ↔ security

Overview

This document maps all imports between modules/interfaces, modules/connectors, and modules/security to identify structural issues, circular dependencies, and architectural concerns.

Architectural Principle:

  • Connectors (infrastructure) can import from Security (infrastructure)
  • Interfaces (business logic) can import from Security (infrastructure)
  • Interfaces (business logic) can import from Connectors (infrastructure)
  • Connectors should NOT import from Interfaces (business logic)

Import Dependencies Map

CONNECTORS → SECURITY

connectorDbPostgre.py

  • Imports from security:
    • from modules.security.rbac import RbacClass (line 13)
    • Usage:
      • Runtime instantiation: RbacClass(self) in getRecordsetWithRBAC() (line 1073)
      • Creates RbacClass instance to get user permissions
    • Status: ARCHITECTURALLY CORRECT - Connectors can import from security module

SECURITY → CONNECTORS

security/rbac.py (moved from interfaces/interfaceRbac.py)

  • Imports from connectors:
    • from modules.connectors.connectorDbPostgre import DatabaseConnector (line 11, inside TYPE_CHECKING)
    • Usage: Type hint only (db: "DatabaseConnector")
    • Status: Fixed with TYPE_CHECKING to avoid circular import
    • Architecture: Correct - Security module can import from connectors (infrastructure layer)

INTERFACES → CONNECTORS

interfaceBootstrap.py

  • Imports from connectors:
    • from modules.connectors.connectorDbPostgre import DatabaseConnector (line 9)
    • Usage: Function parameter types (initBootstrap(db: DatabaseConnector))

interfaceDbAppObjects.py

  • Imports from connectors:
    • from modules.connectors.connectorDbPostgre import DatabaseConnector (line 12)
    • Usage: Class initialization (self.db: DatabaseConnector)
  • Imports from security:
    • from modules.security.rbac import RbacClass (line 17)
    • Usage: RBAC permission checking
    • Architecture: Correct - Interfaces can import from security (infrastructure layer)

interfaceDbChatObjects.py

  • Imports from connectors:
    • from modules.connectors.connectorDbPostgre import DatabaseConnector (line 29)
    • Usage: Class initialization

interfaceDbComponentObjects.py

  • Imports from connectors:
    • from modules.connectors.connectorDbPostgre import DatabaseConnector (line 13)
    • Usage: Class initialization

interfaceVoiceObjects.py

  • Imports from connectors:
    • from modules.connectors.connectorVoiceGoogle import ConnectorGoogleSpeech (line 10)
    • Usage: Class initialization

Circular Dependency Analysis

CIRCULAR DEPENDENCY #1: RESOLVED

connectorDbPostgre.py (line 13)
  └─> imports RbacClass from security.rbac
       └─> Uses: RbacClass(self) at runtime (line 1073)

security/rbac.py (line 11, inside TYPE_CHECKING)
  └─> imports DatabaseConnector (type hint only)

Status: RESOLVED by moving RBAC to security module + TYPE_CHECKING

Architectural Fix:

  • Moved interfaceRbac.pysecurity/rbac.py
  • Connectors can import from security (infrastructure layer)
  • Interfaces can import from security (business logic layer)
  • No architectural violation: security is shared infrastructure

Solution Applied:

# security/rbac.py
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from modules.connectors.connectorDbPostgre import DatabaseConnector

class RbacClass:
    def __init__(self, db: "DatabaseConnector"):  # String annotation
        self.db = db  # Uses db at runtime, but import is deferred

Why This Works:

  1. At import time: connectorDbPostgre imports RbacClass
  2. RbacClass tries to import DatabaseConnector but it's inside TYPE_CHECKING, so no actual import occurs
  3. At runtime: When getRecordsetWithRBAC() calls RbacClass(self), DatabaseConnector is already fully loaded
  4. Runtime circular reference is safe because Python objects can reference each other once loaded

Architecture Analysis

Current Structure

┌─────────────────────────────────────────────────────────────┐
│                      CONNECTORS                             │
│  (Database, External Services)                             │
│                                                              │
│  connectorDbPostgre.py                                     │
│    └─> Uses: RbacClass (runtime instantiation) ⚠️      │
│                                                              │
│  connectorVoiceGoogle.py                                   │
│  connectorTicketsClickup.py                                 │
│  connectorTicketsJira.py                                    │
└─────────────────────────────────────────────────────────────┘
                          ▲
                          │ imports
                          │
┌─────────────────────────────────────────────────────────────┐
│                      INTERFACES                             │
│  (Business Logic, Data Access Layer)                       │
│                                                              │
│  security/rbac.py (moved from interfaces)                  │
│    └─> Uses: DatabaseConnector (type hint only) ✅         │
│    └─> Can be imported by both connectors and interfaces   │
│                                                              │
│  interfaceBootstrap.py                                      │
│    └─> Uses: DatabaseConnector                              │
│                                                              │
│  interfaceDbAppObjects.py                                 │
│    └─> Uses: DatabaseConnector                             │
│    └─> Uses: security.rbac.RbacClass                    │
│    └─> Uses: interfaceBootstrap.initBootstrap             │
│                                                              │
│  interfaceDbChatObjects.py                                 │
│    └─> Uses: DatabaseConnector                             │
│                                                              │
│  interfaceDbComponentObjects.py                             │
│    └─> Uses: DatabaseConnector                            │
│                                                              │
│  interfaceVoiceObjects.py                                  │
│    └─> Uses: connectorVoiceGoogle.ConnectorGoogleSpeech   │
└─────────────────────────────────────────────────────────────┘

Potential Issues & Recommendations

RESOLVED ISSUES

  1. Circular Import: security.rbac ↔ connectorDbPostgre
    • Status: Resolved by moving to security module + TYPE_CHECKING
    • Impact: None - Proper architectural layering maintained

⚠️ POTENTIAL ISSUES

  1. Tight Coupling: Interfaces depend on specific connectors

    • Issue: interfaceDbAppObjects.py directly imports DatabaseConnector
    • Impact: Makes it harder to swap database implementations
    • Recommendation: Consider dependency injection or abstract base class
  2. Connector importing from Security (connectorDbPostgre → security.rbac)

    • Status: RESOLVED - Moved RBAC to security module
    • Current Usage: Runtime instantiation in getRecordsetWithRBAC() (line 1073)
    • Code:
      RbacInstance = RbacClass(self)
      permissions = RbacInstance.getUserPermissions(...)
      
    • Architecture: Correct - Connectors can import from security (infrastructure layer)
    • Rationale: Security is shared infrastructure, not business logic
  3. Multiple interfaces importing same connector

    • Files importing DatabaseConnector:
      • interfaceBootstrap.py
      • interfaceDbAppObjects.py
      • interfaceDbChatObjects.py
      • interfaceDbComponentObjects.py
    • Impact: Medium - creates coupling
    • Recommendation: Consider a shared database interface abstraction

Recommendations

1. Move RBAC Logic Out of Connector

Current: connectorDbPostgre.getRecordsetWithRBAC() instantiates RbacClass(self) at runtime Recommendation:

  • Move getRecordsetWithRBAC() to interfaceRbac.py or interfaceDbAppObjects.py RESOLVED - RBAC moved to security module
  • Connector should only handle raw database operations
  • Interface layer handles RBAC filtering

2. Use Dependency Injection

Current: Interfaces directly import DatabaseConnector Recommendation:

  • Create abstract base class DatabaseConnectorBase
  • Interfaces depend on abstraction, not concrete implementation
  • Allows easier testing and swapping implementations

3. Consider Layered Architecture

┌─────────────────────────────────────┐
│   Interfaces (Business Logic)       │
│   - Uses connectors via abstraction │
└─────────────────────────────────────┘
              ▲
              │
┌─────────────────────────────────────┐
│   Connectors (Infrastructure)       │
│   - No knowledge of interfaces     │
└─────────────────────────────────────┘

4. Use TYPE_CHECKING for All Type-Only Imports

Current: security/rbac.py uses TYPE_CHECKING (moved from interfaces) Recommendation: Use TYPE_CHECKING for all type-only imports between layers


Summary

Current State:

  • 1 circular dependency RESOLVED (moved to security module)
  • Architectural violation FIXED (RBAC moved to security)
  • ⚠️ Multiple tight couplings to DatabaseConnector (acceptable for now)

Architectural Health:

  • Overall: 🟢 Good - Proper layering maintained
  • Architecture: Connectors → Security (infrastructure) Interfaces → Security (infrastructure)
  • Risk Level: Low - Clean separation of concerns

Completed Actions:

  1. DONE: Fixed circular import with TYPE_CHECKING
  2. DONE: Moved RBAC to security module (proper architectural layering)
  3. 🔄 OPTIONAL: Introduce abstraction layer for database connector (future improvement)