Repository navigation
Expand file tree
/
Copy pathaction.yml
More file actions
114 lines (105 loc) · 4.83 KB
/
Copy pathaction.yml
File metadata and controls
114 lines (105 loc) · 4.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
name: 'Tracefold Agent Mutation & Receipt Verifier'
description: 'Verifies DSSE audit receipts offline against a trusted checkpoint, and lints the Cedar policy pack, in CI'
author: 'Tracefold Core Team'
branding:
icon: 'shield'
color: 'purple'
# What changed on 3 Sep 2026 (issue #5): the previous version of this file called
# `gx verify-receipts --dir <d> --policy <p>`, which is not a subcommand the CLI has
# ever shipped, so the action could not pass even with `gx` installed. The shipped
# surface is `gx receipt verify <FILE> [--offline --checkpoint --checkpoint-key --key]`
# and `gx policy lint <PATH>` -- both read off `gx --help` on the built binary. The
# steps below call those, one receipt at a time.
#
# Two inputs were removed rather than kept as decoration: `enforce-inverses` and
# `fail-on-tamper`. Neither mapped to any flag. `gx receipt verify` always checks the
# DSSE signature, the canonical CID, and inclusion against the head it is given; there
# is no dial that turns half of that off, so an input claiming to be one was a lie.
#
# Honest limit: this action has not been observed running green in CI. Actions on this
# repository are blocked at the billing gate (no workflow job has started since 20 Aug),
# so the evidence behind it is the CLI's own `--help` and the same call shape
# `crates/gx-cli/src/demo.rs::verify_offline` uses -- not a green run.
#
# What a green run would mean, and would not: it says each receipt is genuine, is the
# bytes it names, and is included in the log at that checkpoint's tree size. It says
# nothing about whether the change a receipt describes was correct. See docs/LIMITS.md.
inputs:
receipt-dir:
description: 'Directory holding the receipts to verify (*.json and *.dsse are read)'
required: false
default: '.agent-receipts'
checkpoint:
description: 'The trusted ledger head to check each inclusion proof against'
required: false
default: 'checkpoint.json'
checkpoint-key:
description: 'The public key that checkpoint was signed with. Without it the answer says anchor_authenticated: false'
required: false
default: 'trusted_key.json'
key:
description: 'The public key the receipts were signed with'
required: false
default: 'trusted_key.json'
policy-path:
description: 'Cedar policy pack to lint. Skipped when the path does not exist'
required: false
default: 'policy.cedar'
fail-on-empty:
description: 'Fail when receipt-dir holds no receipts. A gate with nothing to check should not report green'
required: false
default: 'true'
runs:
using: 'composite'
steps:
- name: Run Tracefold verification gate
shell: bash
env:
RECEIPT_DIR: ${{ inputs.receipt-dir }}
CHECKPOINT: ${{ inputs.checkpoint }}
CHECKPOINT_KEY: ${{ inputs.checkpoint-key }}
TRUSTED_KEY: ${{ inputs.key }}
POLICY_PATH: ${{ inputs.policy-path }}
FAIL_ON_EMPTY: ${{ inputs.fail-on-empty }}
run: |
set -euo pipefail
# Fail-closed: a gate that cannot run must not pass.
if ! command -v gx >/dev/null 2>&1; then
echo "::error::gx not found on PATH. Install the CLI in a prior step (see examples/ci/receipt-check.yml) before this action." >&2
exit 1
fi
gx --version
if [ -f "$POLICY_PATH" ]; then
echo "Linting policy pack: $POLICY_PATH"
gx policy lint "$POLICY_PATH"
else
echo "::notice::no policy pack at $POLICY_PATH -- skipping gx policy lint"
fi
shopt -s nullglob
receipts=("$RECEIPT_DIR"/*.json "$RECEIPT_DIR"/*.dsse)
if [ "${#receipts[@]}" -eq 0 ]; then
if [ "$FAIL_ON_EMPTY" = "true" ]; then
echo "::error::no receipts under $RECEIPT_DIR -- a gate with nothing to check must not report green." >&2
exit 1
fi
echo "::notice::no receipts under $RECEIPT_DIR, and fail-on-empty is false -- nothing was checked."
exit 0
fi
# --offline keeps this self-contained: no ledger is consulted, so the checkpoint
# the caller already trusts is the only anchor. Missing anchor files are an error
# rather than a silent downgrade to anchor_authenticated:false.
for f in "$CHECKPOINT" "$CHECKPOINT_KEY" "$TRUSTED_KEY"; do
if [ ! -f "$f" ]; then
echo "::error::anchor file not found: $f -- offline verification needs the checkpoint, the key it was signed with, and the receipts' key." >&2
exit 1
fi
done
for receipt in "${receipts[@]}"; do
echo "Verifying $receipt"
gx receipt verify "$receipt" \
--offline \
--checkpoint "$CHECKPOINT" \
--checkpoint-key "$CHECKPOINT_KEY" \
--key "$TRUSTED_KEY"
done
echo "Verified ${#receipts[@]} receipt(s) offline against $CHECKPOINT."