astrid-runtime/astrid · critical

capsule capabilities changed after authority decision

Error message

capsule capabilities changed after authority decision

What it means

`authority_for_install_source` compares `approved.approved_capabilities` (the capability ceiling the operator approved) with `manifest.capabilities` (the capabilities the capsule now requests). This error is thrown when the capsule's requested capabilities were expanded after the authority decision — a privilege-escalation guard that stops an unreviewed capability grant from being installed under an old, narrower approval.

Source

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

            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
    // the same exact content and capability ceiling.
    Ok(InstalledAuthority {
        schema_version: 1,
        source: AuthoritySource::OperatorDistribution,
        capsule_id: manifest.package.name.clone(),
        version: manifest.package.version.clone(),
        content_digest,
        manifest_digest,
        signer,
        signature,
        approved_capabilities: manifest.capabilities.clone(),

View on GitHub (pinned to affd8760f4)

Solutions

  1. Re-run the authority approval so the operator reviews and approves the new capability set, then install with the new receipt
  2. Revert the capabilities section of Capsule.toml to the approved set and retry
  3. If the new capabilities are intentional, document and complete a fresh review before installing

Example fix

// before
bail!("capsule capabilities changed after authority decision");
// after: obtain a new decision covering the expanded capabilities
// let authority = decision::approve_with_capabilities(source_dir, &manifest.capabilities)?;
// install_from_local_path_internal(source_dir, Some(authority))
Defensive patterns

Strategy: validation

Validate before calling

// Ensure requested capabilities match the approved ceiling before install
let manifest = load_manifest(source_dir.join("Capsule.toml"))?;
assert_eq!(approved.approved_capabilities, manifest.capabilities,
          "capability set changed since approval; re-run operator review");

Type guard

fn capabilities_unchanged(approved: &InstalledAuthority, m: &CapsuleManifest) -> bool {
    approved.approved_capabilities == m.capabilities
}

Try / catch

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

Prevention

When it happens

Trigger: Calling `install_from_local_path_internal` with an approved `InstalledAuthority` where `approved.approved_capabilities != manifest.capabilities`, i.e. the `capabilities` section of Capsule.toml changed after approval (added permissions like network, fs access, etc.).

Common situations: A developer adds a new permission to Capsule.toml after the operator reviewed it; a dependency update pulls in capability requirements; accidentally editing the capabilities block while changing something else.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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