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: 0 additions & 2 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ steps:
timeout_in_minutes: 50
artifact_paths:
- "tabellio-validation-result.json"
- ".artifacts/tabellio/validation-ref.bundle"
- ".artifacts/tabellio/validation-ref.sha"
plugins:
- mise#v1.1.4:
version: "2026.2.11"
44 changes: 44 additions & 0 deletions .buildkite/scripts/checkpoint-evidence.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
set -euo pipefail
# Import only native checkpoint history explicitly supplied by the operator.
# The subsequent product gate still verifies metadata and exact-candidate association.
checkpoint_ref=refs/heads/entire/checkpoints/v1
if [[ -n "${TABELLIO_CHECKPOINT_BUNDLE:-}" ]]; then
bundle="$TABELLIO_CHECKPOINT_BUNDLE"
if [[ ! -f "$bundle" ]] || ! git bundle verify "$bundle" >/dev/null 2>&1; then
echo 'Checkpoint setup blocked: supplied bundle is missing, invalid, or has unavailable prerequisites.' >&2
exit 1
fi
if ! git bundle list-heads "$bundle" "$checkpoint_ref" | awk -v ref="$checkpoint_ref" '$2 == ref { found=1 } END { exit !found }'; then
echo 'Checkpoint setup blocked: bundle does not advertise the native Entire checkpoint ref.' >&2
exit 1
fi
# No force: divergent existing history requires explicit operator reconciliation.
if head -n 4 "$bundle" | grep -q '^@filter='; then
# Native filtered bundles preserve original object IDs and use promisor packs.
# Ordinary fetch rejects their intentionally absent transcript/prompt blobs.
advertised="$(git bundle list-heads "$bundle")"
imported="$(printf '%s\n' "$advertised" | awk -v ref="$checkpoint_ref" '$2 == ref { print $1 }')"
if [[ "$(printf '%s\n' "$advertised" | wc -l | tr -d ' ')" != 1 ]] ||
! git bundle unbundle "$bundle" >/dev/null 2>&1; then
echo 'Checkpoint setup blocked: filtered native history import failed.' >&2
exit 1
fi
current="$(git rev-parse --verify "$checkpoint_ref" 2>/dev/null || true)"
if [[ -n "$current" ]] && ! git merge-base --is-ancestor "$current" "$imported"; then
echo 'Checkpoint setup blocked: divergent native history requires operator reconciliation.' >&2
exit 1
fi
if ! git update-ref "$checkpoint_ref" "$imported" "$current"; then
echo 'Checkpoint setup blocked: native history changed during import.' >&2
exit 1
fi
elif ! git fetch --no-tags "$bundle" "$checkpoint_ref:$checkpoint_ref" >/dev/null 2>&1; then
echo 'Checkpoint setup blocked: native checkpoint import failed; reconcile existing history on the trusted worker.' >&2
exit 1
fi
fi
if ! git rev-parse --verify "$checkpoint_ref^{commit}" >/dev/null 2>&1; then
echo 'Checkpoint setup blocked: use a trusted worker with genuine native Entire history, or supply TABELLIO_CHECKPOINT_BUNDLE from customer-owned private storage. Never upload session records to public CI artifacts.' >&2
exit 1
fi
37 changes: 37 additions & 0 deletions .buildkite/scripts/entire-tools.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail

# Source to retain PATH in Buildkite; GitHub receives it through GITHUB_PATH.
entire_tools_root="${TABELLIO_ENTIRE_TOOLS_DIR:-${RUNNER_TEMP:-${TMPDIR:-/tmp}}/tabellio-entire-0.7.7}"
case "$(uname -s)-$(uname -m)" in
Linux-x86_64)
entire_archive_name=entire_linux_amd64.tar.gz
entire_archive_digest=63d89e2ac57fc52307907a15b168a7b0bf7b114993b27f8fa943dfdb4159ad26
;;
Darwin-arm64)
entire_archive_name=entire_darwin_arm64.tar.gz
entire_archive_digest=960f25c18ebd7fa66c00081fc0abff64ce34774ff7ce0c03e3b5d12a4b134568
;;
*) printf '%s\n' 'Unsupported Entire tool platform.' >&2; exit 1 ;;
esac
mkdir -p "$entire_tools_root"
entire_archive_path="$entire_tools_root/$entire_archive_name"
if [[ ! -f "$entire_archive_path" ]]; then
curl --fail --silent --show-error --location --proto '=https' --proto-redir '=https' --tlsv1.2 \
--connect-timeout 15 --max-time 120 \
"https://github.com/entireio/cli/releases/download/v0.7.7/$entire_archive_name" \
--output "$entire_archive_path"
fi
node --input-type=module - "$entire_archive_path" "$entire_archive_digest" <<'NODE'
import { createHash } from 'node:crypto';
import { readFileSync } from 'node:fs';
const actual = createHash('sha256').update(readFileSync(process.argv[2])).digest('hex');
if (actual !== process.argv[3]) throw new Error('Entire archive integrity mismatch.');
NODE
tar -xzf "$entire_archive_path" -C "$entire_tools_root" entire
export PATH="$entire_tools_root:$PATH"
entire_version_output="$(entire version)"
grep -Eq '^Entire CLI v?0\.7\.7([[:space:]]|$)' <<< "$entire_version_output"
if [[ -n "${GITHUB_PATH:-}" ]]; then
printf '%s\n' "$entire_tools_root" >> "$GITHUB_PATH"
fi
31 changes: 21 additions & 10 deletions .buildkite/scripts/product-validation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,22 @@ fi

. .buildkite/scripts/verify-git-toolchain.sh
. .buildkite/scripts/security-tools.sh
. .buildkite/scripts/entire-tools.sh

postgres_bin="$(pg_config --bindir)"
test -x "$postgres_bin/initdb"
test -x "$postgres_bin/pg_ctl"
export PATH="$postgres_bin:$PATH"

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")"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept ssh:// GitHub origin URLs

When a Buildkite checkout configures origin as the valid canonical form ssh://git@github.com/OWNER/REPO.git, this regex does not match, so the node -e command exits nonzero under set -e and product validation aborts before running the gate. The repository's own remote parser accepts this form, so derive the ID through that shared parser or extend this extraction to cover ssh:// URLs.

Useful? React with 👍 / 👎.

fi
[[ "$repository_id" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]] || { echo "A valid customer repository ID is required." >&2; exit 1; }

candidate="${BUILDKITE_COMMIT:-HEAD}"
base_branch="${BUILDKITE_PULL_REQUEST_BASE_BRANCH:-${TABELLIO_BASE_BRANCH:-main}}"
base_ref="origin/${base_branch}"
Expand All @@ -30,6 +40,7 @@ checkpoint_args=()
git fetch --no-tags origin "+refs/heads/${base_branch}:refs/remotes/origin/${base_branch}"
test "$(git rev-parse HEAD^{commit})" = "$(git rev-parse "${candidate}^{commit}")"

umask 077
temporary_dir="$(mktemp -d)"
trap 'rm -rf "$temporary_dir"' EXIT

Expand All @@ -47,7 +58,7 @@ if [[ "$default_branch_build" == "true" ]]; then
fi
if ! curl --fail --silent --show-error \
"${github_headers[@]}" \
"https://api.github.com/repos/IntelIP/Tabellio/commits/${candidate}/pulls" \
"https://api.github.com/repos/${repository_id}/commits/${candidate}/pulls" \
| node scripts/resolve-merged-checkpoint.mjs \
--commit "$candidate" \
--github-output "$checkpoint_output"; then
Expand Down Expand Up @@ -84,19 +95,19 @@ fi

install -m 755 scripts/tabellio-validator.mjs "$temporary_dir/tabellio-validator"

PATH="$temporary_dir:$PATH" node scripts/tabellio-validate.mjs gate \
if ! PATH="$temporary_dir:$PATH" node scripts/tabellio-validate.mjs gate \
--repo . \
--repo-id IntelIP/Tabellio \
--repo-id "$repository_id" \
--runner-id "buildkite:${BUILDKITE_BUILD_ID:?Buildkite build ID is required}" \
--base "$base_ref" \
--commit HEAD \
"${checkpoint_args[@]}" \
--manifest tabellio.validation.json \
| tee tabellio-validation-result.json
> "$temporary_dir/tabellio-validation-private.json" 2> "$temporary_dir/validation-stderr.log"; then
node scripts/validation-public-summary.mjs "$temporary_dir/tabellio-validation-private.json" tabellio-validation-result.json
printf '%s\n' "Product validation failed; inspect the trusted worker result. Missing genuine checkpoint evidence must fail the gate." >&2
exit 1
fi

validation_ref="refs/tabellio/validations"
validation_commit="$(git rev-parse "${validation_ref}^{commit}")"
mkdir -p .artifacts/tabellio
git bundle create .artifacts/tabellio/validation-ref.bundle "$validation_ref"
printf '%s\n' "$validation_commit" > .artifacts/tabellio/validation-ref.sha
git bundle verify .artifacts/tabellio/validation-ref.bundle
node scripts/validation-public-summary.mjs "$temporary_dir/tabellio-validation-private.json" tabellio-validation-result.json
# Native validation refs remain private on the trusted worker; never upload them as public CI artifacts.
60 changes: 58 additions & 2 deletions .buildkite/scripts/provenance-coverage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,64 @@ test -x "$postgres_bin/initdb"
test -x "$postgres_bin/pg_ctl"
export PATH="$postgres_bin:$PATH"

c8 --exclude '**/node_modules/**' --reporter=json --reports-dir coverage node scripts/demo-provenance.mjs \
--verify-storage-tests true --out coverage/provenance-demo.json
# Run the storage/security/publication suite and changed local-workflow tests
# directly with one file worker, so actual two-process race tests remain intact
# while unrelated Git fixtures do not compete. Their individual
# test deadlines and the existing job deadline apply instead of the demo's
# unrelated 60-second child-process deadline. Do not skip PostgreSQL evidence.
umask 077
coverage_pg_root="$(mktemp -d /tmp/tabellio-coverage-pg.XXXXXX)"
coverage_pg_data="$coverage_pg_root/data"
coverage_pg_socket="$coverage_pg_root/socket"
cleanup_coverage_postgres() {
[[ -n "$coverage_pg_root" ]] || return 0
if [[ -f "$coverage_pg_data/PG_VERSION" ]]; then
if pg_ctl -D "$coverage_pg_data" status >/dev/null 2>&1; then
if ! pg_ctl -D "$coverage_pg_data" -m fast -w -t 30 stop >/dev/null 2>&1; then
printf '%s\n' "Coverage PostgreSQL cleanup failed; preserve $coverage_pg_root for recovery." >&2
return 1
fi
else
coverage_pg_status=$?
if [[ "$coverage_pg_status" != 3 ]]; then
printf '%s\n' "Coverage PostgreSQL state is uncertain; preserve $coverage_pg_root for recovery." >&2
return 1
fi
fi
fi
if ! rm -rf "$coverage_pg_root"; then
printf '%s\n' "Coverage PostgreSQL directory cleanup failed; preserve $coverage_pg_root for recovery." >&2
return 1
fi
coverage_pg_root=
}
trap 'coverage_exit=$?; trap - EXIT; if ! cleanup_coverage_postgres; then exit 1; fi; exit "$coverage_exit"' EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
mkdir "$coverage_pg_socket"
initdb -D "$coverage_pg_data" --auth-local=trust --auth-host=reject \
--username=tabellio --encoding=UTF8 --no-locale >/dev/null
pg_ctl -D "$coverage_pg_data" -l "$coverage_pg_root/postgres.log" \
-o "-c listen_addresses='' -k $coverage_pg_socket" -w -t 30 start >/dev/null
TABELLIO_REQUIRE_POSTGRES=1 TABELLIO_TEST_PG_SOCKET="$coverage_pg_socket" TABELLIO_TEST_PG_USER=tabellio \
c8 --exclude '**/node_modules/**' --reporter=json --reports-dir coverage \
node --test --test-concurrency=1 tests/local-provenance-store.test.mjs tests/provenance-ledger.test.mjs \
tests/provenance-sources.test.mjs tests/provenance-security.test.mjs \
tests/provenance-security-scanners.test.mjs tests/provenance-review-result.test.mjs \
tests/provenance-review-publication.test.mjs \
tests/platform-config.test.mjs tests/preflight.test.mjs \
tests/release-workflow.test.mjs tests/release-cli.test.mjs tests/checkpoint-evidence.test.mjs
cleanup_coverage_postgres

# Preserve the same real recovery demo coverage without rerunning that suite
# through its nested child-process wrapper.
c8 --clean=false --exclude '**/node_modules/**' --reporter=json --reports-dir coverage \
node scripts/demo-provenance.mjs --out coverage/provenance-demo.json

# Include the policy benchmark and negative setup diagnostics without discarding
# the integration demo coverage collected above.
c8 --clean=false --exclude '**/node_modules/**' --reporter=json --reports-dir coverage \
node --test --test-concurrency=1 tests/provenance-benchmark.test.mjs tests/demo-provenance.test.mjs tests/validation-checkpoints.test.mjs

# Fallow 2.89 consumes function/statement coverage but rejects c8's unknown
# branch-column sentinel (-1). Preserve the original report; omit only branch
Expand Down
3 changes: 2 additions & 1 deletion .buildkite/scripts/verify-git-toolchain.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ git merge-base --is-ancestor "$head_commit" "$head_commit"
(
temporary_dir="$(mktemp -d)"
trap 'rm -rf "$temporary_dir"' EXIT
git bundle create "$temporary_dir/capability.bundle" --all
# Probe the public candidate without traversing private, intentionally filtered refs.
git bundle create "$temporary_dir/capability.bundle" HEAD
git bundle verify "$temporary_dir/capability.bundle" >/dev/null
)

Expand Down
48 changes: 36 additions & 12 deletions .github/workflows/product-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ on:
branches: [main]
workflow_dispatch:

concurrency:
group: product-validation-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read
pull-requests: read

jobs:
validate:
environment: tabellio-checkpoint-proof
runs-on: ubuntu-latest
timeout-minutes: 50
steps:
Expand All @@ -21,7 +26,7 @@ jobs:
persist-credentials: false
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with: {node-version: 22}
with: {node-version: 22.23.1, package-manager-cache: false}
- name: Enable local PostgreSQL binaries for isolated provenance validation
run: |
postgres_bin="$(pg_config --bindir)"
Expand All @@ -30,6 +35,8 @@ jobs:
echo "$postgres_bin" >> "$GITHUB_PATH"
- name: Install pinned security scanners
run: bash .buildkite/scripts/security-tools.sh
- name: Install checksum-verified Entire 0.7.7
run: bash .buildkite/scripts/entire-tools.sh
- name: Resolve squash-merge checkpoint revision
id: checkpoint
if: github.event_name == 'push'
Expand All @@ -55,12 +62,20 @@ jobs:
git fetch --no-tags origin "+$CHECKPOINT_FETCH_REF:$CHECKPOINT_LOCAL_REF"
actual_head="$(git rev-parse "$CHECKPOINT_LOCAL_REF^{commit}")"
test "$actual_head" = "$CHECKPOINT_EXPECTED_HEAD"
- name: Load approved exact-candidate checkpoint evidence
env:
TABELLIO_CHECKPOINT_PROOF_1: ${{ secrets.TABELLIO_CHECKPOINT_PROOF_1 }}
TABELLIO_CHECKPOINT_PROOF_2: ${{ secrets.TABELLIO_CHECKPOINT_PROOF_2 }}
run: node scripts/ci-checkpoint-evidence.mjs load
- name: Validate exact candidate
env:
CHECKPOINT_FOUND: ${{ steps.checkpoint.outputs.found }}
CHECKPOINT_HEAD: ${{ steps.checkpoint.outputs.head }}
run: |
set -o pipefail
umask 077
private_dir="$(mktemp -d)"
trap 'rm -rf "$private_dir"' EXIT
base_ref=origin/main
checkpoint_args=()
if [ "$GITHUB_EVENT_NAME" = "push" ]; then
Expand All @@ -70,19 +85,28 @@ jobs:
fi
fi
install -m 755 scripts/tabellio-validator.mjs "$RUNNER_TEMP/tabellio-validator"
PATH="$RUNNER_TEMP:$PATH" node scripts/tabellio-validate.mjs gate \
if ! PATH="$RUNNER_TEMP:$PATH" node scripts/tabellio-validate.mjs gate \
--repo . \
--repo-id IntelIP/Tabellio \
--repo-id "github.com/$GITHUB_REPOSITORY" \
--runner-id "github:$GITHUB_RUN_ID:$GITHUB_RUN_ATTEMPT" \
--base "$base_ref" \
--commit HEAD \
"${checkpoint_args[@]}" \
--manifest tabellio.validation.json | tee tabellio-validation-result.json
- name: Upload validation result
--manifest tabellio.validation.json > "$private_dir/tabellio-validation-private.json" 2> "$private_dir/validation-stderr.log"; then
node scripts/validation-public-summary.mjs "$private_dir/tabellio-validation-private.json" tabellio-validation-result.json
echo "Product validation failed; inspect the trusted worker result. Missing genuine checkpoint evidence must fail the gate." >&2
exit 1
fi
node scripts/validation-public-summary.mjs "$private_dir/tabellio-validation-private.json" tabellio-validation-result.json
- name: Publish safe validation summary without artifact storage
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: tabellio-validation-${{ github.event.pull_request.head.sha || github.sha }}
path: |
tabellio-validation-result.json
refs/tabellio/validations/
if-no-files-found: warn
run: |
if [ -f tabellio-validation-result.json ]; then
cat tabellio-validation-result.json
cat tabellio-validation-result.json >> "$GITHUB_STEP_SUMMARY"
else
echo 'Product validation blocked before a safe result was produced.' >> "$GITHUB_STEP_SUMMARY"
fi
- name: Remove private checkpoint runner files
if: always()
run: node scripts/ci-checkpoint-evidence.mjs cleanup
Loading
Loading