diff --git a/application/single_app/config.py b/application/single_app/config.py index b9da9e81..011a741d 100644 --- a/application/single_app/config.py +++ b/application/single_app/config.py @@ -95,7 +95,7 @@ EXECUTOR_TYPE = 'thread' EXECUTOR_MAX_WORKERS = 30 SESSION_TYPE = 'filesystem' -VERSION = "0.250.110" +VERSION = "0.250.111" IS_DEVELOPMENT = is_development_env_enabled() SESSION_COOKIE_SAMESITE = os.getenv('SESSION_COOKIE_SAMESITE', 'Lax') diff --git a/application/single_app/route_backend_data_management.py b/application/single_app/route_backend_data_management.py index d5d97dfb..dd411f44 100644 --- a/application/single_app/route_backend_data_management.py +++ b/application/single_app/route_backend_data_management.py @@ -769,25 +769,6 @@ def get_admin_data_management_migration_catalog(target_type): return jsonify({"success": False, "error": str(exc)}), 400 return jsonify({"success": True, **catalog}), 200 - @bp.route("/api/admin/data-management/restore/review", methods=["POST"]) - @swagger_route(security=get_auth_security()) - @login_required - @admin_required - def review_admin_data_management_restore(): - payload = request.get_json(silent=True) or {} - restore_plan = payload.get("restore_plan") if isinstance(payload.get("restore_plan"), dict) else {} - try: - review = review_data_management_restore(restore_plan) - except Exception as exc: - log_event( - "[DataManagement] Restore review failed.", - {"error": str(exc)}, - level=logging.ERROR, - exceptionTraceback=True, - ) - return jsonify({"success": False, "error": "Restore review could not be completed."}), 400 - return jsonify({"success": True, "review": review}), 200 - @bp.route("/api/admin/data-management/migration/summary", methods=["POST"]) @swagger_route(security=get_auth_security()) @login_required diff --git a/docs/explanation/fixes/DATA_MANAGEMENT_RESTORE_ROUTE_ENDPOINT_COLLISION_FIX.md b/docs/explanation/fixes/DATA_MANAGEMENT_RESTORE_ROUTE_ENDPOINT_COLLISION_FIX.md new file mode 100644 index 00000000..d100893a --- /dev/null +++ b/docs/explanation/fixes/DATA_MANAGEMENT_RESTORE_ROUTE_ENDPOINT_COLLISION_FIX.md @@ -0,0 +1,44 @@ +# Data Management Restore Route Endpoint Collision Fix + +Fixed/Implemented in version: **0.250.111** + +## Issue Description + +Application startup failed while registering the Data Management Blueprint because two restore review routes used the same URL and endpoint function name. + +## Root Cause Analysis + +An earlier restore review handler remained in `route_backend_data_management.py` after the authorization-aware restore review workflow was added. Flask therefore attempted to register `backend_data_management.review_admin_data_management_restore` twice and raised an `AssertionError`. + +## Technical Details + +Files modified: + +- `application/single_app/route_backend_data_management.py` +- `application/single_app/config.py` +- `functional_tests/test_data_management_security_patterns.py` + +Code changes summary: + +- Removed the obsolete duplicate restore review route. +- Retained the complete handler that validates settings and restore plans and issues restore review authorization tokens. +- Added a regression assertion requiring unique route endpoint names in the Data Management Blueprint. +- Updated the application version to `0.250.111`. + +Impact analysis: + +- The Data Management Blueprint can register during application startup. +- The restore review API path and authorization-aware behavior remain unchanged. + +## Validation + +Test results: + +- The endpoint uniqueness regression test passes with 28 unique Data Management routes. +- Data Management route security and route policy tests validate authentication and Blueprint registration contracts. + +Before: Flask stopped startup because the restore review endpoint was registered twice. + +After: Flask registers one restore review endpoint backed by the guarded restore workflow. + +Version reference: `application/single_app/config.py` version `0.250.111`. \ No newline at end of file diff --git a/docs/explanation/fixes/index.md b/docs/explanation/fixes/index.md index 05f85985..ebd43a09 100644 --- a/docs/explanation/fixes/index.md +++ b/docs/explanation/fixes/index.md @@ -6,6 +6,7 @@ order: 120 category: Version History --- +- [Data Management Restore Route Endpoint Collision Fix](DATA_MANAGEMENT_RESTORE_ROUTE_ENDPOINT_COLLISION_FIX.md) - [Font Size and 200 Percent Zoom Fix](FONT_SIZE_AND_200_PERCENT_ZOOM_FIX.md) - [Public Workspace Prompt Migration Fix](PUBLIC_WORKSPACE_PROMPT_MIGRATION_FIX.md) - [Azure OpenAI Model Discovery Identity Fix](v0.250.001/AZURE_OPENAI_MODEL_DISCOVERY_IDENTITY_FIX.md) diff --git a/docs/explanation/release_notes.md b/docs/explanation/release_notes.md index 5a31ac99..f85eb61d 100644 --- a/docs/explanation/release_notes.md +++ b/docs/explanation/release_notes.md @@ -2,6 +2,15 @@ For feature-focused and fix-focused drill-downs by version, see [Features by Version](/explanation/features/) and [Fixes by Version](/explanation/fixes/). +### **(v0.250.111)** + +#### Bug Fixes + +* **Data Management Restore Route Registration** + * Fixed application startup failure caused by duplicate Data Management restore review route and endpoint registrations. + * Preserved the authorization-aware restore review workflow and added regression coverage requiring unique Blueprint endpoint names. + * (Ref: `route_backend_data_management.py`, `test_data_management_security_patterns.py`, `DATA_MANAGEMENT_RESTORE_ROUTE_ENDPOINT_COLLISION_FIX.md`) + ### **(v0.250.110)** #### New Features diff --git a/functional_tests/test_data_management_security_patterns.py b/functional_tests/test_data_management_security_patterns.py index aeccc684..06e0c6c7 100644 --- a/functional_tests/test_data_management_security_patterns.py +++ b/functional_tests/test_data_management_security_patterns.py @@ -2,7 +2,7 @@ # test_data_management_security_patterns.py """ Functional test for Data Management security patterns. -Version: 0.250.108 +Version: 0.250.111 Implemented in: 0.241.211 Updated in: 0.250.102 Updated in: 0.250.103 @@ -10,6 +10,7 @@ Updated in: 0.250.105 Updated in: 0.250.106 Updated in: 0.250.108 +Updated in: 0.250.111 This test ensures Data Management admin routes require authenticated admin access, secrets stay redacted in frontend responses, and the admin browser @@ -26,6 +27,7 @@ admin cancellation/retry controls, and latest-only sidecar state sanitization. Version 0.250.103 verifies paginated migration catalogs and sanitized server-owned review results. +Version 0.250.111 verifies Data Management Blueprint endpoint names are unique. """ import ast @@ -76,7 +78,7 @@ def test_version_and_container_registration(): """Validate the Data Management version and Cosmos job container registrations.""" config_source = read_text(CONFIG_FILE) - assert 'VERSION = "0.250.108"' in config_source + assert 'VERSION = "0.250.111"' in config_source assert 'cosmos_data_management_jobs_container_name = "data_management_jobs"' in config_source assert 'partition_key=PartitionKey(path="/id")' in config_source assert 'cosmos_data_management_job_items_container_name = "data_management_job_items"' in config_source @@ -96,7 +98,12 @@ def test_version_and_container_registration(): def test_admin_routes_require_login_admin_and_swagger_security(): """Validate every Data Management route has the required admin security stack.""" routes = route_functions_with_decorators() - assert len(routes) == 29 + assert len(routes) == 28 + + route_function_names = [function_name for function_name, _decorators in routes] + assert len(route_function_names) == len(set(route_function_names)), ( + "Data Management route endpoint names must be unique" + ) for function_name, decorators in routes: assert "swagger_route" in decorators, f"{function_name} missing swagger_route"