{"record":{"id":"e5261e6545eb824a","repo":"astrid-runtime/astrid","slug":"retire-audit-source","errorCode":null,"errorMessage":"retire audit source","messagePattern":"retire audit source","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/audit_retirement_tests.rs","lineNumber":15,"sourceCode":"use super::{preflight_legacy_audit_sources, require_audit_integrity, retire_legacy_audit_dir};\nuse astrid_audit::ChainVerificationResult;\nuse astrid_core::SessionId;\nuse astrid_core::dirs::AstridHome;\n\n#[test]\nfn audit_retirement_validates_tree_and_removes_only_verified_source() {\n    let directory = tempfile::tempdir().expect(\"temporary home\");\n    let home = AstridHome::from_path(directory.path().join(\".astrid\"));\n    home.ensure().expect(\"home layout\");\n    let principal_home = home.principal_home(&astrid_core::PrincipalId::default());\n    principal_home.ensure().expect(\"legacy principal layout\");\n    std::fs::write(principal_home.audit_dir().join(\"entry\"), b\"audit\").expect(\"audit fixture\");\n\n    retire_legacy_audit_dir(&home, &principal_home.audit_dir()).expect(\"retire audit source\");\n    assert!(!principal_home.audit_dir().exists());\n    assert!(\n        !home\n            .migrations_dir()\n            .join(\"audit-principal-home.retired\")\n            .exists()\n    );\n}\n\n#[cfg(unix)]\n#[test]\nfn audit_retirement_rejects_redirects_before_removal() {\n    let directory = tempfile::tempdir().expect(\"temporary home\");\n    let home = AstridHome::from_path(directory.path().join(\".astrid\"));\n    home.ensure().expect(\"home layout\");\n    let principal_home = home.principal_home(&astrid_core::PrincipalId::default());\n    principal_home.ensure().expect(\"legacy principal layout\");\n    let outside = directory.path().join(\"outside\");","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/audit_retirement_tests.rs#L1-L33","documentation":"The message \"retire audit source\" is the expect() on retire_legacy_audit_dir(&home, &principal_home.audit_dir()) at audit_retirement_tests.rs:15. retire_legacy_audit_dir is the function under test: it validates the legacy per-principal audit tree and removes it, recording a migration marker under home.migrations_dir() only for verified sources. This expect fails when the retirement function returns Err — meaning the function refused to retire a tree the test believes is a legitimate, verified default-principal audit directory (no symlinks, non-empty).","triggerScenarios":"Calling retire_legacy_audit_dir() with a real, symlink-free audit directory that nonetheless fails its internal validation: e.g. it mistakes the tree for a redirect (symlink-detection false positive), rejects a non-default principal when the test intends the default one, fails to write the migration marker, or errors while removing the directory.","commonSituations":"A regression in the symlink/redirect validation in retire_legacy_audit_dir that misclassifies plain directories; changes to migrations_dir layout so the marker write fails; an API change where retire_legacy_audit_dir now requires a different argument (e.g. PrincipalHome instead of a PathBuf).","solutions":["Print the returned error (change .expect(\"retire audit source\") to match on Err and panic! with the error text) to see which validation rejected the tree.","Confirm the test uses PrincipalId::default() — retire_legacy_audit_dir may only retire the default principal's source by design.","Audit recent changes to retire_legacy_audit_dir for stricter redirect detection or new preconditions.","Check that no leftover 'redirect' symlink from another test pollutes the audit dir; recreate the tempdir fixture."],"exampleFix":"// before\nretire_legacy_audit_dir(&home, &principal_home.audit_dir()).expect(\"retire audit source\");\n// after\nretire_legacy_audit_dir(&home, &principal_home.audit_dir())\n    .unwrap_or_else(|e| panic!(\"retire audit source: {e}\"));","handlingStrategy":"try-catch","validationCode":"// precondition check before retiring\nlet dir = principal_home.audit_dir();\nassert!(dir.is_dir(), \"source must be a real directory\");\nassert!(!fs::symlink_metadata(dir).map(|m| m.file_type().is_symlink()).unwrap_or(true), \"source must not be a symlink\");","typeGuard":null,"tryCatchPattern":"if let Err(e) = retire_legacy_audit_dir(&home, &principal_home.audit_dir()) {\n    panic!(\"retire audit source: {e}\");\n}","preventionTips":["Surface the underlying error (unwrap_or_else + panic!) so the refusing validation rule is visible.","Keep retirement tests on the default principal unless testing the non-default rejection path explicitly.","After refactors of redirect detection, re-check that plain directories are not misclassified as symlinks.","Verify migrations_dir is writable since retirement records a marker there."],"tags":["rust","migration","audit","test-panic"],"backgroundTag":"invalid-state-transition","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"}