astrid-runtime/astrid · critical

capsule provenance changed after authority decision

Error message

capsule provenance changed after authority decision

What it means

`authority_for_install_source` compares the signer identity and signature of the freshly verified source against those recorded in the approved authority decision. This error is thrown when provenance changed — the capsule is now signed by a different signer or carries a different signature than what was approved — so the library refuses to reuse the old authority decision for content from a different origin.

Source

Thrown at crates/astrid-capsule-install/src/authority.rs:929

    source_dir: &Path,
    manifest: &CapsuleManifest,
    approved: Option<InstalledAuthority>,
) -> anyhow::Result<InstalledAuthority> {
    let verification = artifact::verify_directory(source_dir)?;
    let content_digest = verification.content_digest().to_string();
    let manifest_digest = digest_manifest(&std::fs::read(source_dir.join("Capsule.toml"))?);
    let (signer, signature) = verification_provenance(&verification);

    if let Some(approved) = approved {
        if approved.content_digest != content_digest {
            bail!(
                "capsule content changed after authority decision (approved {}, found {})",
                approved.content_digest,
                content_digest
            );
        }
        if approved.signer != signer || approved.signature != signature {
            bail!("capsule provenance changed after authority decision");
        }
        if approved.capsule_id != manifest.package.name
            || approved.version != manifest.package.version
        {
            bail!("capsule identity or version changed after authority decision");
        }
        if approved.manifest_digest != manifest_digest {
            bail!("capsule manifest changed after authority decision");
        }
        if approved.approved_capabilities != manifest.capabilities {
            bail!("capsule capabilities changed after authority decision");
        }
        return Ok(approved);
    }

    // Calling the legacy library install API is itself an operator-authority
    // action. User-facing CLI and daemon entry points use explicit decisions;
    // this path preserves the existing trusted embedding API while recording

View on GitHub (pinned to affd8760f4)

Solutions

  1. Re-run the authority approval against the current signing identity so the receipt records the new signer/signature
  2. Restore the capsule to the exact signed artifact that was originally approved (same signer key and signature)
  3. Verify the signing key was not unexpectedly rotated; if rotation is legitimate, publish and approve the re-signed release

Example fix

// before
bail!("capsule provenance changed after authority decision");
// after: re-approve with the new signer
// let authority = decision::approve(source_dir)?;
// install_from_local_path_internal(source_dir, Some(authority))
Defensive patterns

Strategy: validation

Validate before calling

// Verify provenance matches the approved decision before install
let verification = artifact::verify_directory(source_dir)?;
let (signer, signature) = verification_provenance(&verification);
assert_eq!(approved.signer.as_deref(), signer.as_deref());
assert_eq!(approved.signature.as_deref(), signature.as_deref());

Type guard

fn provenance_unchanged(approved: &InstalledAuthority, signer: &Option<String>, signature: &Option<String>) -> bool {
    approved.signer == *signer && approved.signature == *signature
}

Try / catch

match authority_for_install_source(source_dir, &manifest, Some(approved)) {
    Err(e) if e.to_string().contains("provenance changed") => reapprove_with_new_signer(),
    other => other.map(install),
}

Prevention

When it happens

Trigger: Calling `install_from_local_path_internal` with an approved `InstalledAuthority` where `approved.signer != current signer` or `approved.signature != current signature`, as recomputed by `verification_provenance(&verification)` over the re-verified source directory.

Common situations: Re-signing the capsule with a new key after approval; switching between signed and unsigned builds (or vice versa) in the source directory; pulling content from a different publisher into the reviewed directory.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/9c82f117bfd1ccba. Report an issue: GitHub.