Working versioned in-app OTAs
diff --git a/src/deployments/expo.ts b/src/deployments/expo.ts
index 0f83d0f..1a572db 100644
--- a/src/deployments/expo.ts
+++ b/src/deployments/expo.ts
@@ -43,18 +43,19 @@
         perspective: "published"
     });
 
-    const manifest = await client.fetch<string | null>(`*[_type == "release" && channel <= $channel && count(artifacts[_type == "expo" && platform == $platform && runtime == $runtime]) == 1] {
+    const manifestID = await client.fetch<string | null>(`*[_type == "release" && product->identity.current == $product && channel <= $channel && count(artifacts[_type == "expo" && platform == $platform && runtime == $runtime]) == 1] {
         "manifest": select(artifacts[_type == "expo" && platform == $platform && runtime == $runtime])[0].manifest,
         version
     } | order(version desc)[0].manifest`, {
+        product,
         platform,
         runtime,
         channel: EXPO_CHANNEL_NAMES[channel as keyof typeof EXPO_CHANNEL_NAMES]
     });
 
-    if (!manifest) return env.HTTP_STATUS_PAGES.fetch("https://http-status-pages.jottocraft.com/?status=404");
+    if (!manifestID) return env.HTTP_STATUS_PAGES.fetch("https://http-status-pages.jottocraft.com/?status=404");
 
-    return serveExpoManifest(request, env, ctx, product, manifest, channel);
+    return serveExpoManifest(request, env, ctx, product, manifestID, channel);
 }
 
 async function serveExpoAsset(request: Request, env: Env, ctx: AeroCtx, product: string, filename: string) {
@@ -73,6 +74,11 @@
     buildManifest.launchAsset.url = `https://aero.jottocraft.com/${product}/expo/assets/${buildManifest.launchAsset.key}.js`;
     buildManifest.assets.forEach((asset: any) => asset.url = `https://aero.jottocraft.com/${product}/expo/assets/${asset.key}${asset.fileExtension}`);
 
+    // Preserve native build and channel headers
+    if (!buildManifest.extra.expoClient.updates.requestHeaders) buildManifest.extra.expoClient.updates.requestHeaders = {};
+    if (request.headers.get("Expo-Channel-Name")) buildManifest.extra.expoClient.updates.requestHeaders["Expo-Channel-Name"] = request.headers.get("Expo-Channel-Name");
+    if (request.headers.get("jottocraft-Native-App-Version")) buildManifest.extra.expoClient.updates.requestHeaders["jottocraft-Native-App-Version"] = request.headers.get("jottocraft-Native-App-Version");
+
     const boundary = "jottocraft-Aero-Boundary-" + crypto.randomUUID();
 
     let multipartBody = [];
diff --git a/src/util/r2.ts b/src/util/r2.ts
index a7ed19e..9ddc120 100644
--- a/src/util/r2.ts
+++ b/src/util/r2.ts
@@ -14,7 +14,7 @@
         object.writeHttpMetadata(headers);
         headers.set("Etag", object.httpEtag);
         headers.set("Content-Type", contentType ?? "application/octet-stream");
-        headers.set("Cache-Control", (cacheControl ? cacheControl + ", " : "") + "no-transform");
+        if (cacheControl) headers.set("Cache-Control", cacheControl);
         headers.set("Accept-Ranges", "bytes");
         headers.set("Content-Length", String(object.size));
 
@@ -37,7 +37,7 @@
     object.writeHttpMetadata(headers);
     headers.set("ETag", object.httpEtag);
     headers.set("Content-Type", contentType ?? "application/octet-stream");
-    headers.set("Cache-Control", (cacheControl ? cacheControl + ", " : "") + "no-transform");
+    if (cacheControl) headers.set("Cache-Control", cacheControl);
     headers.set("Accept-Ranges", "bytes");
 
     if (hasRequestedRange && object.range) {