{"record":{"id":"f201fe3aa051f003","repo":"astrid-runtime/astrid","slug":"capsule-changed-after-authority-review-appro","errorCode":null,"errorMessage":"capsule '{}' changed after authority review (approved {}, found {})","messagePattern":"capsule '(.+?)' changed after authority review \\(approved (.+?), found (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/astrid-capsule-install/src/authority.rs","lineNumber":988,"sourceCode":"            Some(verified.signature.to_string()),\n        ),\n        ArtifactVerification::Unsigned { .. } => (None, None),\n    }\n}\n\npub(crate) fn digest_manifest(bytes: &[u8]) -> String {\n    let mut hasher = blake3::Hasher::new();\n    hasher.update(MANIFEST_DIGEST_DOMAIN);\n    hasher.update(bytes);\n    hasher.finalize().to_hex().to_string()\n}\n\nfn ensure_bound_digest(\n    inspection: &InstallInspection,\n    approved_digest: &str,\n) -> anyhow::Result<()> {\n    if inspection.content_digest != approved_digest {\n        bail!(\n            \"capsule '{}' changed after authority review (approved {}, found {})\",\n            inspection.capsule_id,\n            approved_digest,\n            inspection.content_digest\n        );\n    }\n    Ok(())\n}\n\n#[cfg(test)]\n#[path = \"authority/unit_tests.rs\"]\nmod tests;\n","sourceCodeStart":970,"sourceCodeEnd":1001,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/authority.rs#L970-L1001","documentation":"`ensure_bound_digest` verifies that the content digest recorded at authority review time matches the digest of the capsule actually being installed (`inspection.content_digest` vs `approved_digest`). Called from `authorize_install`, this error is thrown when the capsule changed between the interactive/programmatic review and final authorization — the last line of defense binding an approval to exact bytes.","triggerScenarios":"Calling `authorize_install` with an `InstallInspection` whose `content_digest` differs from the `approved_digest` captured during the review — i.e. the source directory or artifact was modified after the user approved it (including in `inspect_archive_for_principal_in_workspace` / `inspect_directory_for_principal_in_workspace` flows).","commonSituations":"Rebuilding the artifact while the approval prompt is open; editing source files between review and confirm; a concurrent process writing into the capsule directory during authorization.","solutions":["Re-run inspection and approval against the current content so the approved digest matches, then authorize again","Freeze the source (revert to the reviewed commit/artifact) and retry authorization without modifying it in between","Ensure no concurrent builds/watchers write to the capsule directory while authorization is in flight"],"exampleFix":"// before\nbail!(\"capsule '{}' changed after authority review (approved {}, found {})\", inspection.capsule_id, approved_digest, inspection.content_digest);\n// after: re-inspect current content and re-approve\n// let inspection = inspect_directory_for_principal_in_workspace(...)?;\n// let approved = prompt_authority_decision(&inspection)?;\n// authorize_install(inspection, &approved)","handlingStrategy":"validation","validationCode":"// Bind the approval to exact bytes before authorizing\nif inspection.content_digest != approved_digest {\n    // re-run inspection + approval; never authorize stale decisions\n}","typeGuard":"fn bound_to_reviewed(inspection: &InstallInspection, approved_digest: &str) -> bool {\n    inspection.content_digest == approved_digest\n}","tryCatchPattern":"match authorize_install(&inspection, &approved_digest) {\n    Err(e) if e.to_string().contains(\"changed after authority review\") => {\n        let fresh = inspect_and_review(source)?; authorize_install(&fresh, &fresh.approved_digest)\n    },\n    other => other,\n}","preventionTips":["Complete authorization immediately after review; don't leave approvals open while editing","Pause builds/watchers while the approval dialog is open","Verify clean git state in the capsule directory before review","Prevent concurrent writes into the source directory during authorization"],"tags":["security","integrity","digest-mismatch","authorization"],"backgroundTag":"checksum-mismatch","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}