A secret that can only be replaced atomically cannot be rotated without coordinating a deploy on somebody else’s system.
// sign with the new secret, and also with the old one
$headers = [
'X-Signature' => $this->sign($body, $secrets->current()),
'X-Signature-Old'=> $this->sign($body, $secrets->previous()),
];
// or, better, a single header with several values:
// X-Signature: t=1663...,v1=abc...,v1=def...
// the subscriber accepts if ANY matches.
The multi-value header is the arrangement every large provider converged on, because it lets the subscriber verify against either secret without knowing which is current. Publishing an overlap window — both valid for thirty days — turns a rotation from a coordinated event into a self-service one.