@limrun/api 0.39.8 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,405 @@
1
+ import crypto from 'crypto';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { Readable } from 'stream';
5
+ import { nodeProxyTransport } from "./proxy-transport.mjs";
6
+ const SIGNATURE_VERSION = 1;
7
+ const STRONG_HASH_HEX_LENGTH = 32;
8
+ const SCAN_CHUNK_SIZE = 1024 * 1024;
9
+ const MAX_ALIGNED_MISS_BYTES = 32 * 1024 * 1024;
10
+ const SHA256_PATTERN = /^[0-9a-f]{64}$/i;
11
+ const STRONG_HASH_PATTERN = /^[0-9a-f]{32}$/i;
12
+ function strongHash(buffer) {
13
+ return crypto.createHash('sha256').update(buffer).digest('hex').slice(0, STRONG_HASH_HEX_LENGTH);
14
+ }
15
+ function blockSpan(signature, index) {
16
+ const offset = index * signature.blockSize;
17
+ return {
18
+ offset,
19
+ length: Math.min(signature.blockSize, signature.fileSize - offset),
20
+ };
21
+ }
22
+ async function sha256FileHex(filePath) {
23
+ return await new Promise((resolve, reject) => {
24
+ const hash = crypto.createHash('sha256');
25
+ const stream = fs.createReadStream(filePath);
26
+ stream.on('data', (chunk) => hash.update(chunk));
27
+ stream.on('error', reject);
28
+ stream.on('end', () => resolve(hash.digest('hex')));
29
+ });
30
+ }
31
+ export function weakRollingChecksum(buffer) {
32
+ let a = 0;
33
+ let b = 0;
34
+ for (let i = 0; i < buffer.byteLength; i++) {
35
+ const value = buffer[i];
36
+ a = (a + value) & 0xffff;
37
+ b = (b + (buffer.byteLength - i) * value) & 0xffff;
38
+ }
39
+ return b * 0x10000 + a;
40
+ }
41
+ function validateSignature(value, expectedSha256) {
42
+ if (!value || typeof value !== 'object') {
43
+ throw new Error('Invalid seed signature: expected an object');
44
+ }
45
+ const candidate = value;
46
+ if (candidate.version !== SIGNATURE_VERSION) {
47
+ throw new Error(`Unsupported seed signature version: ${String(candidate.version)}`);
48
+ }
49
+ if (!Number.isSafeInteger(candidate.blockSize) || candidate.blockSize <= 0) {
50
+ throw new Error('Invalid seed signature blockSize');
51
+ }
52
+ if (!Number.isSafeInteger(candidate.fileSize) || candidate.fileSize < 0) {
53
+ throw new Error('Invalid seed signature fileSize');
54
+ }
55
+ if (typeof candidate.sha256 !== 'string' ||
56
+ !SHA256_PATTERN.test(candidate.sha256) ||
57
+ candidate.sha256.toLowerCase() !== expectedSha256.toLowerCase()) {
58
+ throw new Error('Seed signature sha256 does not match the requested seed');
59
+ }
60
+ if (!Array.isArray(candidate.blocks)) {
61
+ throw new Error('Invalid seed signature blocks');
62
+ }
63
+ const expectedBlocks = Math.ceil(candidate.fileSize / candidate.blockSize);
64
+ if (candidate.blocks.length !== expectedBlocks) {
65
+ throw new Error(`Invalid seed signature block count: got ${candidate.blocks.length}, expected ${expectedBlocks}`);
66
+ }
67
+ const blocks = candidate.blocks.map((block, index) => {
68
+ if (!block ||
69
+ !Number.isInteger(block.w) ||
70
+ block.w < 0 ||
71
+ block.w > 0xffffffff ||
72
+ typeof block.s !== 'string' ||
73
+ !STRONG_HASH_PATTERN.test(block.s)) {
74
+ throw new Error(`Invalid seed signature block at index ${index}`);
75
+ }
76
+ return { w: block.w, s: block.s.toLowerCase() };
77
+ });
78
+ return {
79
+ version: candidate.version,
80
+ blockSize: candidate.blockSize,
81
+ fileSize: candidate.fileSize,
82
+ sha256: candidate.sha256.toLowerCase(),
83
+ blocks,
84
+ };
85
+ }
86
+ export async function fetchSeedSignature(signatureUrl, token, expectedSha256) {
87
+ const response = await nodeProxyTransport.fetch(signatureUrl, {
88
+ method: 'GET',
89
+ headers: { Authorization: `Bearer ${token}` },
90
+ });
91
+ if (!response.ok) {
92
+ const body = await response.text();
93
+ throw new Error(`Seed signature download failed: ${response.status} ${body}`);
94
+ }
95
+ return validateSignature(await response.json(), expectedSha256);
96
+ }
97
+ async function readExactly(handle, buffer, length, position) {
98
+ let offset = 0;
99
+ while (offset < length) {
100
+ const { bytesRead } = await handle.read(buffer, offset, length - offset, position + offset);
101
+ if (bytesRead <= 0) {
102
+ throw new Error(`Unexpected EOF at offset ${position + offset}`);
103
+ }
104
+ offset += bytesRead;
105
+ }
106
+ }
107
+ async function scanSourceForFullBlocks(source, candidatesByWeak, signature, matches, unmatched) {
108
+ const blockLength = signature.blockSize;
109
+ const handle = await fs.promises.open(source.path, 'r');
110
+ try {
111
+ if (source.size < blockLength || unmatched.size === 0) {
112
+ return;
113
+ }
114
+ const ring = Buffer.allocUnsafe(blockLength);
115
+ await readExactly(handle, ring, blockLength, 0);
116
+ let a = 0;
117
+ let b = 0;
118
+ for (let i = 0; i < blockLength; i++) {
119
+ const value = ring[i];
120
+ a = (a + value) & 0xffff;
121
+ b = (b + (blockLength - i) * value) & 0xffff;
122
+ }
123
+ let ringPosition = 0;
124
+ let sourceOffset = 0;
125
+ let candidateBuffer;
126
+ const confirmCandidate = async (candidateIndexes) => {
127
+ candidateBuffer ?? (candidateBuffer = Buffer.allocUnsafe(blockLength));
128
+ await readExactly(handle, candidateBuffer, blockLength, sourceOffset);
129
+ const strong = strongHash(candidateBuffer);
130
+ for (const index of candidateIndexes) {
131
+ if (unmatched.has(index) && signature.blocks[index].s === strong) {
132
+ matches.set(index, { sourcePath: source.path, sourceOffset });
133
+ unmatched.delete(index);
134
+ }
135
+ }
136
+ };
137
+ let candidateIndexes = candidatesByWeak.get(b * 0x10000 + a);
138
+ if (candidateIndexes?.some((index) => unmatched.has(index))) {
139
+ await confirmCandidate(candidateIndexes);
140
+ }
141
+ const incoming = Buffer.allocUnsafe(SCAN_CHUNK_SIZE);
142
+ let readPosition = blockLength;
143
+ while (readPosition < source.size && unmatched.size > 0) {
144
+ const requested = Math.min(incoming.byteLength, source.size - readPosition);
145
+ const { bytesRead } = await handle.read(incoming, 0, requested, readPosition);
146
+ if (bytesRead <= 0) {
147
+ break;
148
+ }
149
+ for (let i = 0; i < bytesRead && unmatched.size > 0; i++) {
150
+ const outgoingValue = ring[ringPosition];
151
+ const incomingValue = incoming[i];
152
+ ring[ringPosition] = incomingValue;
153
+ ringPosition++;
154
+ if (ringPosition === blockLength) {
155
+ ringPosition = 0;
156
+ }
157
+ a = (a - outgoingValue + incomingValue) & 0xffff;
158
+ b = (b - ((blockLength * outgoingValue) & 0xffff) + a) & 0xffff;
159
+ sourceOffset++;
160
+ candidateIndexes = candidatesByWeak.get(b * 0x10000 + a);
161
+ if (candidateIndexes?.some((index) => unmatched.has(index))) {
162
+ await confirmCandidate(candidateIndexes);
163
+ }
164
+ }
165
+ readPosition += bytesRead;
166
+ }
167
+ }
168
+ finally {
169
+ await handle.close();
170
+ }
171
+ }
172
+ async function existingSourceFiles(sourcePaths) {
173
+ const sources = [];
174
+ for (const sourcePath of sourcePaths) {
175
+ const stat = await fs.promises.stat(sourcePath).catch(() => undefined);
176
+ if (stat?.isFile()) {
177
+ sources.push({ path: sourcePath, size: stat.size });
178
+ }
179
+ }
180
+ return sources;
181
+ }
182
+ async function matchAlignedBlocks(sources, signature, matches) {
183
+ for (const source of sources) {
184
+ const handle = await fs.promises.open(source.path, 'r');
185
+ const block = Buffer.allocUnsafe(signature.blockSize);
186
+ try {
187
+ for (let index = 0; index < signature.blocks.length; index++) {
188
+ if (matches.has(index)) {
189
+ continue;
190
+ }
191
+ const span = blockSpan(signature, index);
192
+ if (span.offset + span.length > source.size) {
193
+ continue;
194
+ }
195
+ await readExactly(handle, block, span.length, span.offset);
196
+ if (strongHash(block.subarray(0, span.length)) === signature.blocks[index].s) {
197
+ matches.set(index, { sourcePath: source.path, sourceOffset: span.offset });
198
+ }
199
+ }
200
+ }
201
+ finally {
202
+ await handle.close();
203
+ }
204
+ }
205
+ }
206
+ async function matchTrailingPartialBlock(sources, signature, matches) {
207
+ if (signature.fileSize === 0 || signature.fileSize % signature.blockSize === 0) {
208
+ return;
209
+ }
210
+ const index = signature.blocks.length - 1;
211
+ if (matches.has(index)) {
212
+ return;
213
+ }
214
+ const span = blockSpan(signature, index);
215
+ const expectedStrongHash = signature.blocks[index].s;
216
+ const block = Buffer.allocUnsafe(span.length);
217
+ for (const source of sources) {
218
+ if (source.size < span.length) {
219
+ continue;
220
+ }
221
+ const sourceOffset = source.size - span.length;
222
+ if (sourceOffset === span.offset) {
223
+ continue; // The aligned pass already checked this offset.
224
+ }
225
+ const handle = await fs.promises.open(source.path, 'r');
226
+ try {
227
+ await readExactly(handle, block, span.length, sourceOffset);
228
+ if (strongHash(block) === expectedStrongHash) {
229
+ matches.set(index, { sourcePath: source.path, sourceOffset });
230
+ return;
231
+ }
232
+ }
233
+ finally {
234
+ await handle.close();
235
+ }
236
+ }
237
+ }
238
+ function shouldSkipRollingScan(signature, matches) {
239
+ let missingBytes = 0;
240
+ for (let index = 0; index < signature.blocks.length; index++) {
241
+ if (!matches.has(index)) {
242
+ missingBytes += blockSpan(signature, index).length;
243
+ }
244
+ }
245
+ const matchRatio = signature.blocks.length === 0 ? 1 : matches.size / signature.blocks.length;
246
+ return matchRatio >= 0.8 && missingBytes <= MAX_ALIGNED_MISS_BYTES;
247
+ }
248
+ async function matchShiftedFullBlocks(sources, signature, matches) {
249
+ const fullBlockCount = Math.floor(signature.fileSize / signature.blockSize);
250
+ const unmatched = new Set();
251
+ const candidatesByWeak = new Map();
252
+ for (let index = 0; index < fullBlockCount; index++) {
253
+ if (matches.has(index)) {
254
+ continue;
255
+ }
256
+ unmatched.add(index);
257
+ const weak = signature.blocks[index].w;
258
+ const candidates = candidatesByWeak.get(weak) ?? [];
259
+ candidates.push(index);
260
+ candidatesByWeak.set(weak, candidates);
261
+ }
262
+ for (const source of sources) {
263
+ if (unmatched.size === 0) {
264
+ return;
265
+ }
266
+ await scanSourceForFullBlocks(source, candidatesByWeak, signature, matches, unmatched);
267
+ }
268
+ }
269
+ export async function findSeedBlockMatches(sourcePaths, signature) {
270
+ const sources = await existingSourceFiles(sourcePaths);
271
+ const matches = new Map();
272
+ await matchAlignedBlocks(sources, signature, matches);
273
+ await matchTrailingPartialBlock(sources, signature, matches);
274
+ if (!shouldSkipRollingScan(signature, matches)) {
275
+ await matchShiftedFullBlocks(sources, signature, matches);
276
+ }
277
+ return matches;
278
+ }
279
+ export function missingSeedRanges(signature, matches) {
280
+ const ranges = [];
281
+ let startBlock;
282
+ for (let index = 0; index <= signature.blocks.length; index++) {
283
+ const missing = index < signature.blocks.length && !matches.has(index);
284
+ if (missing && startBlock === undefined) {
285
+ startBlock = index;
286
+ }
287
+ else if (!missing && startBlock !== undefined) {
288
+ const first = blockSpan(signature, startBlock);
289
+ const last = blockSpan(signature, index - 1);
290
+ ranges.push({
291
+ start: first.offset,
292
+ end: last.offset + last.length - 1,
293
+ });
294
+ startBlock = undefined;
295
+ }
296
+ }
297
+ return ranges;
298
+ }
299
+ async function copyMatchedBlocks(output, signature, matches) {
300
+ const sourceHandles = new Map();
301
+ try {
302
+ for (const [index, match] of matches) {
303
+ let source = sourceHandles.get(match.sourcePath);
304
+ if (!source) {
305
+ source = await fs.promises.open(match.sourcePath, 'r');
306
+ sourceHandles.set(match.sourcePath, source);
307
+ }
308
+ const span = blockSpan(signature, index);
309
+ const block = Buffer.allocUnsafe(span.length);
310
+ await readExactly(source, block, span.length, match.sourceOffset);
311
+ await writeExactly(output, block, span.offset);
312
+ }
313
+ }
314
+ finally {
315
+ await Promise.all([...sourceHandles.values()].map((handle) => handle.close()));
316
+ }
317
+ }
318
+ async function writeExactly(handle, buffer, position) {
319
+ let offset = 0;
320
+ while (offset < buffer.byteLength) {
321
+ const { bytesWritten } = await handle.write(buffer, offset, buffer.byteLength - offset, position + offset);
322
+ if (bytesWritten <= 0) {
323
+ throw new Error(`Unable to write reconstructed seed at offset ${position + offset}`);
324
+ }
325
+ offset += bytesWritten;
326
+ }
327
+ }
328
+ async function downloadRange(seedUrl, token, range, fileSize, output, reportBytes) {
329
+ const response = await nodeProxyTransport.fetch(seedUrl, {
330
+ method: 'GET',
331
+ headers: {
332
+ Authorization: `Bearer ${token}`,
333
+ Range: `bytes=${range.start}-${range.end}`,
334
+ },
335
+ });
336
+ if (response.status !== 206 || !response.body) {
337
+ const body = await response.text();
338
+ throw new Error(`Seed range download failed: ${response.status} ${body}`);
339
+ }
340
+ const expectedContentRange = `bytes ${range.start}-${range.end}/${fileSize}`;
341
+ if (response.headers.get('content-range') !== expectedContentRange) {
342
+ throw new Error(`Invalid Content-Range for seed: ${response.headers.get('content-range') ?? '<missing>'}`);
343
+ }
344
+ const expectedLength = range.end - range.start + 1;
345
+ let received = 0;
346
+ const source = Readable.fromWeb(response.body);
347
+ for await (const value of source) {
348
+ const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
349
+ if (received + chunk.byteLength > expectedLength) {
350
+ throw new Error('Seed range response exceeded the requested length');
351
+ }
352
+ await writeExactly(output, chunk, range.start + received);
353
+ received += chunk.byteLength;
354
+ reportBytes(chunk.byteLength);
355
+ }
356
+ if (received !== expectedLength) {
357
+ throw new Error(`Seed range response was truncated: got ${received}, expected ${expectedLength}`);
358
+ }
359
+ }
360
+ export async function reconstructSeedFromLocalFiles(options) {
361
+ const expectedSha256 = options.expectedSha256.toLowerCase();
362
+ const signature = await fetchSeedSignature(options.signatureUrl, options.token, expectedSha256);
363
+ const uniqueSources = [...new Set(options.sourcePaths.map((sourcePath) => path.resolve(sourcePath)))];
364
+ const matches = await findSeedBlockMatches(uniqueSources, signature);
365
+ const ranges = missingSeedRanges(signature, matches);
366
+ const totalDownloadBytes = ranges.reduce((total, range) => total + range.end - range.start + 1, 0);
367
+ let downloadedBytes = 0;
368
+ options.onProgress?.(0, totalDownloadBytes);
369
+ await fs.promises.mkdir(path.dirname(options.outputPath), { recursive: true });
370
+ const temporaryPath = `${options.outputPath}.reconstruct-${process.pid}-${crypto
371
+ .randomBytes(6)
372
+ .toString('hex')}`;
373
+ const output = await fs.promises.open(temporaryPath, 'wx');
374
+ let outputClosed = false;
375
+ let installed = false;
376
+ try {
377
+ await output.truncate(signature.fileSize);
378
+ await copyMatchedBlocks(output, signature, matches);
379
+ for (const range of ranges) {
380
+ await downloadRange(options.seedUrl, options.token, range, signature.fileSize, output, (bytes) => {
381
+ downloadedBytes += bytes;
382
+ options.onProgress?.(downloadedBytes, totalDownloadBytes);
383
+ });
384
+ }
385
+ await output.close();
386
+ outputClosed = true;
387
+ const actualSha256 = await sha256FileHex(temporaryPath);
388
+ if (actualSha256 !== expectedSha256) {
389
+ throw new Error(`Reconstructed seed SHA-256 mismatch: got ${actualSha256}, expected ${expectedSha256}`);
390
+ }
391
+ await fs.promises.rm(options.outputPath, { force: true });
392
+ await fs.promises.rename(temporaryPath, options.outputPath);
393
+ installed = true;
394
+ }
395
+ finally {
396
+ if (!outputClosed) {
397
+ await output.close().catch(() => undefined);
398
+ }
399
+ if (!installed) {
400
+ await fs.promises.rm(temporaryPath, { force: true });
401
+ }
402
+ }
403
+ return { downloadedBytes, totalDownloadBytes, matchedBlocks: matches.size };
404
+ }
405
+ //# sourceMappingURL=seed-reconstruct.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed-reconstruct.mjs","sourceRoot":"","sources":["../src/internal/seed-reconstruct.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@limrun/api",
3
- "version": "0.39.8",
3
+ "version": "0.40.0",
4
4
  "description": "The official TypeScript library for the Limrun API",
5
5
  "author": "Limrun <contact@limrun.com>",
6
6
  "types": "./index.d.ts",
@@ -118,6 +118,12 @@ export declare namespace IosInstanceCreateParams {
118
118
  }
119
119
  interface Spec {
120
120
  clues?: Array<Spec.Clue>;
121
+ /**
122
+ * Keeps this app in the foreground after it is first observed there. This does not
123
+ * launch the app when the simulator starts. Once armed, closing or backgrounding
124
+ * the app causes it to be brought back to the foreground.
125
+ */
126
+ forceBundleId?: string;
121
127
  /**
122
128
  * After how many minutes should the instance be terminated. Example values 1m,
123
129
  * 10m, 3h. Default is "0" which means no hard timeout.
@@ -1 +1 @@
1
- {"version":3,"file":"ios-instances.d.mts","sourceRoot":"","sources":["../src/resources/ios-instances.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ios-instances.d.mts","sourceRoot":"","sources":["../src/resources/ios-instances.ts"],"names":[],"mappings":"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"}
@@ -118,6 +118,12 @@ export declare namespace IosInstanceCreateParams {
118
118
  }
119
119
  interface Spec {
120
120
  clues?: Array<Spec.Clue>;
121
+ /**
122
+ * Keeps this app in the foreground after it is first observed there. This does not
123
+ * launch the app when the simulator starts. Once armed, closing or backgrounding
124
+ * the app causes it to be brought back to the foreground.
125
+ */
126
+ forceBundleId?: string;
121
127
  /**
122
128
  * After how many minutes should the instance be terminated. Example values 1m,
123
129
  * 10m, 3h. Default is "0" which means no hard timeout.
@@ -1 +1 @@
1
- {"version":3,"file":"ios-instances.d.ts","sourceRoot":"","sources":["../src/resources/ios-instances.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ios-instances.d.ts","sourceRoot":"","sources":["../src/resources/ios-instances.ts"],"names":[],"mappings":"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"}
@@ -165,9 +165,9 @@ export type InstanceClient = {
165
165
  launchMode?: 'ForegroundIfRunning' | 'RelaunchIfRunning';
166
166
  basisCacheDir?: string;
167
167
  /**
168
- * Called while the basis seed is downloaded from the instance. Fires once with
169
- * `(0, expectedSizeBytes)` before the download starts (expectedSizeBytes is 0 when
170
- * unknown), then repeatedly as bytes arrive.
168
+ * Called while missing basis-seed ranges are downloaded from the instance. Fires
169
+ * once with `(0, requiredDownloadBytes)` before transfer, then repeatedly as bytes
170
+ * arrive. A full-download fallback restarts progress with the complete seed size.
171
171
  */
172
172
  onBasisDownloadProgress?: (downloadedBytes: number, totalBytes: number) => void;
173
173
  /** Called after every successful sync, including watch-triggered re-syncs. */
@@ -4,13 +4,14 @@ import path from 'path';
4
4
 
5
5
  import { downloadFileToLocalPath } from './download-file';
6
6
  import { nodeProxyTransport } from './proxy-transport';
7
+ import { reconstructSeedFromLocalFiles } from './seed-reconstruct';
7
8
 
8
9
  export type AndroidSyncState = {
9
10
  roots?: Array<{
10
11
  rootName?: string;
11
12
  files?: Array<{ path?: string; sha256?: string; size?: number; mode?: number }>;
12
13
  }>;
13
- seeds?: Array<{ sha256?: string; size?: number; name?: string; mtime?: number }>;
14
+ seeds?: Array<{ sha256?: string; size?: number; mtime?: number }>;
14
15
  };
15
16
 
16
17
  type SyncLog = (level: 'debug' | 'info' | 'warn' | 'error', msg: string) => void;
@@ -85,7 +86,7 @@ export async function bootstrapAndroidBasisCache(
85
86
  }
86
87
  const seeds = [...(state.seeds ?? [])]
87
88
  .filter(
88
- (seed): seed is { sha256: string; size?: number; name?: string; mtime?: number } =>
89
+ (seed): seed is { sha256: string; size?: number; mtime?: number } =>
89
90
  typeof seed.sha256 === 'string' && /^[0-9a-f]{64}$/i.test(seed.sha256),
90
91
  )
91
92
  .sort((a, b) => (b.mtime ?? 0) - (a.mtime ?? 0));
@@ -93,16 +94,16 @@ export async function bootstrapAndroidBasisCache(
93
94
  serverShas.add(seed.sha256.toLowerCase());
94
95
  }
95
96
 
97
+ let staleBasisPath: string | undefined;
96
98
  if (fs.existsSync(basisPath)) {
97
99
  const basisSha = (await sha256FileHex(basisPath)).toLowerCase();
98
100
  if (serverShas.has(basisSha)) {
99
101
  return;
100
102
  }
101
- // A delta against a basis this instance doesn't have only earns a needFull
102
- // round trip and then a full upload (e.g. a warm cache pointed at a fresh
103
- // instance), so drop the stale basis and re-seed below.
103
+ // Keep the stale basis temporarily: even though the instance cannot use it
104
+ // directly, many of its blocks may be reusable while reconstructing a seed.
104
105
  log('debug', `local basis ${basisSha} unknown to instance; re-seeding basis cache`);
105
- await fs.promises.rm(basisPath, { force: true });
106
+ staleBasisPath = basisPath;
106
107
  }
107
108
 
108
109
  const localSha = (await sha256FileHex(apkPath)).toLowerCase();
@@ -116,16 +117,37 @@ export async function bootstrapAndroidBasisCache(
116
117
  }
117
118
  const seed = seeds[0];
118
119
  if (!seed) {
120
+ if (staleBasisPath) {
121
+ await fs.promises.rm(staleBasisPath, { force: true });
122
+ }
119
123
  return;
120
124
  }
121
- // Announce the download before any bytes flow so consumers can react to the
122
- // expected size even during connection setup / time-to-first-byte.
123
- onBasisDownloadProgress?.(0, seed.size ?? 0);
124
- await downloadFileToLocalPath(
125
- buildSyncSeedUrl(apiUrl, seed.sha256),
126
- token,
127
- basisPath,
128
- onBasisDownloadProgress,
129
- );
130
- log('debug', `seeded Android basis cache from instance seed: ${seed.sha256}`);
125
+ const seedUrl = buildSyncSeedUrl(apiUrl, seed.sha256);
126
+ try {
127
+ const result = await reconstructSeedFromLocalFiles({
128
+ signatureUrl: `${seedUrl}.sig`,
129
+ seedUrl,
130
+ token,
131
+ sourcePaths: staleBasisPath ? [apkPath, staleBasisPath] : [apkPath],
132
+ outputPath: basisPath,
133
+ expectedSha256: seed.sha256,
134
+ ...(onBasisDownloadProgress ? { onProgress: onBasisDownloadProgress } : {}),
135
+ });
136
+ log(
137
+ 'debug',
138
+ `reconstructed Android basis seed ${seed.sha256}: matched=${result.matchedBlocks} downloaded=${result.downloadedBytes}`,
139
+ );
140
+ } catch (err) {
141
+ log(
142
+ 'debug',
143
+ `basis seed reconstruction unavailable; downloading full seed: ${
144
+ err instanceof Error ? err.message : String(err)
145
+ }`,
146
+ );
147
+ // A failed reconstruction never replaces basisPath, so it is safe to
148
+ // truncate the stale basis in place for the full-download fallback.
149
+ onBasisDownloadProgress?.(0, seed.size ?? 0);
150
+ await downloadFileToLocalPath(seedUrl, token, basisPath, onBasisDownloadProgress);
151
+ log('debug', `seeded Android basis cache from full instance seed: ${seed.sha256}`);
152
+ }
131
153
  }