installed-update-distribution.ts 4.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. /** Validate local qualification payload bytes and prepare separate binary and fixed-feed operations. */
  2. import { createHash } from 'node:crypto'
  3. import { createReadStream } from 'node:fs'
  4. import { readFile, stat } from 'node:fs/promises'
  5. import { join } from 'node:path'
  6. import { dump, load } from 'js-yaml'
  7. import { readInstalledUpdateRun } from './installed-update-qualification.ts'
  8. /** A local immutable object, with its final test-only destination and digest. */
  9. export interface InstalledUpdateBinary {
  10. readonly path: string
  11. readonly key: string
  12. readonly size: number
  13. readonly sha512: string
  14. }
  15. /** File integrity does not establish signature, application identity, or authority to publish. */
  16. export interface InstalledUpdateDistribution {
  17. readonly version: string
  18. readonly bucket: string
  19. readonly binaries: readonly InstalledUpdateBinary[]
  20. readonly feed: { readonly key: string; readonly url: string; readonly contents: string; readonly sha512: string }
  21. readonly verified: 'file-integrity-only'
  22. readonly publicationAuthorized: false
  23. }
  24. async function binary(path: string, key: string): Promise<InstalledUpdateBinary> {
  25. const file = await stat(path)
  26. if (!file.isFile() || file.size === 0) throw new Error('installed update: missing or empty binary material')
  27. const hash = createHash('sha512')
  28. for await (const chunk of createReadStream(path)) hash.update(chunk)
  29. return { path, key, size: file.size, sha512: hash.digest('base64') }
  30. }
  31. function record(value: unknown): Record<string, unknown> {
  32. if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new Error('installed update: invalid feed metadata')
  33. return value as Record<string, unknown>
  34. }
  35. /**
  36. * Check generated YAML against installer bytes and prepare one independent fixed-feed body per version.
  37. * @param manifest Original qualification run.json; test identity and destinations are revalidated.
  38. * @param version One of the run's two versions, never a version inferred from YAML.
  39. * @returns Read-only binary and feed plans; no credentials, network, signing, or installation are involved.
  40. */
  41. export async function planInstalledUpdateDistribution(manifest: string, version: string): Promise<InstalledUpdateDistribution> {
  42. const run = await readInstalledUpdateRun(manifest)
  43. if (!run.versions.includes(version)) throw new Error('installed update: version is outside the qualification run')
  44. const directory = join(run.root, version, 'installer')
  45. const metadata = record(load(await readFile(join(directory, 'nightly.yml'), 'utf8')))
  46. if (metadata.version !== version || !Array.isArray(metadata.files) || metadata.files.length !== 1) {
  47. throw new Error('installed update: feed must describe exactly the selected version and installer')
  48. }
  49. const info = record(metadata.files[0])
  50. const filename = `deepseek-harness-${version}-win-x64.exe`
  51. if (info.url !== filename || (metadata.path !== undefined && metadata.path !== filename)) {
  52. throw new Error('installed update: feed filename must identify the selected local Windows installer')
  53. }
  54. const installer = await binary(join(directory, filename), `${run.binPrefix}/${filename}`)
  55. if (info.size !== installer.size || info.sha512 !== installer.sha512
  56. || (metadata.sha512 !== undefined && metadata.sha512 !== installer.sha512)) {
  57. throw new Error('installed update: installer size or SHA-512 differs from the generated feed')
  58. }
  59. const blockmap = await binary(join(directory, `${filename}.blockmap`), `${run.binPrefix}/${filename}.blockmap`)
  60. if (metadata.releaseDate !== undefined && (typeof metadata.releaseDate !== 'string'
  61. || !Number.isFinite(Date.parse(metadata.releaseDate)))) throw new Error('installed update: invalid feed release date')
  62. const url = `${run.origin}/${installer.key}`
  63. const contents = dump({ version, files: [{ url, size: installer.size, sha512: installer.sha512 }],
  64. path: url, sha512: installer.sha512, ...(metadata.releaseDate === undefined ? {} : { releaseDate: metadata.releaseDate }) })
  65. return { version, bucket: run.bucket, binaries: [installer, blockmap],
  66. feed: { key: run.feedKey, url: `${run.origin}/${run.feedKey}`, contents,
  67. sha512: createHash('sha512').update(contents).digest('base64') },
  68. verified: 'file-integrity-only', publicationAuthorized: false }
  69. }