{"record":{"id":"a1651b82e04976c1","repo":"Hmbown/CodeWhale","slug":"only-codewhale-managed-skills-can-be-trusted-mutation","errorCode":null,"errorMessage":"only Codewhale managed skills can be trusted","messagePattern":"only Codewhale managed skills can be trusted","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/skills/mutation.rs","lineNumber":978,"sourceCode":"        scope,\n        safe_target_path: safe_display_path(&path, Some(ctx.workspace), ctx.home),\n        before_digest: before,\n        after_digest: None,\n        outcome: SkillMutationOutcome::Removed,\n    })\n}\n\nfn trust_skill(\n    skill_id: AuditedSkillId,\n    expected_digest: String,\n    ctx: &MutationContext<'_>,\n) -> Result<SkillMutationReceipt> {\n    let (skill, path) = find_audited_skill(ctx, &skill_id)?;\n    if !skill.root.is_writable_owned() {\n        bail!(\"refusing to trust skill outside Codewhale-owned roots\");\n    }\n    if skill.source_kind != SkillSourceKind::CodeWhaleManaged {\n        bail!(\"only Codewhale managed skills can be trusted\");\n    }\n    validate_owned_skill_path(ctx, &skill, &path)?;\n    let before = verify_expected_digest(&path, Some(&expected_digest))?;\n    validate_owned_skill_path(ctx, &skill, &path)?;\n    write_trust_v2(&path, &expected_digest)?;\n    let scope = match skill.root.kind {\n        SkillRootKind::CodeWhaleProject => SkillScope::Project,\n        SkillRootKind::CodeWhaleGlobal => SkillScope::Global,\n        _ => SkillScope::Logical,\n    };\n    Ok(SkillMutationReceipt {\n        action: SkillActionKind::Trust,\n        name: skill_id.canonical_name,\n        scope,\n        safe_target_path: safe_display_path(&path, Some(ctx.workspace), ctx.home),\n        before_digest: before.clone(),\n        after_digest: before,\n        outcome: SkillMutationOutcome::Trusted,","sourceCodeStart":960,"sourceCodeEnd":996,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/skills/mutation.rs#L960-L996","documentation":"trust_skill() only trusts skills whose source_kind is SkillSourceKind::CodeWhaleManaged. Skills from other sources (user-authored, imported) cannot receive a managed trust v2 record, because the trust record's digest binding assumes Codewhale-managed lifecycle. The root-ownership check passes before this check fires.","triggerScenarios":"Calling trust_skill on a skill that resides in an owned writable root but was not created/installed by Codewhale (source_kind != CodeWhaleManaged), e.g. a hand-copied skill directory inside the managed skills folder.","commonSituations":"A developer manually copies a skill directory into the Codewhale skills directory and then tries to trust it programmatically; migration/import tools drop skills in place without setting the managed source flag.","solutions":["Install the skill through a Codewhale-managed flow so it is registered with source_kind CodeWhaleManaged","Add/repair the skill's managed-source metadata (registration entry) rather than trusting it as-is","If the skill should remain external, use whatever external-skill trust path the product offers instead of trust_skill"],"exampleFix":"// before\nctx.trust_skill(hand_copied_skill_id, digest)?;\n// after\nlet skill = ctx.find_audited_skill(&skill_id)?;\nif skill.source_kind != SkillSourceKind::CodeWhaleManaged {\n    ctx.install_skill(&skill.path)?; // register as managed first\n}\nctx.trust_skill(skill_id, digest)?;","handlingStrategy":"validation","validationCode":"ensure!(matches!(skill.source_kind, SkillSourceKind::CodeWhaleManaged), \"install the skill through Codewhale before trusting\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Install skills via managed flows so source_kind is set correctly","After manual copies into the skills dir, run the re-register/import flow","Audit skills with unexpected source_kind values periodically"],"tags":["rust","skills","trust","validation"],"backgroundTag":"unsupported-operation","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}