astrid-runtime/astrid · critical
durable capsule {id} provenance differs from authority recei
Error message
durable capsule {id} provenance differs from authority receipt What it means
The archive carries a signature (ArtifactVerification::Signed) whose signer or signature does not match the signer/signature recorded in the InstalledAuthority receipt. The library throws this because durable capsules must be provably signed by the same identity the authority receipt approved; a different signer or signature means the artifact provenance was replaced or the receipt is stale.
Source
Thrown at crates/astrid-capsule-install/src/storage.rs:339
for component in &manifest.components {
if let Some(capabilities) = &component.capabilities {
effective_capabilities.merge_from(capabilities);
}
}
if !effective_capabilities
.expansions_from(&authority.approved_capabilities)
.is_empty()
{
bail!("durable capsule {id} manifest exceeds its authority receipt");
}
match verification {
ArtifactVerification::Signed(provenance) => {
let signer = provenance.signer.to_string();
let signature = provenance.signature.to_string();
if authority.signer.as_deref() != Some(signer.as_str())
|| authority.signature.as_deref() != Some(signature.as_str())
{
bail!("durable capsule {id} provenance differs from authority receipt");
}
},
ArtifactVerification::Unsigned { .. } => {
if authority.signer.is_some() || authority.signature.is_some() {
bail!("durable capsule {id} authority claims provenance absent from archive");
}
},
}
Ok(())
}
struct ArchiveInventory {
files: std::collections::BTreeMap<String, Vec<u8>>,
directories: std::collections::BTreeSet<String>,
}
fn read_archive_files(archive_bytes: &[u8]) -> anyhow::Result<ArchiveInventory> {
let decoder = flate2::read::GzDecoder::new(Cursor::new(archive_bytes));View on GitHub (pinned to affd8760f4)
Solutions
- Re-issue the authority receipt with the current signer and signature values.
- Re-sign the archive with the key matching authority.signer so provenance matches the receipt.
- Restore the original signed artifact if the wrong one was installed.
- Update the key-rotation workflow so receipts are refreshed whenever signing keys change.
Example fix
// before: receipt holds old signer
authority.signer = Some("old-publisher".into());
// after: refresh receipt after re-signing
authority.signer = Some(provenance.signer.to_string());
authority.signature = Some(provenance.signature.to_string()); Defensive patterns
Strategy: validation
Validate before calling
if let ArtifactVerification::Signed(p) = verification {
if authority.signer.as_deref() != Some(p.signer.to_string().as_str())
|| authority.signature.as_deref() != Some(p.signature.to_string().as_str()) {
return Err("provenance does not match authority receipt");
}
} Type guard
fn provenance_matches(p: &Provenance, authority: &InstalledAuthority) -> bool {
authority.signer.as_deref() == Some(p.signer.to_string().as_str())
&& authority.signature.as_deref() == Some(p.signature.to_string().as_str())
} Try / catch
match read_verified_durable_package_for_owner(&store, owner, id).await {
Ok(pkg) => pkg,
Err(e) if e.to_string().contains("provenance differs from authority receipt") => {
// re-sign with approved key or refresh the receipt
},
Err(e) => return Err(e),
} Prevention
- Always sign with the key recorded in the authority receipt.
- Refresh receipts as part of any key-rotation procedure.
- Verify provenance against the receipt immediately after signing, before publishing.
When it happens
Trigger: read_verified_durable_package_for_owner where provenance.signer.to_string() != authority.signer or provenance.signature.to_string() != authority.signature for a Signed artifact.
Common situations: Re-signing an artifact with a new key without updating the authority receipt; importing a capsule signed by a different publisher; rotating signing keys; receipt pinned to an old signature of the same package.
Related errors
- capsule provenance changed after authority decision
- durable capsule {id} authority claims provenance absent from
- capsule '{}' is {}; explicit local approval is required
- durable capsule {id} manifest exceeds its authority receipt
- signed shuttle for '{distro_id}' is missing its manifest_has
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/347960a8e9627ee6.
Report an issue: GitHub.