I split network deployments into Preview and Apply jobs so the diff can be reviewed before anything writes to a router. The first version produced a cryptographic review token, but Preview and Apply disagreed even when the rendered configuration was identical.
Semaphore checks the project out into a new task-local directory for every run. I had accidentally included that path in the token input. The token proved where the preview happened, not just what had been reviewed.
The approval now binds stable facts: the source revision, selected hosts, rendered artifacts, semantic configuration changes and the relevant live state. A different checkout can reproduce it. A changed commit, changed candidate or changed device state cannot.
VyOS then found a second version of the same mistake. One render proposed an empty configuration node. The text was different, so the automation expected a change; VyOS quite reasonably built the candidate and reported that there was nothing to commit. I removed the redundant node and added a regression check rather than teaching the deployment to distrust the router.
That left me with a clearer rule for the workflow: the review must describe an operation the target system can actually perform. Temporary paths, formatting and empty containers are implementation noise. If they can change an approval token or manufacture a diff, the approval is attached to the wrong thing.