mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 02:46:16 -08:00
* docs(performance): plan Xtream benchmark * feat(xtream-mock-server): add deterministic 100k fixture * style(xtream-mock-server): apply repository formatting * fix(xtream-mock-server): harden performance fixture data * feat(xtream-mock-server): add performance control plane * docs(performance): correct Xtream capture plan * fix(xtream-mock-server): harden performance controls * fix(xtream-mock-server): harden control lifecycle * feat(performance): add Xtream preload markers * feat(performance): trace Xtream main phases * feat(performance): mark Xtream store publications * feat(performance): trace Xtream database phases * feat(performance): trace Xtream delete cancellation * feat(performance): capture Xtream phase attribution * feat(performance): mark Sources Xtream refresh * test(performance): define Xtream benchmark evidence contracts * test(performance): add Xtream benchmark runner * test(performance): surface failure evidence writes * test(performance): align database read clock * test(performance): preserve capture failure contracts
100 lines
3.2 KiB
TypeScript
100 lines
3.2 KiB
TypeScript
import { createHash, randomUUID } from 'node:crypto';
|
|
import { lstat, realpath } from 'node:fs/promises';
|
|
|
|
import type { ElectronApplication } from '@playwright/test';
|
|
|
|
import type { XtreamIterationProcessEvidence } from './xtream-iteration-assembler';
|
|
|
|
export interface XtreamLaunchIdentity {
|
|
readonly electronPid: number;
|
|
readonly launchId: string;
|
|
}
|
|
|
|
export interface XtreamIterationProcessEvidenceOptions extends XtreamLaunchIdentity {
|
|
readonly diagnosticDirectorySha256: string | null;
|
|
readonly iterationDirectory: string;
|
|
}
|
|
|
|
export async function captureXtreamLaunchIdentity(
|
|
electronApp: ElectronApplication,
|
|
launcherPid: number | undefined,
|
|
seenElectronPids: Set<number>,
|
|
createUuid: () => string = randomUUID
|
|
): Promise<XtreamLaunchIdentity> {
|
|
try {
|
|
const evaluatedPid = await electronApp.evaluate(
|
|
async () => process.pid
|
|
);
|
|
if (
|
|
!Number.isSafeInteger(launcherPid) ||
|
|
Number(launcherPid) <= 0 ||
|
|
evaluatedPid !== launcherPid ||
|
|
seenElectronPids.has(Number(launcherPid))
|
|
) {
|
|
invalidProcess();
|
|
}
|
|
const launchId = `launch-${createUuid()}`;
|
|
if (!/^launch-[a-f0-9-]{36}$/u.test(launchId)) invalidProcess();
|
|
seenElectronPids.add(Number(launcherPid));
|
|
return Object.freeze({
|
|
electronPid: Number(launcherPid),
|
|
launchId,
|
|
});
|
|
} catch (error) {
|
|
if (
|
|
error instanceof Error &&
|
|
error.message === 'xtream-electron-process-identity-invalid'
|
|
) {
|
|
throw error;
|
|
}
|
|
invalidProcess();
|
|
}
|
|
}
|
|
|
|
export async function createXtreamIterationProcessEvidence(
|
|
options: XtreamIterationProcessEvidenceOptions
|
|
): Promise<XtreamIterationProcessEvidence> {
|
|
try {
|
|
if (
|
|
!Number.isSafeInteger(options.electronPid) ||
|
|
options.electronPid <= 0 ||
|
|
!/^launch-[a-f0-9-]{36}$/u.test(options.launchId)
|
|
) {
|
|
invalidProcess();
|
|
}
|
|
const stats = await lstat(options.iterationDirectory);
|
|
if (!stats.isDirectory() || stats.isSymbolicLink()) invalidProcess();
|
|
const canonicalDirectory = await realpath(options.iterationDirectory);
|
|
const pathSha256 = sha256(canonicalDirectory);
|
|
const profileDirectorySha256 =
|
|
options.diagnosticDirectorySha256 === null
|
|
? pathSha256
|
|
: options.diagnosticDirectorySha256;
|
|
if (!/^[a-f0-9]{64}$/u.test(profileDirectorySha256)) {
|
|
invalidProcess();
|
|
}
|
|
return Object.freeze({
|
|
electronPid: options.electronPid,
|
|
freshProcessVerified: true,
|
|
launchId: options.launchId,
|
|
profileDirectorySha256,
|
|
});
|
|
} catch (error) {
|
|
if (
|
|
error instanceof Error &&
|
|
error.message === 'xtream-electron-process-identity-invalid'
|
|
) {
|
|
throw error;
|
|
}
|
|
invalidProcess();
|
|
}
|
|
}
|
|
|
|
function sha256(value: string): string {
|
|
return createHash('sha256').update(value).digest('hex');
|
|
}
|
|
|
|
function invalidProcess(): never {
|
|
throw new Error('xtream-electron-process-identity-invalid');
|
|
}
|