Skip to content
92 changes: 92 additions & 0 deletions .github/scripts/__tests__/helpers/keepalive-presence-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
'use strict';

const assert = require('node:assert/strict');
const crypto = require('node:crypto');

// Keep immutable snapshots: a cache publication changes the branch commit, while
// only an index writer changes the attempt subtree. No process-local helper state.
function presenceServer({ count = 1001, missing = null } = {}) {
const sha = (value) => value.toString(16).padStart(40, '0');
const inventories = new Map();
const commits = new Map();
const trees = new Map();
const blobs = new Map();
const calls = [];
let hook = () => {};
let version = 0;
let indexVersion = 0;
const entries = [];
function addIndex(prNumber, runId) {
const ownerAttempt = `owner/repo:${runId}:1`;
const index = { version: 1, repository: 'owner/repo', owner_attempt: ownerAttempt,
pr_number: prNumber, generation: 'a'.repeat(64),
receipt: { id: 'b'.repeat(64), claim_digest: 'c'.repeat(64), owner_attempt: ownerAttempt,
head_sha: 'd'.repeat(40), provider: 'codex', consumed_at: '2026-10-01T00:00:00.000Z' } };
const blobSha = sha(500000 + runId);
blobs.set(blobSha, { sha: blobSha, encoding: 'base64',
content: Buffer.from(JSON.stringify(index)).toString('base64') });
entries.push({ path: crypto.createHash('sha256').update(ownerAttempt).digest('hex') + '.json',
type: 'blob', sha: blobSha });
indexVersion += 1;
}
for (let i = 1; i <= count; i += 1) addIndex(9000, i);
function publish() {
version += 1;
const indexTree = sha(400000 + indexVersion);
trees.set(indexTree, { truncated: false, tree: entries.map((entry) => ({ ...entry })) });
const githubTree = sha(300000 + version);
trees.set(githubTree, { truncated: false, tree: missing === 'attempts' ? [] :
[{ path: 'keepalive-authority-attempts', type: 'tree', sha: indexTree }] });
const rootTree = sha(200000 + version);
trees.set(rootTree, { truncated: false, tree: missing === 'github' ? [] :
[{ path: '.github', type: 'tree', sha: githubTree }] });
commits.set(sha(100000 + version), { tree: { sha: rootTree }, inventories: new Map(inventories) });
}
publish();
const request = async (method, path, body) => {
calls.push({ method, path });
let response;
if (path.includes('/contents/.github/keepalive-authority-presence/')) {
const key = path.split('keepalive-authority-presence/')[1].split('?')[0];
if (method === 'PUT') {
assert.equal(body.sha, undefined, 'inventory must be create-only');
if (inventories.has(key)) throw Object.assign(new Error('existing'), { status: 422 });
inventories.set(key, body.content);
publish();
response = {};
} else {
assert.equal(method, 'GET');
const ref = path.split('?ref=')[1];
const snapshot = ref === 'keepalive-authority-state' ? inventories : commits.get(ref)?.inventories;
if (!snapshot?.has(key)) throw Object.assign(new Error('missing'), { status: 404 });
response = { sha: sha(600000), encoding: 'base64', content: snapshot.get(key) };
}
} else {
assert.equal(method, 'GET');
const key = path.split('/').pop();
if (path.includes('/git/ref/')) response = { object: { type: 'commit', sha: sha(100000 + version) } };
else if (path.includes('/git/commits/')) response = { tree: commits.get(key)?.tree };
else if (path.includes('/git/trees/')) response = trees.get(key);
else if (path.includes('/git/blobs/')) response = blobs.get(key);
assert.ok(response, `Unexpected request ${method} ${path}`);
}
await hook({ method, path, body });
return response;
};
return {
request,
calls,
setHook(value) { hook = value; },
addAttempt(prNumber = 44) {
missing = null;
addIndex(prNumber, 9999);
publish();
},
stats() {
return { blobs: calls.filter((call) => call.path.includes('/git/blobs/')).length,
writes: calls.filter((call) => call.method === 'PUT').length, calls: calls.length };
},
};
}

module.exports = { presenceServer };
156 changes: 156 additions & 0 deletions .github/scripts/__tests__/keepalive-attempt-presence.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
'use strict';

const test = require('node:test');
const assert = require('node:assert/strict');
const crypto = require('node:crypto');

function fixture({ count = 1, target = 42, truncate = false, mutate = () => {},
missingDirectory = false, unreadable = false, wrongBlob = false, badBase64 = false,
malformedTree = false, missingBranch = false, putStatus = 0, corruptPresence = false } = {}) {
const calls = [];
const hashes = ['1', '2', '3', '4'].map((x) => x.repeat(40));
const blobs = new Map();
const inventories = new Map();
const entries = Array.from({ length: count }, (_, i) => {
const owner = `owner/repo:${i + 1}:1`;
const name = crypto.createHash('sha256').update(owner).digest('hex') + '.json';
const sha = (i + 10).toString(16).padStart(40, '0');
const index = { version: 1, repository: 'owner/repo', owner_attempt: owner,
pr_number: i === count - 1 ? target : 43, generation: 'a'.repeat(64),
receipt: { id: 'b'.repeat(64), claim_digest: 'c'.repeat(64), owner_attempt: owner,
head_sha: 'd'.repeat(40), provider: 'codex', consumed_at: '2026-10-01T00:00:00.000Z' } };
mutate(index);
blobs.set(sha, { sha: wrongBlob ? 'f'.repeat(40) : sha, encoding: 'base64',
content: Buffer.from(JSON.stringify(index)).toString('base64') + (badBase64 ? '!' : '') });
return { path: name, type: 'blob', sha };
});
const request = async (method, path, body) => {
calls.push(path);
if (path.includes('/contents/.github/keepalive-authority-presence/')) {
const key = path.split('keepalive-authority-presence/')[1].split('?')[0];
if (method === 'PUT') {
if (putStatus) {
const attempted = JSON.parse(Buffer.from(body.content, 'base64').toString('utf8'));
if (putStatus === 409) inventories.set(key, { ...attempted, positive_prs: [999] });
throw Object.assign(new Error('write failed'), { status: putStatus });
}
inventories.set(key, JSON.parse(Buffer.from(body.content, 'base64').toString('utf8')));
return {};
}
assert.equal(method, 'GET');
if (!inventories.has(key)) throw Object.assign(new Error('missing inventory'), { status: 404 });
return { sha: 'e'.repeat(40), encoding: 'base64',
content: corruptPresence ? 'not base64!' : Buffer.from(JSON.stringify(inventories.get(key))).toString('base64') };
}
assert.equal(method, 'GET');
if (path.endsWith('/git/ref/heads/keepalive-authority-state')) {
if (missingBranch) throw Object.assign(new Error('unavailable branch'), { status: 404 });
return { object: { type: 'commit', sha: hashes[0] } };
}
if (path.endsWith(`/git/commits/${hashes[0]}`)) return { tree: { sha: hashes[1] } };
if (path.endsWith(`/git/trees/${hashes[1]}`)) return { truncated: false,
tree: [{ path: '.github', type: 'tree', sha: hashes[2] }] };
if (path.endsWith(`/git/trees/${hashes[2]}`)) return { truncated: false,
tree: missingDirectory ? [] : [{ path: 'keepalive-authority-attempts', type: 'tree', sha: hashes[3] }] };
if (path.endsWith(`/git/trees/${hashes[3]}`)) return { truncated: truncate,
tree: malformedTree ? [...entries, { path: 'bad', type: 'blob', sha: 'invalid' }] : entries };
const sha = path.split('/git/blobs/')[1];
if (blobs.has(sha)) {
if (unreadable) throw Object.assign(new Error('unavailable blob'), { status: 404 });
return blobs.get(sha);
}
throw new Error(`Unexpected request ${path}`);
};
return { request, calls };
}

for (const surface of ['../keepalive_authority_state.js',
'../../../templates/consumer-repo/.github/scripts/keepalive_authority_state.js']) {
const { hasAttemptIndexesForPr } = require(surface);
test(`${surface}: finds an index beyond the Contents API directory limit`, async () => {
const { request, calls } = fixture({ count: 1001 });
assert.equal(await hasAttemptIndexesForPr(request, 'owner/repo', 42), true);
const blobReads = calls.filter((p) => p.includes('/git/blobs/')).length;
assert.equal(await hasAttemptIndexesForPr(request, 'owner/repo', 42), true);
assert.equal(await hasAttemptIndexesForPr(request, 'owner/repo', 43), true);
assert.equal(await hasAttemptIndexesForPr(request, 'owner/repo', 44), false);
assert.equal(calls.filter((p) => p.includes('/git/blobs/')).length, blobReads);
assert.ok(calls.filter((p) => p.includes('/git/ref/')).length >= 1);
assert.ok(calls.every((p) => !p.includes('/contents/.github/keepalive-authority-attempts/')));
});
test(`${surface}: proves absence only from complete validated evidence`, async () => {
for (const options of [{ target: 43 }, { count: 0 }, { missingDirectory: true }]) {
assert.equal(await hasAttemptIndexesForPr(fixture(options).request, 'owner/repo', 42), false);
}
});
test(`${surface}: rejects incomplete, unreadable, or malformed evidence`, async () => {
for (const options of [
{ truncate: true }, { malformedTree: true }, { unreadable: true }, { wrongBlob: true },
{ badBase64: true }, { missingBranch: true },
{ mutate: (index) => { index.repository = 'other/repo'; } },
{ mutate: (index) => { index.pr_number = '42'; } },
{ mutate: (index) => { index.receipt = null; } },
{ mutate: (index) => { index.owner_attempt = 'owner/repo:999:1'; index.receipt.owner_attempt = index.owner_attempt; } },
]) {
await assert.rejects(hasAttemptIndexesForPr(fixture(options).request, 'owner/repo', 42));
}
});
test(`${surface}: rejects lost, conflicting, or malformed inventory publication`, async () => {
for (const options of [{ putStatus: 500 }, { putStatus: 409 }, { corruptPresence: true }]) {
await assert.rejects(hasAttemptIndexesForPr(fixture(options).request, 'owner/repo', 42));
}
});
}


// A legacy writer never touches presence records. Its new attempt still changes
// the immutable subtree key, so old negative inventory cannot hide the attempt.
for (const surface of ['../keepalive_authority_state.js',
'../../../templates/consumer-repo/.github/scripts/keepalive_authority_state.js']) {
function changingServer(trigger) {
const base = fixture({ target: 43 });
let changed = false;
let armed = false;
const owner = 'owner/repo:9999:1';
const index = { version: 1, repository: 'owner/repo', owner_attempt: owner,
pr_number: 44, generation: 'a'.repeat(64),
receipt: { id: 'b'.repeat(64), claim_digest: 'c'.repeat(64), owner_attempt: owner,
head_sha: 'd'.repeat(40), provider: 'codex', consumed_at: '2026-10-01T00:00:00.000Z' } };
const request = async (method, url, body) => {
if (url.endsWith('/git/trees/' + '5'.repeat(40))) {
return { truncated: false, tree: [{ path: crypto.createHash('sha256').update(owner).digest('hex') + '.json',
type: 'blob', sha: '6'.repeat(40) }] };
}
if (url.endsWith('/git/blobs/' + '6'.repeat(40))) {
return { sha: '6'.repeat(40), encoding: 'base64', content: Buffer.from(JSON.stringify(index)).toString('base64') };
}
const response = await base.request(method, url, body);
if (url.endsWith('/git/trees/' + '3'.repeat(40)) && changed) {
return { truncated: false, tree: [{ path: 'keepalive-authority-attempts', type: 'tree', sha: '5'.repeat(40) }] };
}
if (armed && ((trigger === 'warm' && method === 'GET' && url.includes('/keepalive-authority-presence/')) ||
(trigger === 'backfill' && url.includes('/git/blobs/')) ||
(trigger === 'publication' && method === 'PUT'))) changed = true;
return response;
};
return { request, arm: () => { armed = true; }, advance: () => { changed = true; } };
}
test(`${surface}: an older writer invalidates negative presence by changing the subtree`, async () => {
let { hasAttemptIndexesForPr } = require(surface);
const server = changingServer();
assert.equal(await hasAttemptIndexesForPr(server.request, 'owner/repo', 44), false);
server.advance();
delete require.cache[require.resolve(surface)];
({ hasAttemptIndexesForPr } = require(surface));
assert.equal(await hasAttemptIndexesForPr(server.request, 'owner/repo', 44), true);
});
test(`${surface}: concurrent changes fail closed during warm read, backfill and publication`, async () => {
const { hasAttemptIndexesForPr } = require(surface);
for (const phase of ['warm', 'backfill', 'publication']) {
const server = changingServer(phase);
if (phase === 'warm') assert.equal(await hasAttemptIndexesForPr(server.request, 'owner/repo', 44), false);
server.arm();
await assert.rejects(hasAttemptIndexesForPr(server.request, 'owner/repo', 44), /changed during/);
}
});
}
97 changes: 97 additions & 0 deletions .github/scripts/__tests__/keepalive-authority-state.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,103 @@ const prNumber = 42;
const fingerprint = 'a'.repeat(64);
const headSha = 'd'.repeat(40);
const ownerAttempt = 'owner/repo:100:1';
const { presenceServer } = require('./helpers/keepalive-presence-server.js');

for (const directory of ['..', '../../../templates/consumer-repo/.github/scripts']) {
function freshHelper(filename) {
const authority = require.resolve(`${directory}/keepalive_authority_state.js`);
delete require.cache[authority];
const target = require.resolve(`${directory}/${filename}`);
delete require.cache[target];
return require(target);
}

test(`${directory}: separate default reporters reuse positive and negative inventory`, async () => {
const server = presenceServer();
const replay = async (number) => {
const { replayReporterAuthority } = freshHelper('keepalive_reporter_applicability.js');
// Exercise both production defaults, including the real pinned ledger read.
return replayReporterAuthority({ github: {}, context: { repo: { owner: 'owner', repo: 'repo' } },
prNumber: number, makeRequest: () => server.request });
};
assert.deepEqual(await replay(42), { prNumber: 42, results: [] });
assert.equal(server.stats().blobs, 1001);
assert.equal(server.stats().writes, 1);
for (const number of [43, 44, 9000, 45, 9000]) {
const before = server.stats();
if (number === 9000) await assert.rejects(replay(number), /ledger is missing/);
else assert.deepEqual(await replay(number), { prNumber: number, results: [] });
assert.equal(server.stats().blobs, before.blobs);
assert.equal(server.stats().writes, before.writes);
assert.ok(server.stats().calls - before.calls <= 15, 'warm calls must be bounded');
}
// An older writer only publishes an index; it knows nothing about inventories.
server.addAttempt(44);
await assert.rejects(replay(44), /ledger is missing/);
assert.equal(server.stats().blobs, 2003);
const settled = server.stats();
await assert.rejects(replay(44), /ledger is missing/);
await replay(45);
assert.equal(server.stats().blobs, settled.blobs);
assert.equal(server.stats().writes, settled.writes);
});

test(`${directory}: separate backfill writers converge on the same complete inventory`, async () => {
const server = presenceServer({ count: 20 });
const first = freshHelper('keepalive_authority_state.js');
const second = freshHelper('keepalive_authority_state.js');
assert.deepEqual(await Promise.all([
first.hasAttemptIndexesForPr(server.request, repository, 44),
second.hasAttemptIndexesForPr(server.request, repository, 9000),
]), [false, true]);
assert.equal(server.stats().writes, 2, 'the second create must reconcile its 422');
const before = server.stats();
assert.equal(await freshHelper('keepalive_authority_state.js')
.hasAttemptIndexesForPr(server.request, repository, 44), false);
assert.equal(server.stats().blobs, before.blobs);
});

test(`${directory}: partial backfill and landed lost response deny the current read`, async () => {
for (const phase of ['scan', 'publication']) {
const server = presenceServer({ count: 20 });
let failed = false;
server.setHook(({ method, path }) => {
if (!failed && (phase === 'scan' ? path.includes('/git/blobs/') : method === 'PUT')) {
failed = true;
throw status(503);
}
});
await assert.rejects(freshHelper('keepalive_authority_state.js')
.hasAttemptIndexesForPr(server.request, repository, 44), /HTTP 503/);
assert.equal(server.stats().writes, phase === 'scan' ? 0 : 1);
const before = server.stats();
assert.equal(await freshHelper('keepalive_authority_state.js')
.hasAttemptIndexesForPr(server.request, repository, 44), false);
// A failed scan publishes nothing. A landed lost-response write is usable
// only by a later independent reader that validates the settled snapshot.
assert.equal(server.stats().blobs - before.blobs, phase === 'scan' ? 20 : 0);
}
});

for (const missing of ['github', 'attempts']) {
test(`${directory}: first older-writer index cannot hide behind absent ${missing}`, async () => {
const server = presenceServer({ count: 0, missing });
const { hasAttemptIndexesForPr } = freshHelper('keepalive_authority_state.js');
assert.equal(await hasAttemptIndexesForPr(server.request, repository, 44), false);
let advanced = false;
server.setHook(({ path }) => {
const absentTree = missing === 'github' ? 200001 : 300001;
if (!advanced && path.endsWith(absentTree.toString(16).padStart(40, '0'))) {
advanced = true;
server.addAttempt(44);
}
});
await assert.rejects(hasAttemptIndexesForPr(server.request, repository, 44), /changed during/);
assert.equal(server.stats().writes, 0, 'uncertain absence must not be published');
assert.equal(await hasAttemptIndexesForPr(server.request, repository, 44), true);
});
}
}

function replayTreeRequest({ missingRef = false, truncated = false,
ledgerPresent = false, blobUnavailable = false, malformedBase64 = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,11 @@ test('replay is a no-op when an ordinary PR has no authority ledger', async () =
assert.equal(number, 42);
return null;
},
hasAttemptIndexes: async (_request, repository, number) => {
assert.equal(repository, 'stranske/repo');
assert.equal(number, 42);
return false;
},
makeRequest: () => 'request',
});
assert.deepEqual(result, { prNumber: 42, results: [] });
Expand All @@ -421,6 +426,25 @@ test('replay still fails closed when an authority ledger read fails', async () =
}), /ledger unavailable/);
});

test('replay fails closed when an authority candidate PR has a missing ledger but has attempt indexes', async () => {
await assert.rejects(replayReporterAuthority({
github: { request: async () => { throw new Error('no run lookup expected'); } },
context: { repo: { owner: 'stranske', repo: 'repo' } },
prNumber: 42,
readAuthority: async (_request, repository, number) => {
assert.equal(repository, 'stranske/repo');
assert.equal(number, 42);
return null;
},
hasAttemptIndexes: async (_request, repository, number) => {
assert.equal(repository, 'stranske/repo');
assert.equal(number, 42);
return true; // PR has attempt indexes, so it's an authority candidate
},
makeRequest: () => 'request',
}), /Authority ledger is missing for a PR with attempt indexes/);
});

test('replay rejects a present receipt with an invalid owner attempt', async () => {
await assert.rejects(replayReporterAuthority({
github: {},
Expand Down
Loading
Loading