Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .buildkite/scripts/product-validation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ bash .buildkite/scripts/checkpoint-evidence.sh
repository_id="${TABELLIO_REPO_ID:-}"
if [[ -z "$repository_id" ]]; then
repository_url="$(git remote get-url origin)"
repository_id="$(node -e 'const u=process.argv[1]; const m=u.match(/^(?:https:\/\/github\.com\/|git@github\.com:)([^/]+\/[^/]+?)(?:\.git)?$/); if(!m)process.exit(1); console.log(m[1]);' "$repository_url")"
repository_id="$(node --input-type=module -e 'import { parseGitHubRepositoryRemote } from "./scripts/lib/github-repository.mjs"; const repository = parseGitHubRepositoryRemote(process.argv[1]); if (!repository) process.exit(1); console.log(repository.fullName);' "$repository_url")"
fi
[[ "$repository_id" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]] || { echo "A valid customer repository ID is required." >&2; exit 1; }

Expand Down
6 changes: 5 additions & 1 deletion scripts/ci-checkpoint-evidence.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ try {
const text = (process.env.TABELLIO_CHECKPOINT_PROOF_1 ?? '') + (process.env.TABELLIO_CHECKPOINT_PROOF_2 ?? '');
if (!text || text.length > 98000) throw new Error('Missing or oversized evidence.');
const envelope = JSON.parse(text);
// Keep the transport range aligned with the validation gate after main advances.
const base = process.env.GITHUB_EVENT_NAME === 'push'
? git('rev-parse', 'HEAD^')
: git('merge-base', 'origin/main', 'HEAD');
if (Object.keys(envelope).sort().join(',') !== 'base,bundle,candidate,nativeTip,repositoryId,schemaVersion,sha256'
|| envelope.schemaVersion !== 'tabellio-private-checkpoint-proof/v1'
|| envelope.repositoryId !== `github.com/${process.env.GITHUB_REPOSITORY}`
|| envelope.candidate !== git('rev-parse', 'HEAD')
|| envelope.base !== git('merge-base', 'origin/main', 'HEAD')
|| envelope.base !== base
|| !/^[0-9a-f]{40}$/.test(envelope.nativeTip)) throw new Error('Evidence scope mismatch.');
const bytes = Buffer.from(envelope.bundle, 'base64');
if (bytes.toString('base64') !== envelope.bundle || createHash('sha256').update(bytes).digest('hex') !== envelope.sha256) throw new Error('Evidence integrity mismatch.');
Expand Down
2 changes: 1 addition & 1 deletion tests/buildkite-high-gates.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ test("GitHub merged-head validation remains during Buildkite migration", async (
const loader = await repositoryFile("scripts/ci-checkpoint-evidence.mjs");
assert.match(loader, /execFileSync\('bash', \['\.buildkite\/scripts\/checkpoint-evidence\.sh'\]/);
assert.match(loader, /envelope\.candidate !== git\('rev-parse', 'HEAD'\)/);
assert.match(loader, /envelope\.base !== git\('merge-base', 'origin\/main', 'HEAD'\)/);
assert.match(loader, /envelope\.base !== base/);
assert.match(loader, /createHash\('sha256'\)\.update\(bytes\)\.digest\('hex'\) !== envelope\.sha256/);
assert.doesNotMatch(workflow, /refs\/tabellio\/validations\//);
assert.doesNotMatch(workflow, /validation-ref\.bundle/);
Expand Down
41 changes: 40 additions & 1 deletion tests/checkpoint-evidence.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,25 @@ test('private runner envelope binds candidate and digest, rejects leaks, and rem
const loader = resolve('scripts/ci-checkpoint-evidence.mjs');
const invoke = (command, value = envelope) => {
const text = JSON.stringify(value); const middle = Math.floor(text.length / 2);
return run(target, process.execPath, [loader, command], { GITHUB_ACTIONS: 'true', GITHUB_WORKSPACE: target, RUNNER_TEMP: runner, GITHUB_REPOSITORY: 'Fixture/Transport', TABELLIO_CHECKPOINT_PROOF_1: text.slice(0, middle), TABELLIO_CHECKPOINT_PROOF_2: text.slice(middle) });
return run(target, process.execPath, [loader, command], { GITHUB_ACTIONS: 'true', GITHUB_EVENT_NAME: 'pull_request', GITHUB_WORKSPACE: target, RUNNER_TEMP: runner, GITHUB_REPOSITORY: 'Fixture/Transport', TABELLIO_CHECKPOINT_PROOF_1: text.slice(0, middle), TABELLIO_CHECKPOINT_PROOF_2: text.slice(middle) });
};
for (const bad of [{ ...envelope, candidate: base }, { ...envelope, sha256: '0'.repeat(64) }, { ...envelope, repositoryId: 'wrong/private-secret-marker' }]) {
const r = invoke('load', bad); assert.equal(r.status, 1); assert.ok(!r.stderr.includes('private-secret-marker'));
}
// A main push advances origin/main to HEAD; the gate still validates HEAD^..HEAD.
git(target, 'update-ref', 'refs/remotes/origin/main', candidate);
const invokePush = value => {
const text = JSON.stringify(value); const middle = Math.floor(text.length / 2);
return run(target, process.execPath, [loader, 'load'], { GITHUB_ACTIONS: 'true', GITHUB_EVENT_NAME: 'push', GITHUB_WORKSPACE: target, RUNNER_TEMP: runner, GITHUB_REPOSITORY: 'Fixture/Transport', TABELLIO_CHECKPOINT_PROOF_1: text.slice(0, middle), TABELLIO_CHECKPOINT_PROOF_2: text.slice(middle) });
};
assert.equal(invokePush({ ...envelope, base: candidate }).status, 1, 'HEAD is not the prior push base');
assert.equal(invokePush({ ...envelope, repositoryId: 'github.com/Wrong/Repository' }).status, 1);
assert.equal(invokePush({ ...envelope, candidate: base }).status, 1);
assert.equal(invokePush(envelope).status, 0, 'prior-base proof loads after origin/main advances');
assert.equal(git(target, 'rev-parse', 'refs/heads/entire/checkpoints/v1'), nativeTip);
assert.equal(invoke('cleanup').status, 0);
git(target, 'update-ref', 'refs/remotes/origin/main', base);
assert.equal(invoke('load', { ...envelope, base: candidate }).status, 1, 'PR proof rejects the wrong base');
const loaded = invoke('load'); assert.equal(loaded.status, 0, loaded.stderr);
assert.equal(git(target, 'rev-parse', 'refs/heads/entire/checkpoints/v1'), nativeTip);
for (const path of ['prompt.txt', 'full.jsonl']) assert.notEqual(run(target, 'git', ['cat-file', '-e', git(source, 'rev-parse', `${nativeTip}:${path}`)]).status, 0);
Expand All @@ -135,5 +149,30 @@ test('private runner envelope binds candidate and digest, rejects leaks, and rem
git(target, 'update-ref', ref, base); assert.equal(invoke('load').status, 1);
assert.equal(git(target, 'rev-parse', ref), base); git(target, 'update-ref', '-d', ref);
}
git(target, '-c', 'user.name=Fixture', '-c', 'user.email=fixture@example.invalid', 'commit', '--allow-empty', '-m', 'Second PR candidate');
const secondCandidate = git(target, 'rev-parse', 'HEAD');
assert.equal(git(target, 'rev-parse', 'HEAD^'), candidate);
assert.equal(git(target, 'merge-base', 'origin/main', 'HEAD'), base);
assert.equal(invoke('load', { ...envelope, candidate: secondCandidate, base: candidate }).status, 1, 'multi-commit PR must reject HEAD^ in place of merge-base');
assert.equal(invoke('load', { ...envelope, candidate: secondCandidate }).status, 0, 'multi-commit PR retains its merge-base');
assert.equal(invoke('cleanup').status, 0);
assert.equal(git(target, 'rev-parse', 'HEAD'), secondCandidate);
} finally { await rm(root, { recursive: true, force: true }); }
});


test('Buildkite repository extraction uses shared GitHub parser for HTTPS and SSH origins', async () => {
const source = await readFile(resolve('.buildkite/scripts/product-validation.sh'), 'utf8');
const extraction = source.match(/node --input-type=module -e '([^']+)' "\$repository_url"/);
assert.ok(extraction, 'Exercise the registered shell command, not a copy of its parser');
for (const remote of ['https://github.com/Fixture/Transport.git', 'git@github.com:Fixture/Transport.git', 'ssh://git@github.com/Fixture/Transport.git']) {
const result = run(process.cwd(), process.execPath, ['--input-type=module', '-e', extraction[1], remote]);
assert.equal(result.status, 0, result.stderr);
assert.equal(result.stdout.trim(), 'Fixture/Transport');
}
for (const remote of ['ssh://git@example.com/Fixture/Transport.git', 'https://github.com/Fixture/Transport/extra', 'ssh://git@github.com/../Transport.git', 'not-a-repository']) {
const result = run(process.cwd(), process.execPath, ['--input-type=module', '-e', extraction[1], remote]);
assert.equal(result.status, 1);
assert.equal(result.stdout.trim(), '');
}
});
Loading