{"record":{"id":"5a49c69ec3715812","repo":"jdx/mise","slug":"lockfile-generation-would-change-the-recorded-signer","errorCode":null,"errorMessage":"lockfile generation would change the recorded signer; previous files were preserved","messagePattern":"lockfile generation would change the recorded signer; previous files were preserved","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lockfile/generate.rs","lineNumber":790,"sourceCode":"    // artifact authenticated by its signed release manifest. Older incremental\n    // lock updates could carry detected GitHub provenance into a Packslip entry,\n    // but complete generation intentionally does not persist that unverified\n    // link. Without a signer, retain the ordinary provenance ratchet.\n    let packslip_signer_replaces_provenance =\n        backend.starts_with(\"packslip:\") && new.signer.is_some();\n    if provenance_is_downgrade(\n        old.provenance.as_ref(),\n        new.provenance.as_ref(),\n        packslip_signer_replaces_provenance,\n    ) {\n        bail!(\n            \"lockfile generation would downgrade recorded provenance; previous files were preserved\"\n        );\n    }\n    if let Some(signer) = &old.signer\n        && (new.signer.as_ref() != Some(signer) || new.attested_by != old.attested_by)\n    {\n        bail!(\n            \"lockfile generation would change the recorded signer; previous files were preserved\"\n        );\n    }\n    // Preserve identities across reordering, then pair replaced URLs in their\n    // configured order so version upgrades retain the previous trust baseline.\n    let mut replacements = new.additional_artifacts.iter().filter(|artifact| {\n        !old.additional_artifacts\n            .iter()\n            .any(|old| old.url == artifact.url)\n    });\n    for artifact in &old.additional_artifacts {\n        let replacement = new\n            .additional_artifacts\n            .iter()\n            .find(|new| new.url == artifact.url)\n            .or_else(|| replacements.next());\n        if provenance_is_downgrade(\n            artifact.provenance.as_ref(),","sourceCodeStart":772,"sourceCodeEnd":808,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/lockfile/generate.rs#L772-L808","documentation":"The lockfile records the signer identity (and `attested_by`) used to verify artifacts. `ensure_no_downgrade` bails if regeneration would record a different signer or attestation authority than the existing entry, preserving the previous files. This prevents silently re-trusting artifacts under a new signing identity.","triggerScenarios":"Regenerating a lockfile where the old entry has `signer: Some(...)` but the newly computed entry has a different signer, or a different `attested_by` value — e.g. the packslip manifest switched signing keys or a different attestation authority now signs the release.","commonSituations":"A project rotated its release signing key; mise switched between GitHub attestations and a project's own signing identity; a mirror serves artifacts signed by a different party; packslip manifest updated signer metadata.","solutions":["Verify the signer change is legitimate (check the project's release announcements/key rotation) before proceeding","Update or remove the existing lockfile entry deliberately so the new signer is consciously accepted","Pin generation to the artifact source that uses the original signer","Regenerate the lockfile from a trusted checkout after reviewing the new signer fingerprint"],"exampleFix":"# before: blindly regenerating after upstream key rotation\nmise lock --all\n# after: review then explicitly refresh\nmise lock --all   # after confirming new signer fingerprint via project announcements","handlingStrategy":"validation","validationCode":"if let Some(old_signer) = &existing.signer {\n    if new.signer.as_ref() != Some(old_signer) || new.attested_by != existing.attested_by {\n        // signer changed — confirm upstream key rotation before regenerating\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Track upstream signing-key/attestation announcements for locked dependencies","Diff the recorded signer field after lockfile regeneration and review changes","Avoid switching backends for already-locked tools without re-verifying signatures","Pin generation to the original artifact source"],"tags":["lockfile","signing","security"],"backgroundTag":"checksum-mismatch","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}