Skip to main content

42. Dependency Injection Configuration Fixes

Date: 2025-01-28

Status

Accepted

Category

Core Architecture

Context

OpenAI Codex identified three critical runtime failures and two high-priority configuration issues in our dependency injection system that would cause production outages:

Critical Risks Identified

  1. Keycloak Admin Credentials Not Wired (dependencies.py:31-40)
    • Admin username/password from settings were not passed to KeycloakConfig
    • Caused all admin API operations to fail with 400/401 errors
    • Affected: API key CRUD, service principal creation, user management
  2. OpenFGA Client Always Instantiated Despite Missing Config (dependencies.py:45-59)
    • Client created even when store_id=None and model_id=None
    • OpenFGA SDK raises errors on first check_permission() call
    • Caused confusing 500 errors, broke graceful degradation
  3. Service Principal Manager Crashes When OpenFGA Disabled (service_principal.py:197-221)
    • _sync_to_openfga() assumed self.openfga is always usable
    • Caused AttributeError: 'NoneType' object has no attribute 'write_tuples'
    • Broke service principal workflows in environments without OpenFGA

High Priority Issues

  1. L2 Cache Ignores Secure Redis Settings (cache.py:94-120)
    • Used redis.Redis(host=..., port=...) instead of redis.from_url()
    • Ignored settings.redis_url, settings.redis_password, settings.redis_ssl
    • Caused silent fallback to L1-only in production, degrading performance
  2. Missing Startup/Integration Test Coverage
    • No tests validating dependency factory wiring
    • Bugs only discovered at runtime in production
    • No smoke tests for FastAPI/MCP server startup with default settings

Decision

We implement defensive configuration with fail-fast validation and graceful degradation for all dependency factories.

1. Fix Keycloak Admin Credentials

Changed: src/mcp_server_langgraph/core/dependencies.py:34-40
Impact:
  • ✅ Admin API operations now authenticate correctly
  • ✅ API key manager can create/delete keys
  • ✅ Service principal creation works
  • ✅ User management operations succeed

2. Add OpenFGA Configuration Validation

Changed: src/mcp_server_langgraph/core/dependencies.py:47-76
Impact:
  • ✅ Returns None when config incomplete instead of broken client
  • ✅ Logs clear warning about missing configuration
  • ✅ Enables graceful degradation in non-production environments
  • ✅ Prevents confusing 500 errors from OpenFGA SDK

3. Add OpenFGA Guards in Service Principal Manager

Changed: src/mcp_server_langgraph/auth/service_principal.py

3a. Update Constructor Type Hint

3b. Guard _sync_to_openfga Method

3c. Guard associate_with_user Method

3d. Guard delete_service_principal Method

Impact:
  • ✅ No more AttributeError crashes when OpenFGA disabled
  • ✅ Service principal operations work in fallback mode
  • ✅ Keycloak operations succeed independently of OpenFGA
  • ✅ Clear separation of concerns (identity vs. authorization)

4. Fix L2 Cache Redis Configuration

Changed: src/mcp_server_langgraph/core/cache.py:73-138
Updated: get_cache() function to pass all settings:
Impact:
  • ✅ L2 cache now works with secure Redis deployments
  • ✅ Honors REDIS_URL, REDIS_PASSWORD, REDIS_SSL settings
  • ✅ Consistent pattern with API key manager
  • ✅ Production performance restored (L1+L2 instead of L1-only)

5. Add Comprehensive Test Coverage

Created: tests/unit/core/test_dependencies_wiring.py Tests added (following TDD):
  1. Keycloak admin credential wiring
    • Validates admin_username and admin_password are passed
    • Documents failure mode without credentials
  2. OpenFGA config validation
    • Tests None returned when store_id/model_id missing
    • Tests client created when config complete
    • Tests warning logged for incomplete config
  3. Service principal OpenFGA guards
    • Tests creation succeeds with None OpenFGA client
    • Tests deletion succeeds with None OpenFGA client
    • Tests user association succeeds with None OpenFGA client
  4. Integration smoke tests
    • Tests Keycloak client factory with real settings
    • Tests OpenFGA client factory with incomplete config
    • Tests service principal manager with disabled OpenFGA
Created: tests/unit/core/test_cache_redis_config.py Tests added:
  1. Cache Redis configuration
    • Tests redis.from_url() pattern is used
    • Tests password and SSL settings honored
    • Compares with correct API key manager pattern
  2. Graceful degradation
    • Tests fallback to L1 when Redis unavailable
    • Tests production Redis URL scenarios

Consequences

Positive

  • Production Stability: All critical runtime failures fixed
  • Graceful Degradation: System works in partial-config scenarios
  • Clear Error Messages: Warnings explain missing configuration
  • Test Coverage: Comprehensive tests prevent regressions
  • Consistent Patterns: All Redis clients use from_url() pattern
  • Security: Secure Redis settings (password, SSL) now honored

Negative

  • ⚠️ API Breaking Change: get_openfga_client() now returns Optional[OpenFGAClient]
    • Callers must handle None case
    • Mitigated by: Service principal manager already handles this
  • ⚠️ Increased Verbosity: More parameters to CacheService.__init__
    • Mitigated by: Parameters have sensible defaults

Neutral

🔄 Configuration Required: OpenFGA now requires explicit configuration
  • Production: Must set OPENFGA_STORE_ID and OPENFGA_MODEL_ID
  • Development: Falls back gracefully with warning

Implementation Notes

TDD Process Followed

All fixes followed strict TDD:
  1. RED: Wrote failing tests first
  2. GREEN: Implemented minimal fix to pass tests
  3. REFACTOR: Improved code quality while keeping tests green

Migration Guide

For Keycloak Admin Operations

Ensure environment variables are set:

For OpenFGA Authorization

Either configure fully or accept degraded mode:

For Secure Redis Caching

Configure Redis with credentials:

Rollout Plan

  1. Phase 1: Deploy to development environment
    • Verify warnings for incomplete OpenFGA config
    • Verify Keycloak admin operations work
    • Verify Redis cache with credentials
  2. Phase 2: Deploy to staging environment
    • Run full test suite
    • Verify service principal workflows
    • Verify L2 cache performance metrics
  3. Phase 3: Deploy to production
    • Monitor error rates (should drop to zero)
    • Monitor cache hit rates (should increase with L2)
    • Monitor OpenFGA operation success rate

References

  • OpenAI Codex Security Review (2025-01-28)
  • ADR-0034: API Key JWT Exchange
  • ADR-0033: Service Principal Design
  • Production Incident: Revision 758b8f744 (Redis password encoding)

Verification

Pre-Deployment Checklist

  • All tests pass (pytest tests/unit/core/test_dependencies_wiring.py tests/unit/core/test_cache_redis_config.py)
  • Keycloak admin credentials wired in dependencies.py
  • OpenFGA client validates config and returns None when incomplete
  • Service principal manager guards all OpenFGA operations
  • Cache service uses redis.from_url() with password/SSL
  • ADR document created and reviewed

Post-Deployment Validation

  • No 400/401 errors from Keycloak admin operations
  • No AttributeError crashes from service principal manager
  • No 500 errors from OpenFGA SDK when disabled
  • L2 cache hit rate > 0% in production (was 0% before fix)
  • Redis connection uses TLS in production metrics

Conclusion

These fixes address 5 critical production failures identified by OpenAI Codex. All fixes follow defensive programming principles:
  1. Fail-fast validation (OpenFGA config check)
  2. Graceful degradation (OpenFGA returns None)
  3. Guard clauses (Service principal OpenFGA guards)
  4. Secure defaults (Redis password/SSL support)
  5. Comprehensive testing (100% coverage of bug scenarios)
Risk Level Before Fixes: 🔴 CRITICAL - Multiple production outages Risk Level After Fixes: 🟢 LOW - All scenarios tested and handled Recommendation: APPROVE FOR IMMEDIATE DEPLOYMENT to prevent production incidents.