Integration test fixtures contain encrypted FHE data (secret keys, ciphertext blobs) and are stored as a GPG-encrypted archive (tests/fixtures.tar.gz.gpg) to prevent plaintext secrets from being committed to the repository.
CI decrypts fixtures at test time using a passphrase stored in GitHub Secrets. Two secret slots are used in alternation to allow atomic updates without breaking other PRs:
| Secret | Description |
|---|---|
FIXTURES_GPG_PASSPHRASE |
Slot A |
FIXTURES_GPG_PASSPHRASE_ALT |
Slot B |
The CI workflow (ci.yml) always references one of these by name. A fixture update PR swaps the reference to the other slot, so the old passphrase remains valid for any in-flight PRs until they rebase.
- enVector Cloud access (
ENVECTOR_ENDPOINT,ENVECTOR_API_KEY) - GitHub repo admin access (to update Secrets)
mise run setupcompleted
Open .github/workflows/ci.yml and find the FIXTURES_GPG_PASSPHRASE line:
# If this says FIXTURES_GPG_PASSPHRASE, the next slot is FIXTURES_GPG_PASSPHRASE_ALT
# If this says FIXTURES_GPG_PASSPHRASE_ALT, the next slot is FIXTURES_GPG_PASSPHRASE
FIXTURES_GPG_PASSPHRASE: ${{ secrets.FIXTURES_GPG_PASSPHRASE }}openssl rand -base64 32Copy the output — you will need it for steps 3 and 4.
If CI currently uses FIXTURES_GPG_PASSPHRASE, set the new passphrase in FIXTURES_GPG_PASSPHRASE_ALT, and vice versa.
# Example: setting the ALT slot
gh secret set FIXTURES_GPG_PASSPHRASE_ALT
# Paste the passphrase from step 2, then press Enter and Ctrl+DENVECTOR_ENDPOINT=... ENVECTOR_API_KEY=... python scripts/generate-test-fixtures.pyThis connects to enVector Cloud and writes plaintext fixtures to tests/fixtures/.
FIXTURES_GPG_PASSPHRASE="<passphrase from step 2>" mise run fixtures:encryptThis creates tests/fixtures.tar.gz.gpg. Verify the file was updated:
git diff --stat # should show tests/fixtures.tar.gz.gpg changedEdit .github/workflows/ci.yml — swap the secret name:
# Before (example)
FIXTURES_GPG_PASSPHRASE: ${{ secrets.FIXTURES_GPG_PASSPHRASE }}
# After
FIXTURES_GPG_PASSPHRASE: ${{ secrets.FIXTURES_GPG_PASSPHRASE_ALT }}The environment variable name (FIXTURES_GPG_PASSPHRASE) stays the same — only the secret reference changes.
rm -rf tests/fixtures/ # Remove plaintext fixtures
git add tests/fixtures.tar.gz.gpg .github/workflows/ci.yml
git commit -m "chore: update test fixtures and rotate GPG passphrase"Push the branch and confirm CI passes with the new secret slot. After merge, the old slot becomes stale and will be overwritten on the next rotation.
To run integration tests locally, you need the current passphrase:
export FIXTURES_GPG_PASSPHRASE="<current passphrase>"
mise run fixtures:decrypt
mise run testGenerated by scripts/generate-test-fixtures.py:
| File | Description |
|---|---|
keys/SecKey.json |
FHE secret key (for decryption in tests) |
keys/EncKey.json |
FHE encryption key |
ciphertext_score.b64 |
Base64-encoded CiphertextScore protobuf blob |
expected_scores.json |
Expected decrypted scores (test assertions) |
metadata_envelopes.json |
AES-encrypted metadata envelopes |
expected_metadata.json |
Expected plaintext metadata (test assertions) |
config.json |
Test parameters (team_secret, agent_id, dim, etc.) |