48 lines
2.1 KiB
JavaScript
48 lines
2.1 KiB
JavaScript
const median = (values) => {
|
|
if (values.length === 0) throw new Error('At least one value is required.');
|
|
const sorted = [...values].sort((left, right) => left - right);
|
|
return sorted[Math.floor(sorted.length / 2)];
|
|
};
|
|
|
|
export const aggregateFiveDriveTraces = (runs) => {
|
|
if (!Array.isArray(runs) || runs.length !== 5) throw new Error('Exactly five drive-trace.v1 runs are required.');
|
|
const profile = runs[0]?.profile;
|
|
if (typeof profile !== 'string' || runs.some((run) => run?.schema !== 'drive-trace.v1' || run.profile !== profile)) {
|
|
throw new Error('All runs must use one drive-trace.v1 profile.');
|
|
}
|
|
const identities = runs.map((run) => run.referenceRun);
|
|
const indexes = identities.map((identity) => identity?.runIndex).sort((left, right) => left - right);
|
|
if (JSON.stringify(indexes) !== JSON.stringify([1, 2, 3, 4, 5])) {
|
|
throw new Error('Reference evidence must contain unique run indexes 1 through 5.');
|
|
}
|
|
const runIds = new Set(identities.map((identity) => identity?.runId));
|
|
const digests = new Set(identities.map((identity) => identity?.attestationDigest));
|
|
if (runIds.size !== 5 || digests.size !== 5 || identities.some((identity) => !/^[a-f0-9]{64}$/u.test(identity?.attestationDigest ?? ''))) {
|
|
throw new Error('Reference evidence must contain five unique authenticated identities.');
|
|
}
|
|
const lcp = runs.map((run) => run.metrics.lcp);
|
|
const tbt = runs.map((run) => run.metrics.tbt);
|
|
const everyPerRunBudgetPass = runs.every((run) => Object.values(run.budgetResults).every(Boolean));
|
|
const referenceEvidence = runs.every((run) => run.gatingReferenceResult === true && run.validReferenceCadence === true);
|
|
const summary = {
|
|
lcpWorst: Math.max(...lcp),
|
|
lcpMedian: median(lcp),
|
|
tbtWorst: Math.max(...tbt),
|
|
tbtMedian: median(tbt),
|
|
everyPerRunBudgetPass,
|
|
referenceEvidence,
|
|
};
|
|
return {
|
|
schema: 'drive-trace-aggregation/v1',
|
|
profile,
|
|
runCount: 5,
|
|
summary,
|
|
passes: referenceEvidence
|
|
&& everyPerRunBudgetPass
|
|
&& summary.lcpWorst <= 3_000
|
|
&& summary.lcpMedian <= 2_500
|
|
&& summary.tbtWorst <= 300
|
|
&& summary.tbtMedian <= 200,
|
|
};
|
|
};
|