Skip to content

Commit daece57

Browse files
authored
ITEP-92735: Mapping service should communicate with outside world over proxy (#1469)
This PR updates SceneScape’s mapping service exposure so external clients access it through the manager’s Apache reverse proxy (instead of directly via :8444), aligning service-to-outside-world communication with the existing proxy pattern used for autocalibration.
1 parent 877de83 commit daece57

31 files changed

Lines changed: 440 additions & 380 deletions

.github/copilot-instructions.md

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -129,33 +129,15 @@ make rebuild-core # Clean + build (useful after code changes)
129129

130130
## Testing Framework
131131

132-
**For comprehensive test creation guidance, see `.github/skills/testing/SKILL.md`** - detailed instructions on creating unit, functional, integration, UI, and smoke tests with both positive and negative cases.
132+
Testing guidance is intentionally centralized in skills to avoid duplication.
133133

134-
**Test infrastructure** is fully pytest-based. Docker Compose lifecycle is managed by session-scoped fixtures in `tests/conftest.py`. Tests declare their service requirements via a module-level `SCENESCAPE_SPEC` using `FuncTestSpec` + `ServiceProfile`.
134+
- Canonical test authoring and categorization guidance: `.github/skills/testing/SKILL.md`
135+
- Canonical runtime verification and completion rules: `.github/skills/test-verification-gate/SKILL.md`
135136

136-
**Running Tests** (from repo root):
137+
At this level, only rely on high-level routing:
137138

138-
```bash
139-
make setup-tests # Build test images, secrets, venv
140-
make run_basic_acceptance_tests # Smoke tests (functional + ui + unit + stability)
141-
make run_standard_tests # Functional + UI + security + stability
142-
make run_functional_tests # Functional tests only
143-
make run_ui_tests # UI/Selenium tests only
144-
make run_unit_tests # Unit tests only (sscape_tests)
145-
make run_metric_tests # Tracker quality metrics
146-
make run_performance_tests # Inference performance + geometry
147-
make run_stability_tests HOURS=24 # Long-running stability
148-
```
149-
150-
**Running tests directly with pytest** (from repo root, with tests/.venv activated):
151-
152-
```bash
153-
pytest tests/sscape_tests # Unit tests
154-
pytest tests/functional # All functional tests
155-
pytest tests/functional/test_roi_mqtt.py # Single functional test
156-
pytest tests/ -m basic_acceptance # Smoke suite only
157-
pytest tests/ --junitxml=results.xml 2>&1 | tee output.log # Save results to file
158-
```
139+
- Test infrastructure is pytest-based with Docker Compose lifecycle managed in `tests/conftest.py`.
140+
- Prefer root `Makefile` test targets for execution unless a narrower, explicit pytest invocation is required.
159141

160142
### Completion Gate For Test Tasks (Critical)
161143

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,13 @@ init-secrets: $(SECRETSDIR) certificates auth-secrets
736736

737737
$(SECRETSDIR):
738738
mkdir -p $@
739-
chmod go-rwx $(SECRETSDIR)
739+
@if ! chmod go-rwx $(SECRETSDIR); then \
740+
if [ "$${CI}" = "true" ] || [ "$${CI}" = "1" ]; then \
741+
echo "Warning: could not set restrictive permissions on $(SECRETSDIR) in CI; secrets may be more exposed on this filesystem. Ensure runner isolation controls are in place."; \
742+
else \
743+
exit 1; \
744+
fi; \
745+
fi
740746

741747
.PHONY: $(SECRETSDIR) certificates
742748
certificates:

autocalibration/src/auto_camera_calibration_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def __init__(self, calibrationContext=None):
130130
self.app.config['MAX_CONTENT_LENGTH'] = self.MAX_REQUEST_SIZE
131131
self.calibrationContext = calibrationContext
132132

133-
self.socketio = SocketIO(self.app, cors_allowed_origins=["*"])
133+
self.socketio = SocketIO(self.app, path="/v1/socket.io/", cors_allowed_origins=["*"])
134134
if self.calibrationContext is not None:
135135
self.calibrationContext.socketio = self.socketio
136136
self.socket_client = {}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# SPDX-FileCopyrightText: (C) 2026 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
from scene_common.rest_client import RESTClient
5+
6+
7+
class AutoCalibrationClient(RESTClient):
8+
"""Client for auto-calibration REST endpoints."""
9+
10+
def getStatus(self):
11+
"""Gets auto-calibration service status."""
12+
return self._get("status", None)
13+
14+
def registerScene(self, sceneId, data):
15+
"""Register a scene for auto-calibration."""
16+
return self._create(f"scenes/{sceneId}/registration", data)
17+
18+
def getSceneRegistrationStatus(self, sceneId):
19+
"""Gets scene registration status."""
20+
return self._get(f"scenes/{sceneId}/registration", None)
21+
22+
def updateSceneRegistration(self, sceneId, data):
23+
"""Updates scene registration."""
24+
return self._update(f"scenes/{sceneId}/registration", data)
25+
26+
def calibrateCamera(self, cameraId, data):
27+
"""Calibrate a camera."""
28+
return self._create(f"cameras/{cameraId}/calibration", data)
29+
30+
def getCameraCalibrationStatus(self, cameraId):
31+
"""Gets camera calibration status."""
32+
return self._get(f"cameras/{cameraId}/calibration", None)

common.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ build-image: $(BUILD_DIR) Dockerfile
3131
@{ \
3232
set -xe; \
3333
set -o pipefail; \
34+
EXTRA_BUILD_ARGS="$(EXTRA_BUILD_ARGS)"; \
3435
if [ "$(GHCR_CACHE)" = "true" ]; then \
3536
EXTRA_BUILD_ARGS+=" --cache-from type=registry,ref=ghcr.io/${CACHE_REGISTRY}/$(IMAGE):main"; \
3637
if [ "$(WRITE_CACHE)" = "true" ]; then \

docs/user-guide/microservices/auto-calibration/_assets/autocalibration-api.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ info:
1717

1818
servers:
1919
- url: "https://localhost:8443/v1"
20+
description: Direct standalone access
21+
- url: "https://localhost/api/v1/autocalibration"
22+
description: Access via Apache reverse proxy when web service is running
2023

2124
components:
2225
schemas:

docs/user-guide/microservices/mapping-service/api-docs/mapping-api.yaml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ info:
77
description: |
88
REST API service for 3D reconstruction with build-time model selection.
99
10+
Authentication/Authorization status:
11+
- This service currently does not implement endpoint-level AuthN/AuthZ.
12+
- Protect access using trusted network boundaries, reverse proxy controls, and TLS.
13+
1014
This service provides endpoints for performing 3D reconstruction from multiple input images. The model is selected at build time:
1115
- **MapAnything**: Universal Feed-Forward Metric 3D Reconstruction
1216
- **VGGT**: Visual Geometry Grounded Transformer for sparse view reconstruction
@@ -18,10 +22,10 @@ info:
1822
url: https://www.apache.org/licenses/LICENSE-2.0.html
1923

2024
servers:
21-
- url: https://localhost:8444
22-
description: Local development server
23-
- url: https://0.0.0.0:8444
24-
description: Docker container server
25+
- url: https://localhost:8444/v1
26+
description: Direct standalone access
27+
- url: https://localhost/api/v1/mapping
28+
description: Access via Apache reverse proxy when web service is running
2529

2630
tags:
2731
- name: reconstruction

docs/user-guide/microservices/mapping-service/build-from-source.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ The response will include which model was used:
111111
### Health Check
112112

113113
```bash
114-
curl https://localhost:8444/health
114+
curl https://localhost:8444/v1/health
115115
```
116116

117117
Response includes model information:
@@ -128,7 +128,7 @@ Response includes model information:
128128
### Model Information
129129

130130
```bash
131-
curl https://localhost:8444/models
131+
curl https://localhost:8444/v1/models
132132
```
133133

134134
Response shows single model details:

docs/user-guide/microservices/mapping-service/mapping-service.md

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ sequenceDiagram
4343

4444
## API Endpoints
4545

46+
> **Security note:** Mapping service endpoints currently do not enforce endpoint-level
47+
> authentication or authorization. Deploy behind trusted network boundaries and reverse
48+
> proxy controls, and use TLS for transport protection.
49+
4650
### Health Check
4751

4852
```bash
@@ -130,34 +134,40 @@ the service from source and running it.
130134
```python
131135
import base64
132136
import requests
133-
134-
# Encode images to base64
135-
def encode_image(image_path):
136-
with open(image_path, "rb") as f:
137-
return base64.b64encode(f.read()).decode('utf-8')
138-
139-
# Prepare request
140-
payload = {
141-
"images": [
142-
{"data": encode_image("image1.jpg"), "filename": "image1.jpg"},
143-
{"data": encode_image("image2.jpg"), "filename": "image2.jpg"}
144-
],
145-
"output_format": "glb"
137+
from pathlib import Path
138+
139+
# Prepare multipart request
140+
files = []
141+
handles = []
142+
for image_path in ["image1.jpg", "image2.jpg"]:
143+
path = Path(image_path)
144+
handle = path.open("rb")
145+
handles.append(handle)
146+
files.append(("images", (path.name, handle, "image/jpeg")))
147+
148+
data = {
149+
"output_format": "glb",
150+
"mesh_type": "mesh",
146151
}
147152

148-
# Send request
149-
response = requests.post("https://localhost:8444/reconstruction", json=payload)
150-
result = response.json()
153+
try:
154+
try:
155+
# Send request through the Apache reverse proxy used in the full stack deployment
156+
response = requests.post("https://localhost/api/v1/mapping/reconstruction", data=data, files=files, verify=False)
157+
result = response.json()
151158

152-
if result["success"]:
159+
if result["success"]:
153160
# Save GLB file
154161
glb_data = base64.b64decode(result["glb_data"])
155162
with open("output.glb", "wb") as f:
156-
f.write(glb_data)
163+
f.write(glb_data)
157164

158165
print(f"Model used: {result['model']}")
159166
print(f"Processing time: {result['processing_time']:.2f}s")
160167
print(f"Camera poses: {len(result['camera_poses'])}")
168+
finally:
169+
for handle in handles:
170+
handle.close()
161171
```
162172

163173
### Using the Included Client
@@ -175,29 +185,29 @@ python client_example.py --images image1.jpg image2.jpg --mesh-type pointcloud -
175185

176186
```bash
177187
# Health check
178-
curl https://localhost:8444/health --insecure
188+
curl https://localhost:8444/v1/health --insecure
179189

180190
# List models
181-
curl https://localhost:8444/models --insecure
191+
curl https://localhost:8444/v1/models --insecure
182192

183193
# Reconstruction with images (using multipart/form-data - recommended)
184-
curl -X POST "https://localhost:8444/reconstruction" \
194+
curl -X POST "https://localhost:8444/v1/reconstruction" \
185195
-F "images=@image1.jpg" \
186196
-F "images=@image2.jpg" \
187197
-F "output_format=glb" \
188198
-F "mesh_type=mesh" \
189199
--insecure
190200

191201
# Reconstruction with video
192-
curl -X POST "https://localhost:8444/reconstruction" \
202+
curl -X POST "https://localhost:8444/v1/reconstruction" \
193203
-F "video=@video.mp4" \
194204
-F "output_format=glb" \
195205
-F "mesh_type=mesh" \
196206
-F "use_keyframes=true" \
197207
--insecure
198208

199209
# Reconstruction with both images and video
200-
curl -X POST "https://localhost:8444/reconstruction" \
210+
curl -X POST "https://localhost:8444/v1/reconstruction" \
201211
-F "images=@image1.jpg" \
202212
-F "images=@image2.jpg" \
203213
-F "video=@video.mp4" \
@@ -206,7 +216,7 @@ curl -X POST "https://localhost:8444/reconstruction" \
206216
--insecure
207217

208218
# Save GLB output to file (requires jq for JSON parsing)
209-
curl -X POST "https://localhost:8444/reconstruction" \
219+
curl -X POST "https://localhost:8444/v1/reconstruction" \
210220
-F "images=@image1.jpg" \
211221
-F "images=@image2.jpg" \
212222
-F "output_format=glb" \

kubernetes/scenescape-chart/templates/mapping/deployment.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ spec:
4242
command:
4343
- sh
4444
- -c
45-
- curl -k -s https://localhost:8444/health
45+
- curl -k -s https://localhost:8444/v1/health
4646
periodSeconds: 10
4747
timeoutSeconds: 60
4848
failureThreshold: 5

0 commit comments

Comments
 (0)