feat(config): consolidate configuration with smart dependency resolution (ADR-021)
Simplifies configuration by consolidating overlapping settings and adding automatic dependency resolution. This makes semantic search configuration significantly easier for users while maintaining 100% backward compatibility. ## Key Changes ### Variable Renaming (Backward Compatible) - `VECTOR_SYNC_ENABLED` → `ENABLE_SEMANTIC_SEARCH` (old name still works) - `ENABLE_OFFLINE_ACCESS` → `ENABLE_BACKGROUND_OPERATIONS` (old name still works) - Deprecation warnings logged when old names used - Old names will be removed in v1.0.0 ### Smart Dependency Resolution - `ENABLE_SEMANTIC_SEARCH` automatically enables background operations in multi-user modes - No need to set both `ENABLE_OFFLINE_ACCESS` and `VECTOR_SYNC_ENABLED` anymore - Single-user mode doesn't auto-enable background ops (not needed) ### Explicit Mode Selection (Optional) - New `MCP_DEPLOYMENT_MODE` environment variable - Valid values: single_user_basic, multi_user_basic, oauth_single_audience, oauth_token_exchange, smithery - Removes ambiguity about which deployment mode is active - Falls back to auto-detection if not set (existing behavior) ### Configuration Templates - Reorganized `env.sample` by deployment mode with clear sections - Added mode-specific quick-start templates: - `env.sample.single-user` - Simplest configuration - `env.sample.oauth-multi-user` - Recommended multi-user - `env.sample.oauth-advanced` - Token exchange mode ## Implementation Details ### Files Modified - `nextcloud_mcp_server/config.py` - Smart dependency resolution helpers - `nextcloud_mcp_server/config_validators.py` - Simplified validation, explicit mode - `tests/unit/test_config_validators.py` - 19 new tests (60 total, all passing) - `env.sample` - Reorganized by deployment mode - `docs/configuration.md` - Complete rewrite with consolidated approach - `docs/troubleshooting.md` - New consolidation troubleshooting section - `README.md` - Updated variable references ### New Files - `docs/ADR-021-configuration-consolidation.md` - Architecture decision record - `docs/configuration-migration-v2.md` - Comprehensive migration guide - `env.sample.single-user` - Single-user quick-start template - `env.sample.oauth-multi-user` - OAuth multi-user quick-start template - `env.sample.oauth-advanced` - Token exchange quick-start template ## User Impact ### Before (Confusing) ```bash ENABLE_OFFLINE_ACCESS=true # Why both? VECTOR_SYNC_ENABLED=true # What's the relationship? ``` ### After (Simplified) ```bash MCP_DEPLOYMENT_MODE=oauth_single_audience # Explicit (optional) ENABLE_SEMANTIC_SEARCH=true # Auto-enables background ops! ``` ### Benefits - 📉 2 fewer variables to understand for semantic search - 📋 Clear intent ("I want semantic search") - 🎯 Explicit mode declaration available - 🔄 100% backward compatible - ✅ All 265 unit tests passing ## Testing - All 60 config validation tests passing - 10 new tests for configuration consolidation - 9 new tests for explicit mode selection - Full unit test suite: 265 tests passing - Backward compatibility verified ## Migration Users can migrate at their own pace. Old variable names continue working with deprecation warnings. See docs/configuration-migration-v2.md for detailed migration instructions. Related: ADR-021 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.5
parent
34273ec01e
commit
1a5bb10cd0
@@ -110,10 +110,9 @@ MODE_REQUIREMENTS: dict[AuthMode, ModeRequirements] = {
|
||||
"token_encryption_key",
|
||||
"token_storage_db",
|
||||
],
|
||||
"vector_sync_enabled": [
|
||||
# Requires offline access for background sync
|
||||
"enable_offline_access",
|
||||
],
|
||||
# Note: vector_sync_enabled (now ENABLE_SEMANTIC_SEARCH) automatically
|
||||
# enables background operations in multi-user modes. No explicit
|
||||
# enable_offline_access setting required.
|
||||
},
|
||||
description="Multi-user deployment with BasicAuth pass-through. "
|
||||
"Users provide credentials in request headers. "
|
||||
@@ -152,9 +151,9 @@ MODE_REQUIREMENTS: dict[AuthMode, ModeRequirements] = {
|
||||
"token_encryption_key",
|
||||
"token_storage_db",
|
||||
],
|
||||
"vector_sync_enabled": [
|
||||
"enable_offline_access", # Background sync requires refresh tokens
|
||||
],
|
||||
# Note: vector_sync_enabled (now ENABLE_SEMANTIC_SEARCH) automatically
|
||||
# enables background operations in multi-user modes. No explicit
|
||||
# enable_offline_access setting required.
|
||||
},
|
||||
description="OAuth multi-user deployment with single-audience tokens. "
|
||||
"Tokens work for both MCP server and Nextcloud APIs (pass-through). "
|
||||
@@ -192,9 +191,9 @@ MODE_REQUIREMENTS: dict[AuthMode, ModeRequirements] = {
|
||||
"token_encryption_key",
|
||||
"token_storage_db",
|
||||
],
|
||||
"vector_sync_enabled": [
|
||||
"enable_offline_access",
|
||||
],
|
||||
# Note: vector_sync_enabled (now ENABLE_SEMANTIC_SEARCH) automatically
|
||||
# enables background operations in multi-user modes. No explicit
|
||||
# enable_offline_access setting required.
|
||||
},
|
||||
description="OAuth multi-user deployment with token exchange (RFC 8693). "
|
||||
"MCP tokens are separate from Nextcloud tokens. "
|
||||
@@ -225,7 +224,8 @@ MODE_REQUIREMENTS: dict[AuthMode, ModeRequirements] = {
|
||||
def detect_auth_mode(settings: Settings) -> AuthMode:
|
||||
"""Detect authentication mode from configuration.
|
||||
|
||||
Mode detection priority (most specific to most general):
|
||||
Mode detection priority (ADR-021):
|
||||
0. Explicit MCP_DEPLOYMENT_MODE (if set) - NEW in ADR-021
|
||||
1. Smithery (explicit flag)
|
||||
2. Token exchange (most specific OAuth mode)
|
||||
3. Multi-user BasicAuth
|
||||
@@ -237,12 +237,43 @@ def detect_auth_mode(settings: Settings) -> AuthMode:
|
||||
|
||||
Returns:
|
||||
Detected AuthMode
|
||||
|
||||
Raises:
|
||||
ValueError: If explicit deployment_mode is invalid or conflicts with detected mode
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# ADR-021: Check for explicit deployment mode first
|
||||
if settings.deployment_mode:
|
||||
mode_str = settings.deployment_mode.lower().strip()
|
||||
|
||||
# Map string to AuthMode enum
|
||||
mode_map = {
|
||||
"single_user_basic": AuthMode.SINGLE_USER_BASIC,
|
||||
"multi_user_basic": AuthMode.MULTI_USER_BASIC,
|
||||
"oauth_single_audience": AuthMode.OAUTH_SINGLE_AUDIENCE,
|
||||
"oauth_token_exchange": AuthMode.OAUTH_TOKEN_EXCHANGE,
|
||||
"smithery": AuthMode.SMITHERY_STATELESS,
|
||||
}
|
||||
|
||||
if mode_str not in mode_map:
|
||||
valid_modes = ", ".join(mode_map.keys())
|
||||
raise ValueError(
|
||||
f"Invalid MCP_DEPLOYMENT_MODE: '{settings.deployment_mode}'. "
|
||||
f"Valid values: {valid_modes}"
|
||||
)
|
||||
|
||||
explicit_mode = mode_map[mode_str]
|
||||
logger.info(f"Using explicit deployment mode: {explicit_mode.value}")
|
||||
return explicit_mode
|
||||
|
||||
# Auto-detection (existing behavior)
|
||||
# Check for Smithery mode (explicit environment variable)
|
||||
# Note: This checks the environment directly, not settings
|
||||
# because Smithery mode has no settings-based config
|
||||
import os
|
||||
|
||||
if os.getenv("SMITHERY_DEPLOYMENT", "false").lower() == "true":
|
||||
return AuthMode.SMITHERY_STATELESS
|
||||
|
||||
@@ -364,22 +395,20 @@ def validate_configuration(settings: Settings) -> tuple[AuthMode, list[str]]:
|
||||
)
|
||||
|
||||
if mode == AuthMode.MULTI_USER_BASIC:
|
||||
# Validate that if offline access enabled, we have OAuth credentials
|
||||
# Validate that if background operations enabled, we have OAuth credentials
|
||||
if settings.enable_offline_access:
|
||||
if not settings.oidc_client_id or not settings.oidc_client_secret:
|
||||
errors.append(
|
||||
f"[{mode.value}] NEXTCLOUD_OIDC_CLIENT_ID and "
|
||||
"NEXTCLOUD_OIDC_CLIENT_SECRET are required when "
|
||||
"ENABLE_OFFLINE_ACCESS is enabled (for app password retrieval)"
|
||||
"ENABLE_BACKGROUND_OPERATIONS (or deprecated ENABLE_OFFLINE_ACCESS) "
|
||||
"is enabled (for app password retrieval)"
|
||||
)
|
||||
|
||||
# Validate vector sync requirements
|
||||
if settings.vector_sync_enabled and not settings.enable_offline_access:
|
||||
errors.append(
|
||||
f"[{mode.value}] ENABLE_OFFLINE_ACCESS must be enabled when "
|
||||
"VECTOR_SYNC_ENABLED is true (background sync requires "
|
||||
"app passwords or refresh tokens)"
|
||||
)
|
||||
# Note: Vector sync no longer requires explicit ENABLE_OFFLINE_ACCESS setting
|
||||
# ENABLE_SEMANTIC_SEARCH (formerly VECTOR_SYNC_ENABLED) automatically enables
|
||||
# background operations in multi-user modes via smart dependency resolution
|
||||
# in config.py
|
||||
|
||||
# Note: Embedding provider validation removed - Simple provider is always
|
||||
# available as fallback (ADR-015). Users can optionally configure Ollama or OpenAI
|
||||
|
||||
Reference in New Issue
Block a user