{"record":{"id":"4a79f2f5085e55df","repo":"affaan-m/ECC","slug":"nasiko-uninstall-requires-explicit-yes-consent","errorCode":null,"errorMessage":"Nasiko uninstall requires explicit --yes consent.","messagePattern":"Nasiko uninstall requires explicit --yes consent\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/nasiko-release.js","lineNumber":435,"sourceCode":"    const metadata = { version, platform: release.os, architecture: release.arch, manifestDigest: release.manifestDigest, artifactDigest: layer.digest, binaryDigest: release.binaryDigest, installedPath: destination, license: release.license, sourceUrl: release.sourceUrl };\n    (dependencies.writeMetadata || writeMetadataExclusive)(metadataPath, metadata);\n    metadataOwned = true;\n    return { ...plan, dryRun: false, installed: true, reused: false, artifactDigest: layer.digest };\n  } catch (error) {\n    if (metadataOwned) fs.rmSync(metadataPath, { force: true });\n    if (destinationOwned) fs.rmSync(destination, { force: true });\n    throw error;\n  } finally { releaseLock(); }\n}\n\nfunction uninstallNasiko(options = {}, dependencies = {}) {\n  const version = options.version || 'v0.1.0';\n  const release = getQualifiedRelease(version, dependencies.platform || process.platform, dependencies.arch || process.arch);\n  const installDirectory = validateInstallDirectory(options.installDir || defaultInstallDirectory(release, dependencies.environment || process.env, dependencies.homeDirectory || os.homedir()));\n  const destination = path.join(installDirectory, release.binaryName);\n  const plan = { dryRun: Boolean(options.dryRun), version, destination };\n  if (options.dryRun) return plan;\n  if (!options.yes) throw new Error('Nasiko uninstall requires explicit --yes consent.');\n  if (!fs.existsSync(installDirectory)) return { ...plan, dryRun: false, removed: false };\n  assertPrivateInstallDirectory(installDirectory);\n  const releaseLock = acquireLifecycleLock(installDirectory);\n  const metadataPath = metadataPathFor(destination);\n  const suffix = `${process.pid}-${crypto.randomBytes(6).toString('hex')}`;\n  const binaryTombstone = `${destination}.remove-${suffix}`;\n  const metadataTombstone = `${metadataPath}.remove-${suffix}`;\n  let binaryStaged = false;\n  let metadataStaged = false;\n  const rename = dependencies.rename || fs.renameSync;\n  const remove = dependencies.remove || (target => fs.rmSync(target));\n  try {\n    const status = (dependencies.inspectInstalled || inspectInstalledNasiko)(destination);\n    if (!status.installed) return { ...plan, dryRun: false, removed: false };\n    if (!status.qualified || status.version !== version) throw new Error('Refusing to remove an unqualified or modified Nasiko executable.');\n    rename(destination, binaryTombstone);\n    binaryStaged = true;\n    rename(metadataPath, metadataTombstone);","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/nasiko-release.js#L417-L453","documentation":"uninstallNasiko is a destructive operation (removes the Nasiko binary and its receipt), so it demands explicit --yes consent (options.yes === true). Without it, the function throws before touching the filesystem, even if the binary exists.","triggerScenarios":"Calling uninstallNasiko({ ... }) without options.yes set and without options.dryRun. Any programmatic or CLI invocation lacking the consent flag.","commonSituations":"Scripts automating Nasiko cleanup that forgot the --yes flag; CI jobs calling the uninstall API; users running the uninstall command non-interactively.","solutions":["Pass { yes: true } (or the --yes CLI flag) to uninstallNasiko to confirm removal.","Run with { dryRun: true } first to inspect the plan, then re-run with --yes.","Add --yes to your automation script for non-interactive environments (CI), acknowledging the deletion.","Guard the call behind an interactive prompt in your wrapper tool before forwarding --yes."],"exampleFix":"// before\nawait uninstallNasiko({ version: 'v0.1.0' }); // throws\n// after\nawait uninstallNasiko({ version: 'v0.1.0', yes: true });","handlingStrategy":"validation","validationCode":"function assertUninstallConsent(options) {\n  if (!options.dryRun && options.yes !== true) {\n    throw new Error('uninstall requires --yes');\n  }\n}","typeGuard":"function hasConsent(options) {\n  return typeof options === 'object' && options !== null && options.yes === true;\n}","tryCatchPattern":"try {\n  await uninstallNasiko({ version, yes: true });\n} catch (e) {\n  if (e.message.includes('explicit --yes consent')) {\n    console.error('Re-run with --yes to confirm removal');\n  } else throw e;\n}","preventionTips":["Always pass yes: true in automation that intends real deletion","Use dryRun: true to preview the plan before consenting","Gate the --yes flag behind an interactive confirmation in wrapper tools","Never default yes to true in shared scripts"],"tags":["cli","consent","uninstall"],"backgroundTag":"missing-required-flag","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}