From 40286a8542292cf6ee085f93d42a3393ca8f4c22 Mon Sep 17 00:00:00 2001 From: Stian Date: Fri, 14 Aug 2026 12:05:18 +0200 Subject: [PATCH] =?UTF-8?q?test(vault):=20verkt=C3=B8y=20for=20=C3=A5=20ve?= =?UTF-8?q?rifisere=20en=20kj=C3=B8rende=20vault=20over=20ekte=20HTTP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhets- og e2e-testene kjører mot Hono-fetch i prosess. Dette skriptet går mot en faktisk lyttende tjeneste — container eller deployet instans — og er det som fanget at Dockerfilen pekte på src/standalone.ts i en publisert pakke som bare shipper dist/. SCAFFOLDD_SOCKET=... RELAY=https://vault.zyon.no bun live-e2e.ts Co-Authored-By: Claude Opus 5 (1M context) --- packages/shade-vault/live-e2e.ts | 74 ++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 packages/shade-vault/live-e2e.ts diff --git a/packages/shade-vault/live-e2e.ts b/packages/shade-vault/live-e2e.ts new file mode 100644 index 0000000..f5c8946 --- /dev/null +++ b/packages/shade-vault/live-e2e.ts @@ -0,0 +1,74 @@ +/** + * Full backup mot en KJØRENDE vault — ikke Hono-fetch, men ekte HTTP. + * + * Kjøres manuelt mot en container eller en deployet tjeneste: + * SCAFFOLDD_SOCKET=... RELAY=https://vault.zyon.no bun live-e2e.ts + */ +import { connect } from 'node:net'; +import { readFile } from 'node:fs/promises'; +import { SubtleCryptoProvider } from '@shade/crypto-web'; +import { HttpVaultTransport, VaultClient, deriveVaultKeys } from './src/index.js'; + +const SOCKET = process.env.SCAFFOLDD_SOCKET!; +const RELAY = process.env.RELAY!; + +function ask(req: object): Promise { + return new Promise((res, rej) => { + const s = connect(SOCKET); + let buf = ''; + s.on('connect', () => s.write(`${JSON.stringify(req)}\n`)); + s.on('data', (c) => { + buf += c.toString(); + const nl = buf.indexOf('\n'); + if (nl === -1) return; + s.destroy(); + const r = JSON.parse(buf.slice(0, nl)); + r.ok ? res(r.result) : rej(new Error(r.error)); + }); + s.on('error', rej); + }); +} + +const set = await ask({ op: 'backupSet' }); +const files: { path: string; bytes: Uint8Array }[] = []; +for (const f of set.files) { + try { + files.push({ path: f.path, bytes: new Uint8Array(await readFile(f.source)) }); + } catch { + /* uleselig fil hoppes over, som i broen */ + } +} + +const crypto = new SubtleCryptoProvider(); +const keys = await deriveVaultKeys(new Uint8Array(32).fill(77), 'scaffold-live'); +const client = new VaultClient(crypto, keys, new HttpVaultTransport(RELAY)); + +console.log(`push: ${files.length} filer …`); +let t = Date.now(); +const r1 = await client.push(files, Date.now(), 'live e2e'); +console.log( + ` versjon ${r1.seq}: ${r1.uploaded} opplastet, ` + + `${(r1.bytesUploaded / 1024 / 1024).toFixed(1)} MB, ${((Date.now() - t) / 1000).toFixed(1)}s`, +); + +const edited = files.map((f, i) => + i === 0 ? { path: f.path, bytes: new TextEncoder().encode('endret') } : f, +); +t = Date.now(); +const r2 = await client.push(edited, Date.now(), 'én endring'); +console.log( + ` versjon ${r2.seq}: ${r2.uploaded} opplastet, ${r2.reused} gjenbrukt, ` + + `${(r2.bytesUploaded / 1024).toFixed(0)} KB, ${((Date.now() - t) / 1000).toFixed(1)}s`, +); + +const back = await client.pull(1); +let identical = 0; +let differ = 0; +for (const f of files) { + const got = back.files.get(f.path); + if (got && Buffer.from(got).equals(Buffer.from(f.bytes))) identical++; + else differ++; +} +console.log(`pull versjon 1: ${identical} bit-identiske, ${differ} avvik`); +const log = await client.history(); +console.log(`historikk: ${log.entries.map((e) => e.seq).join(', ')} (head ${log.head})`);