astrid-runtime/astrid · critical
durable capsule {id} authority claims provenance absent from
Error message
durable capsule {id} authority claims provenance absent from archive What it means
The archive is unsigned (ArtifactVerification::Unsigned) but the authority receipt records a signer and/or signature. The library throws this because the receipt claims provenance that the artifact itself does not carry; installing it would let an unsigned artifact pass under a signed identity. Verification fails for the durable read.
Source
Thrown at crates/astrid-capsule-install/src/storage.rs:344
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));
let mut archive = tar::Archive::new(decoder);
let mut files = std::collections::BTreeMap::new();
let mut directories = std::collections::BTreeSet::new();
for entry in archive.entries().context("read durable capsule archive")? {
let mut entry = entry.context("read durable capsule archive entry")?;View on GitHub (pinned to affd8760f4)
Solutions
- Sign the archive with the expected key so the artifact matches the receipt's provenance.
- Clear authority.signer/authority.signature if the capsule is intentionally unsigned and re-approve it.
- Republish the capsule so receipt and artifact are generated in one consistent step.
- Check the build pipeline for a signing step that was skipped or failed silently.
Example fix
// before: unsigned artifact with receipt provenance
ArtifactVerification::Unsigned { .. } + authority.signer = Some("pub")
// after: sign the artifact before installing
let provenance = sign_artifact(&archive_bytes, &signing_key)?;
ArtifactVerification::Signed(provenance) Defensive patterns
Strategy: validation
Validate before calling
if let ArtifactVerification::Unsigned { .. } = verification {
if authority.signer.is_some() || authority.signature.is_some() {
return Err("receipt claims provenance but artifact is unsigned");
}
} Type guard
fn receipt_provenance_consistent(v: &ArtifactVerification, authority: &InstalledAuthority) -> bool {
match v {
ArtifactVerification::Signed(_) => true,
ArtifactVerification::Unsigned { .. } => authority.signer.is_none() && authority.signature.is_none(),
}
} Try / catch
match read_verified_durable_package_for_owner(&store, owner, id).await {
Ok(pkg) => pkg,
Err(e) if e.to_string().contains("provenance absent from archive") => {
// sign the artifact or clear receipt provenance, then republish
},
Err(e) => return Err(e),
} Prevention
- Make signing a mandatory, non-skippable CI step for signed capsules.
- Fail the build if signing produces no signature rather than publishing unsigned.
- Keep receipt and artifact generation in a single publish transaction.
When it happens
Trigger: read_verified_durable_package_for_owner where verification is Unsigned { .. } and authority.signer.is_some() || authority.signature.is_some().
Common situations: Signing step dropped during republish (e.g. CI built an unsigned artifact) while the receipt was preserved; receipt copied from a signed capsule; artifact re-exported without its signature.
Related errors
- capsule provenance changed after authority decision
- durable capsule {id} provenance differs from authority recei
- capsule '{}' is {}; explicit local approval is required
- shuttle for '{distro_id}' is unsigned (no [distro.signing] o
- 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/7e97491cc4a0801d.
Report an issue: GitHub.