diff --git a/starpilot/system/the_galaxy/tests/test_sentry_push_and_routing.py b/starpilot/system/the_galaxy/tests/test_sentry_push_and_routing.py index 63f73d089..7bb42bab0 100644 --- a/starpilot/system/the_galaxy/tests/test_sentry_push_and_routing.py +++ b/starpilot/system/the_galaxy/tests/test_sentry_push_and_routing.py @@ -62,6 +62,26 @@ def test_slug_middleware_service_worker_and_headers(client): assert response_direct.headers.get("Service-Worker-Allowed") == "/" +def test_mobile_manifest_embeds_device_slug_for_fresh_app_login(client): + galaxy_dir = the_galaxy._get_galaxy_dir() + galaxy_dir.mkdir(parents=True, exist_ok=True) + (galaxy_dir / "glxyslug").write_text("df70390ca648d7c3") + + response = client.get("/assets/mobile/manifest.json") + + assert response.status_code == 200 + assert response.mimetype == "application/manifest+json" + assert response.get_json()["start_url"] == "https://galaxy.firestar.link/df70390ca648d7c3" + assert "no-store" in response.headers.get("Cache-Control", "") + + +def test_mobile_manifest_falls_back_to_local_mobile_route_without_slug(client): + response = client.get("/assets/mobile/manifest.json") + + assert response.status_code == 200 + assert response.get_json()["start_url"] == "/mobile/" + + def test_404_api_returns_json_not_html(client): # Non-existent API route without slug res1 = client.get("/api/nonexistent") diff --git a/starpilot/system/the_galaxy/the_galaxy.py b/starpilot/system/the_galaxy/the_galaxy.py index 5837736ab..fda7d7b16 100644 --- a/starpilot/system/the_galaxy/the_galaxy.py +++ b/starpilot/system/the_galaxy/the_galaxy.py @@ -5301,6 +5301,27 @@ def setup(app): return "Settings catalog not found", 404 return send_file(str(SETTINGS_CATALOG_PATH), mimetype="application/json") + @app.route("/assets/mobile/manifest.json", methods=["GET"]) + def mobile_manifest(): + manifest_path = Path(app.static_folder) / "mobile" / "manifest.json" + if not manifest_path.is_file(): + return jsonify({"error": "Big Dipper manifest not found"}), 404 + + try: + manifest_data = json.loads(manifest_path.read_text(encoding="utf-8")) + except (OSError, ValueError, json.JSONDecodeError): + return jsonify({"error": "Big Dipper manifest is invalid"}), 500 + + slug = _read_galaxy_text(_get_galaxy_dir() / "glxyslug") + if re.fullmatch(r"[A-Za-z0-9]{16}", slug): + manifest_data["start_url"] = f"https://galaxy.firestar.link/{slug}" + else: + manifest_data["start_url"] = "/mobile/" + + response = jsonify(manifest_data) + response.mimetype = "application/manifest+json" + return _no_store_response(response) + @app.route("/manifest.json", methods=["GET"]) @app.route("/assets/manifest.json", methods=["GET"]) def manifest():